From c48e4ec4c632b0e2f5188b83463742a3703e26da Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:42:49 +0200 Subject: [PATCH] Feature/improve usage of portfolio calculator in holding endpoint (#3727) * Improve usage of portfolio calculator --- .../src/app/portfolio/portfolio.service.ts | 65 +++++++++---------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 01dd55112..0cd602046 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -602,14 +602,7 @@ export class PortfolioService { userId }); - const orders = activities.filter(({ SymbolProfile }) => { - return ( - SymbolProfile.dataSource === aDataSource && - SymbolProfile.symbol === aSymbol - ); - }); - - if (orders.length <= 0) { + if (activities.length === 0) { return { accounts: [], averagePrice: undefined, @@ -646,10 +639,8 @@ export class PortfolioService { ]); const portfolioCalculator = this.calculatorFactory.createCalculator({ + activities, userId, - activities: orders.filter((order) => { - return ['BUY', 'DIVIDEND', 'ITEM', 'SELL'].includes(order.type); - }), calculationType: PerformanceCalculationType.TWR, currency: userCurrency }); @@ -659,8 +650,8 @@ export class PortfolioService { const { positions } = await portfolioCalculator.getSnapshot(); - const position = positions.find(({ symbol }) => { - return symbol === aSymbol; + const position = positions.find(({ dataSource, symbol }) => { + return dataSource === aDataSource && symbol === aSymbol; }); if (position) { @@ -673,14 +664,22 @@ export class PortfolioService { firstBuyDate, marketPrice, quantity, + symbol, tags, timeWeightedInvestment, timeWeightedInvestmentWithCurrencyEffect, transactionCount } = position; + const activitiesOfPosition = activities.filter(({ SymbolProfile }) => { + return ( + SymbolProfile.dataSource === dataSource && + SymbolProfile.symbol === symbol + ); + }); + const accounts: PortfolioHoldingDetail['accounts'] = uniqBy( - orders.filter(({ Account }) => { + activitiesOfPosition.filter(({ Account }) => { return Account; }), 'Account.id' @@ -715,8 +714,8 @@ export class PortfolioService { ); const historicalDataArray: HistoricalDataItem[] = []; - let maxPrice = Math.max(orders[0].unitPrice, marketPrice); - let minPrice = Math.min(orders[0].unitPrice, marketPrice); + let maxPrice = Math.max(activitiesOfPosition[0].unitPrice, marketPrice); + let minPrice = Math.min(activitiesOfPosition[0].unitPrice, marketPrice); if (historicalData[aSymbol]) { let j = -1; @@ -760,10 +759,10 @@ export class PortfolioService { } else { // Add historical entry for buy date, if no historical data available historicalDataArray.push({ - averagePrice: orders[0].unitPrice, + averagePrice: activitiesOfPosition[0].unitPrice, date: firstBuyDate, - marketPrice: orders[0].unitPrice, - quantity: orders[0].quantity + marketPrice: activitiesOfPosition[0].unitPrice, + quantity: activitiesOfPosition[0].quantity }); } @@ -773,7 +772,6 @@ export class PortfolioService { marketPrice, maxPrice, minPrice, - orders, SymbolProfile, tags, transactionCount, @@ -805,6 +803,7 @@ export class PortfolioService { ]?.toNumber(), netPerformanceWithCurrencyEffect: position.netPerformanceWithCurrencyEffectMap?.['max']?.toNumber(), + orders: activitiesOfPosition, quantity: quantity.toNumber(), value: this.exchangeRateDataService.toCurrency( quantity.mul(marketPrice ?? 0).toNumber(), @@ -862,7 +861,6 @@ export class PortfolioService { marketPrice, maxPrice, minPrice, - orders, SymbolProfile, accounts: [], averagePrice: 0, @@ -882,6 +880,7 @@ export class PortfolioService { netPerformancePercent: undefined, netPerformancePercentWithCurrencyEffect: undefined, netPerformanceWithCurrencyEffect: undefined, + orders: [], quantity: 0, tags: [], transactionCount: undefined, @@ -912,7 +911,7 @@ export class PortfolioService { userCurrency: this.getUserCurrency() }); - if (activities?.length <= 0) { + if (activities.length === 0) { return { hasErrors: false, positions: [] @@ -1037,14 +1036,12 @@ export class PortfolioService { dateRange = 'max', filters, impersonationId, - portfolioCalculator, userId, withExcludedAccounts = false }: { dateRange?: DateRange; filters?: Filter[]; impersonationId: string; - portfolioCalculator?: PortfolioCalculator; userId: string; withExcludedAccounts?: boolean; }): Promise { @@ -1089,7 +1086,7 @@ export class PortfolioService { userId }); - if (accountBalanceItems?.length <= 0 && activities?.length <= 0) { + if (accountBalanceItems.length === 0 && activities.length === 0) { return { chart: [], firstOrderDate: undefined, @@ -1106,16 +1103,14 @@ export class PortfolioService { }; } - portfolioCalculator = - portfolioCalculator ?? - this.calculatorFactory.createCalculator({ - accountBalanceItems, - activities, - filters, - userId, - calculationType: PerformanceCalculationType.TWR, - currency: userCurrency - }); + const portfolioCalculator = this.calculatorFactory.createCalculator({ + accountBalanceItems, + activities, + filters, + userId, + calculationType: PerformanceCalculationType.TWR, + currency: userCurrency + }); const { errors, hasErrors, historicalData } = await portfolioCalculator.getSnapshot();