declare class Investments {}

declare enum DayCountDes {
    ActualActual = 0,
    Actual360 = 1,
    Actual365 = 2,
    Thirty360 = 3,
    ISMAThirty360 = 4,
    ISMAThirty360NONEOM = 5,
}

interface Valuation {
    gav: number,
    accrued_interest: number,
    quantity: number,
    avg_cost: number,
    cost: number,
    market_value: number,
}

declare enum CashType {
    Trade = 0,
    Interest = 1,
    Called = 2,
    Sinkable = 3,
    Commission = 4,
}

interface Cashflow {
    cash_date: string,
    cash_type: CashType,
    currency: Currency,
    amount: number,
}

declare enum CalcType {
    Normal = 0,
    AustraliaExDiv = 23,
}

declare class Deposit extends Investments {
    constructor(basis: DayCountDes);
    valuation(date: string, trades: Trades): Valuation;
    cashflow(date: string, trades: Trades): Array<Cashflow>;
}

declare class Repo extends Investments {
    constructor(basis: DayCountDes, quantity: number);
    valuation(date: string, trades: Trades): Valuation;
    cashflow(date: string, trades: Trades): Array<Cashflow>;
}

declare enum FxType {
    Spot = 0,
    Forward = 1,
}

declare enum Currency {
    Default = 99,
    HKD = 0,
    USD = 1,
    AUD = 2,
    EUR = 3,
    GBP = 4,
    NZD = 5,
    CHF = 6,
    CNH = 7,
    CNY = 8,
    JPY = 9,
    SGD = 10,
}

declare class Fx extends Investments {
    constructor(
        fx_type: FxType,
        trade_currency: Currency,
        target_currency: Currency,
        base_currency: Currency,
        trade_quantity: number,
        target_quantity: number,
        mid_vd: number,
    );
    valuation(): Valuation;
    cashflow(date: string, trades: Trades): Array<Cashflow>;
}

declare class Future extends Investments {
    constructor(commission?: number);
    valuation(price: number, trades: Trades): Valuation;
    cashflow(trades: Trades): Array<Cashflow>;
}

declare class CDS extends Investments {
    constructor(
        start_date: string,
        frequency: number,
        basis: DayCountDes,
    )
    valuation(date: string, price: number, trades: Trades): Valuation;
    cashflow(date: string, trades: Trades): Array<Cashflow>;
}

declare class Fund extends Investments {
    constructor()
    valuation(date: string, price: number, trades: Trades): Valuation;
    cashflow(date: string, trades: Trades): Array<Cashflow>;
}

declare class Bond extends Investments {
    constructor(
        issue_date: string,
        interest_accrual_date: string,
        first_cpn_date: string,
        maturity: string,
        frequency: number,
        basis: DayCountDes,
        cpn_rate: number,
        calc_type?: number,
    );
    calendars(): Array<string>;
    accrued(date: string, quantity: number): number;
    valuation(date: string, price: number, trades: Trades, actions?: Actions): Valuation;
    cashflow(date: string, trades: Trades, actions?: Actions, ex_dvd_days?: number): Array<Cashflow>;
    discount_rate_to_price(date: string, rate: number): number;
}

declare enum AssetType {
    Bond = 0,
    Future = 1,
    Deposit = 2,
    Fx = 3,
    Repo = 4,
    CDS = 5,
    FUND = 6,
}

declare enum ActionType {
    Buy = 0,
    Sell = 1,
    ModifyRate = 2,
    ChangePrincipal = 3,
    RepoReSize = 4,
    RepoReRate = 5,
}

interface Trade {
    action: ActionType,
    currency?: Currency,
    quantity?: number,
    price?: number,
    rate?: number,
    contract_size?: number,
    trade_date: string,
    settle_date: string,
}

declare class Trades {
    constructor(name: string, asset_type: AssetType);
    add(trade: Trade): void;
}

declare enum AssetActionType {
    Called = 0, // 被召回
    Sinking = 1, // 被赎回
    Pay = 2, // 每单位份额支付一定金额
    ChangeCPN = 3, // 修改利率
    Defaulted = 4,
    CancelDefaulted = 5,
    FlatTRADING = 6,
    CancelFlatTRADING = 7,
}

interface ChangeCPNAction {
    action: AssetActionType,
    action_date: string,
    cpn: number,
}

interface DefaultedAction {
    action: AssetActionType,
    action_date: string,
}

interface CalledAction {
    action: AssetActionType,
    action_date: string,
    call_price: number,
    call_ratio: number,
}

interface SinkableAction {
    action: AssetActionType,
    action_date: string,
    sinking_ratio: number,
}

interface PayAction {
    action: AssetActionType,
    action_date: string,
    amount: number,
    unit: number,
}

type Action = ChangeCPNAction | DefaultedAction | CalledAction | SinkableAction | PayAction;

declare class Actions {
    constructor(name: string, asset_type: AssetType);
    add(trade: Action): void;
}

declare const Utils: {
    day_counter: (begin_date: string, target_date: string, basis: number) => number;
};
export {
    Utils,
    Bond,
    Future,
    Fx,
    Deposit,
    Repo,
    Trades,
    DayCountDes,
    AssetType,
    ActionType,
    Actions,
    AssetActionType,
    CashType,
    CalcType,
    FxType,
    Currency,
    CDS,
    Fund,
};

