diff --git a/src/app/components/Portfolio/Report/FeesComponent.tsx b/src/app/components/Portfolio/Report/FeesComponent.tsx index 23eae95..cc87f32 100644 --- a/src/app/components/Portfolio/Report/FeesComponent.tsx +++ b/src/app/components/Portfolio/Report/FeesComponent.tsx @@ -33,6 +33,7 @@ const Fees = ({ theReports, ..._rest }: Props): React.ReactNode => { {report.year}-{report.month} + ))} diff --git a/src/app/components/Portfolio/Report/PnLsComponent.tsx b/src/app/components/Portfolio/Report/PnLsComponent.tsx index e6309dd..4552454 100644 --- a/src/app/components/Portfolio/Report/PnLsComponent.tsx +++ b/src/app/components/Portfolio/Report/PnLsComponent.tsx @@ -8,8 +8,10 @@ type Props = { theReports: ReportEntry[] }; type PnlCallback = (ReportEntry) => number; const PnLs: Record = { - ["Equity"]: (tradesSummary: TradesSummary) => tradesSummary.stocksPnLInBase, - ["Options"]: (tradesSummary: TradesSummary) => tradesSummary.optionsPnLInBase, + ["Stocks"]: (tradesSummary: TradesSummary) => tradesSummary.stocksPnLInBase, + ["Equity Options"]: (tradesSummary: TradesSummary) => tradesSummary.optionsPnLInBase, + ["Futures"]: (tradesSummary: TradesSummary) => tradesSummary.futuresPnLInBase, + ["Futures Options"]: (tradesSummary: TradesSummary) => tradesSummary.fopPnlInBase, ["Bonds"]: (tradesSummary: TradesSummary) => tradesSummary.bondPnLInBase, }; diff --git a/src/bots/index.ts b/src/bots/index.ts index 1c700f7..1ea37fb 100644 --- a/src/bots/index.ts +++ b/src/bots/index.ts @@ -799,7 +799,7 @@ export class ITradingBot extends EventEmitter { const contract_values = { // Contract part of the option conId: ibContract.conId!, // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion - secType: ContractType.Option, + secType: ibContract.secType! as ContractType, symbol: ibContract.localSymbol!, // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion currency: ibContract.currency!, // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion diff --git a/src/models/contract.types.ts b/src/models/contract.types.ts index b078cb7..1f56193 100644 --- a/src/models/contract.types.ts +++ b/src/models/contract.types.ts @@ -6,7 +6,7 @@ export const ContractType = { Bag: "BAG", Cash: "CASH", Future: "FUT", - FutureOption: "FOP", // maybe OPT + FutureOption: "FOP", Index: "IND", Bond: "BOND", } as const; diff --git a/src/models/option_contract.model.ts b/src/models/option_contract.model.ts index 6cc45df..fcfe74b 100644 --- a/src/models/option_contract.model.ts +++ b/src/models/option_contract.model.ts @@ -19,6 +19,7 @@ export class OptionContract extends Model< // updatedAt can be undefined during creation declare updatedAt: CreationOptional; + /** Base contract part of this option */ @BelongsTo(() => Contract, "id") declare contract: Contract; diff --git a/src/models/option_statement.model.ts b/src/models/option_statement.model.ts index ae2c208..3b695cd 100644 --- a/src/models/option_statement.model.ts +++ b/src/models/option_statement.model.ts @@ -43,10 +43,11 @@ export class OptionStatement extends Model< @Column({ type: DataType.SMALLINT, defaultValue: 0 }) declare status: number; - /** related Contract */ + /** Base contract part of the option */ declare contract_id: ForeignKey; @BelongsTo(() => Contract, "contract_id") declare contract: Contract; + /** Option part of the option */ @BelongsTo(() => OptionContract, "contract_id") declare option: OptionContract; } diff --git a/src/routers/reports.types.ts b/src/routers/reports.types.ts index 5438613..7f0374a 100644 --- a/src/routers/reports.types.ts +++ b/src/routers/reports.types.ts @@ -44,7 +44,9 @@ export type FeesSummary = { */ export type TradesSummary = { stocksPnLInBase: number; + futuresPnLInBase: number; optionsPnLInBase: number; + fopPnlInBase: number; bondPnLInBase: number; totalPnL: number; }; diff --git a/src/routers/statements.types.ts b/src/routers/statements.types.ts index 6dc6d15..7d54862 100644 --- a/src/routers/statements.types.ts +++ b/src/routers/statements.types.ts @@ -13,6 +13,7 @@ export type StatementUnderlyingEntry = { }; export type StatementUnderlyingOption = StatementUnderlyingEntry & { + // underlying: StatementUnderlyingEntry; lastTradeDate: string; strike: number; callOrPut: OptionType; @@ -26,7 +27,7 @@ export type BaseStatement = { currency: string; fxRateToBase: number; amount: number; - // underlying: StatementUnderlyingEntry | undefined; + underlying: StatementUnderlyingEntry | undefined; trade_id: number | null; description: string; }; diff --git a/src/routers/statements.utils.ts b/src/routers/statements.utils.ts index 303a090..6bbb455 100644 --- a/src/routers/statements.utils.ts +++ b/src/routers/statements.utils.ts @@ -25,6 +25,7 @@ export const statementModelToStatementEntry = (item: Statement): Promise { const option: StatementUnderlyingOption = { - id: thisStatement!.contract_id, - secType: ContractType.Option, + id: thisStatement!.option.id, + secType: thisStatement!.contract.secType, symbol: thisStatement!.contract.symbol, + currency: item.currency, + name: thisStatement!.contract.name, + price: thisStatement!.contract.price, + // underlying: { + // id: thisStatement!.option.stock.id, + // secType: thisStatement!.option.stock.secType, + // symbol: thisStatement!.option.stock.symbol, + // currency: thisStatement!.option.stock.currency, + // name: thisStatement!.option.stock.name, + // price: thisStatement!.option.stock.price, + // }, + // underlying: { + // id: item.stock.id, + // secType: item.stock.secType, + // symbol: item.stock.symbol, + // currency: item.stock.currency, + // name: item.stock.name, + // price: item.stock.price, + // }, strike: thisStatement!.option.strike, lastTradeDate: thisStatement!.option.lastTradeDate, callOrPut: thisStatement!.option.callOrPut, multiplier: thisStatement!.option.multiplier, - currency: item.currency, - name: thisStatement!.contract.name, - price: thisStatement!.contract.price, }; return { statementType: StatementTypes.OptionStatement, @@ -197,7 +214,14 @@ export const prepareReport = (portfolio: Portfolio): Promise => { interestsDetails: [], feesSummary: { totalAmountInBase: 0 }, feesDetails: [], - tradesSummary: { stocksPnLInBase: 0, optionsPnLInBase: 0, bondPnLInBase: 0, totalPnL: 0 }, + tradesSummary: { + stocksPnLInBase: 0, + optionsPnLInBase: 0, + futuresPnLInBase: 0, + fopPnlInBase: 0, + bondPnLInBase: 0, + totalPnL: 0, + }, tradesDetails: [], otherDetails: [], }; @@ -262,14 +286,26 @@ export const prepareReport = (portfolio: Portfolio): Promise => { break; case StatementTypes.EquityStatement: - report.tradesSummary.stocksPnLInBase += statement.pnl * statement.fxRateToBase; + switch (statement.underlying.secType) { + case ContractType.Stock: + report.tradesSummary.stocksPnLInBase += statement.pnl * statement.fxRateToBase; + break; + case ContractType.Future: + report.tradesSummary.futuresPnLInBase += statement.pnl * statement.fxRateToBase; + break; + } report.tradesSummary.totalPnL += statement.pnl * statement.fxRateToBase; report.tradesDetails.push(statement); break; case StatementTypes.OptionStatement: + if ( + statement.option.secType == ContractType.FutureOption || + statement.underlying?.secType == ContractType.Future + ) + report.tradesSummary.fopPnlInBase += statement.pnl * statement.fxRateToBase; + else report.tradesSummary.optionsPnLInBase += statement.pnl * statement.fxRateToBase; report.tradesSummary.totalPnL += statement.pnl * statement.fxRateToBase; - report.tradesSummary.optionsPnLInBase += statement.pnl * statement.fxRateToBase; report.tradesDetails.push(statement); break;