From bc6e9a8b68534d4f0f70d692e144e7fc8a42884d Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 23 Mar 2023 19:23:31 +0100 Subject: [PATCH] Bugfix/fix total amount calculation in portfolio evolution chart (#1799) * Fix total amount calculation * Update changelog --- CHANGELOG.md | 4 ++ ...folio-calculator-novn-buy-and-sell.spec.ts | 2 +- .../src/app/portfolio/portfolio-calculator.ts | 66 +++++++++++++------ 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43ecb213..9f45e8fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated the URL of the Ghostfolio Slack channel - Upgraded `prisma` from version `4.10.1` to `4.11.0` +### Fixed + +- Fixed the total amount calculation in the portfolio evolution chart + ## 1.246.0 - 2023-03-18 ### Added diff --git a/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell.spec.ts index e4101610..feed5923 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -86,7 +86,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentage: 13.100263852242744, netPerformance: 19.86, totalInvestment: 0, - value: 19.86 + value: 0 }); expect(currentPositions).toEqual({ diff --git a/apps/api/src/app/portfolio/portfolio-calculator.ts b/apps/api/src/app/portfolio/portfolio-calculator.ts index 06c61716..e11f1ed1 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator.ts @@ -235,7 +235,7 @@ export class PortfolioCalculator { } } - const netPerformanceValuesBySymbol: { + const currentValuesBySymbol: { [symbol: string]: { [date: string]: Big }; } = {}; @@ -247,21 +247,31 @@ export class PortfolioCalculator { [symbol: string]: { [date: string]: Big }; } = {}; + const netPerformanceValuesBySymbol: { + [symbol: string]: { [date: string]: Big }; + } = {}; + + const totalCurrentValues: { [date: string]: Big } = {}; const totalNetPerformanceValues: { [date: string]: Big } = {}; const totalInvestmentValues: { [date: string]: Big } = {}; const maxTotalInvestmentValues: { [date: string]: Big } = {}; for (const symbol of Object.keys(symbols)) { - const { investmentValues, maxInvestmentValues, netPerformanceValues } = - this.getSymbolMetrics({ - end, - marketSymbolMap, - start, - step, - symbol, - isChartMode: true - }); + const { + currentValues, + investmentValues, + maxInvestmentValues, + netPerformanceValues + } = this.getSymbolMetrics({ + end, + marketSymbolMap, + start, + step, + symbol, + isChartMode: true + }); + currentValuesBySymbol[symbol] = currentValues; netPerformanceValuesBySymbol[symbol] = netPerformanceValues; investmentValuesBySymbol[symbol] = investmentValues; maxInvestmentValuesBySymbol[symbol] = maxInvestmentValues; @@ -271,6 +281,15 @@ export class PortfolioCalculator { const dateString = format(currentDate, DATE_FORMAT); for (const symbol of Object.keys(netPerformanceValuesBySymbol)) { + totalCurrentValues[dateString] = + totalCurrentValues[dateString] ?? new Big(0); + + if (currentValuesBySymbol[symbol]?.[dateString]) { + totalCurrentValues[dateString] = totalCurrentValues[dateString].add( + currentValuesBySymbol[symbol][dateString] + ); + } + totalNetPerformanceValues[dateString] = totalNetPerformanceValues[dateString] ?? new Big(0); @@ -283,15 +302,15 @@ export class PortfolioCalculator { totalInvestmentValues[dateString] = totalInvestmentValues[dateString] ?? new Big(0); - maxTotalInvestmentValues[dateString] = - maxTotalInvestmentValues[dateString] ?? new Big(0); - if (investmentValuesBySymbol[symbol]?.[dateString]) { totalInvestmentValues[dateString] = totalInvestmentValues[ dateString ].add(investmentValuesBySymbol[symbol][dateString]); } + maxTotalInvestmentValues[dateString] = + maxTotalInvestmentValues[dateString] ?? new Big(0); + if (maxInvestmentValuesBySymbol[symbol]?.[dateString]) { maxTotalInvestmentValues[dateString] = maxTotalInvestmentValues[ dateString @@ -313,9 +332,7 @@ export class PortfolioCalculator { netPerformanceInPercentage, netPerformance: totalNetPerformanceValues[date].toNumber(), totalInvestment: totalInvestmentValues[date].toNumber(), - value: totalInvestmentValues[date] - .plus(totalNetPerformanceValues[date]) - .toNumber() + value: totalCurrentValues[date].toNumber() }; }); } @@ -906,12 +923,16 @@ export class PortfolioCalculator { if (orders.length <= 0) { return { + currentValues: {}, + grossPerformance: new Big(0), + grossPerformancePercentage: new Big(0), hasErrors: false, initialValue: new Big(0), + investmentValues: {}, + maxInvestmentValues: {}, netPerformance: new Big(0), netPerformancePercentage: new Big(0), - grossPerformance: new Big(0), - grossPerformancePercentage: new Big(0) + netPerformanceValues: {} }; } @@ -946,6 +967,7 @@ export class PortfolioCalculator { let grossPerformanceFromSells = new Big(0); let initialValue: Big; let investmentAtStartDate: Big; + const currentValues: { [date: string]: Big } = {}; const investmentValues: { [date: string]: Big } = {}; const maxInvestmentValues: { [date: string]: Big } = {}; let lastAveragePrice = new Big(0); @@ -1164,6 +1186,7 @@ export class PortfolioCalculator { } if (isChartMode && i > indexOfStartOrder) { + currentValues[order.date] = valueOfInvestment; netPerformanceValues[order.date] = grossPerformance .minus(grossPerformanceAtStartDate) .minus(fees.minus(feesAtStartDate)); @@ -1261,15 +1284,16 @@ export class PortfolioCalculator { } return { - initialValue, + currentValues, grossPerformancePercentage, + initialValue, investmentValues, maxInvestmentValues, netPerformancePercentage, netPerformanceValues, + grossPerformance: totalGrossPerformance, hasErrors: totalUnits.gt(0) && (!initialValue || !unitPriceAtEndDate), - netPerformance: totalNetPerformance, - grossPerformance: totalGrossPerformance + netPerformance: totalNetPerformance }; }