From ca2e748c56581f4d2bd3fb0588b0d5554506c50e Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 6 Apr 2024 20:03:16 +0200 Subject: [PATCH] Bugfix/add missing tags in portfolio calculator (#3243) * Add missing tags * Update changelog --- CHANGELOG.md | 4 ++++ .../portfolio/calculator/portfolio-calculator.ts | 14 ++++++++++---- ...tor-baln-buy-and-sell-in-two-activities.spec.ts | 1 + .../portfolio-calculator-baln-buy-and-sell.spec.ts | 1 + .../twr/portfolio-calculator-baln-buy.spec.ts | 1 + ...alculator-btcusd-buy-and-sell-partially.spec.ts | 2 +- .../twr/portfolio-calculator-googl-buy.spec.ts | 2 +- ...folio-calculator-msft-buy-with-dividend.spec.ts | 2 +- ...-calculator-novn-buy-and-sell-partially.spec.ts | 1 + .../portfolio-calculator-novn-buy-and-sell.spec.ts | 1 + apps/api/src/app/portfolio/portfolio.service.ts | 14 ++++---------- 11 files changed, 26 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c20da8462..bf0eeb0fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the url validation in the create and update platform endpoint - Improved the language localization for German (`de`) +### Fixed + +- Fixed the missing tags in the portfolio calculations + ## 2.70.0 - 2024-04-02 ### Added diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 48fcaf343..488f9ce99 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -29,7 +29,7 @@ import { max, subDays } from 'date-fns'; -import { last, uniq } from 'lodash'; +import { last, uniq, uniqBy } from 'lodash'; export abstract class PortfolioCalculator { protected static readonly ENABLE_LOGGING = false; @@ -57,9 +57,10 @@ export abstract class PortfolioCalculator { this.currentRateService = currentRateService; this.exchangeRateDataService = exchangeRateDataService; this.orders = activities.map( - ({ date, fee, quantity, SymbolProfile, type, unitPrice }) => { + ({ date, fee, quantity, SymbolProfile, tags = [], type, unitPrice }) => { return { SymbolProfile, + tags, type, date: format(date, DATE_FORMAT), fee: new Big(fee), @@ -711,17 +712,17 @@ export abstract class PortfolioCalculator { currentTransactionPointItem = { investment, - tags, averagePrice: newQuantity.gt(0) ? investment.div(newQuantity) : new Big(0), currency: SymbolProfile.currency, dataSource: SymbolProfile.dataSource, dividend: new Big(0), - fee: fee.plus(oldAccumulatedSymbol.fee), + fee: oldAccumulatedSymbol.fee.plus(fee), firstBuyDate: oldAccumulatedSymbol.firstBuyDate, quantity: newQuantity, symbol: SymbolProfile.symbol, + tags: oldAccumulatedSymbol.tags.concat(tags), transactionCount: oldAccumulatedSymbol.transactionCount + 1 }; } else { @@ -740,6 +741,11 @@ export abstract class PortfolioCalculator { }; } + currentTransactionPointItem.tags = uniqBy( + currentTransactionPointItem.tags, + 'id' + ); + symbols[SymbolProfile.symbol] = currentTransactionPointItem; const items = lastTransactionPoint?.items ?? []; diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts index ee71a1fb3..b936d21a9 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts @@ -164,6 +164,7 @@ describe('PortfolioCalculator', () => { marketPriceInBaseCurrency: 148.9, quantity: new Big('0'), symbol: 'BALN.SW', + tags: [], timeWeightedInvestment: new Big('285.80000000000000396627'), timeWeightedInvestmentWithCurrencyEffect: new Big( '285.80000000000000396627' diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts index 69078be7c..d1557bc12 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts @@ -149,6 +149,7 @@ describe('PortfolioCalculator', () => { marketPriceInBaseCurrency: 148.9, quantity: new Big('0'), symbol: 'BALN.SW', + tags: [], timeWeightedInvestment: new Big('285.8'), timeWeightedInvestmentWithCurrencyEffect: new Big('285.8'), transactionCount: 2, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts index b52aac68d..593503493 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts @@ -134,6 +134,7 @@ describe('PortfolioCalculator', () => { marketPriceInBaseCurrency: 148.9, quantity: new Big('2'), symbol: 'BALN.SW', + tags: [], timeWeightedInvestment: new Big('273.2'), timeWeightedInvestmentWithCurrencyEffect: new Big('273.2'), transactionCount: 1, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts index 420ba48f1..e3f351b28 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts @@ -166,7 +166,7 @@ describe('PortfolioCalculator', () => { ), quantity: new Big('1'), symbol: 'BTCUSD', - tags: undefined, + tags: [], timeWeightedInvestment: new Big('640.56763686131386861314'), timeWeightedInvestmentWithCurrencyEffect: new Big( '636.79469348020066587024' diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts index 5f33d771b..e7796b4d3 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts @@ -147,7 +147,7 @@ describe('PortfolioCalculator', () => { marketPriceInBaseCurrency: 103.10483, quantity: new Big('1'), symbol: 'GOOGL', - tags: undefined, + tags: [], timeWeightedInvestment: new Big('89.12'), timeWeightedInvestmentWithCurrencyEffect: new Big('82.329056'), transactionCount: 1, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts index a2c106784..49a07e73f 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -126,7 +126,7 @@ describe('PortfolioCalculator', () => { marketPriceInBaseCurrency: 331.83, quantity: new Big('1'), symbol: 'MSFT', - tags: undefined, + tags: [], transactionCount: 2 } ], diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts index 21e0bb499..2bfd6d865 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts @@ -148,6 +148,7 @@ describe('PortfolioCalculator', () => { marketPriceInBaseCurrency: 87.8, quantity: new Big('1'), symbol: 'NOVN.SW', + tags: [], timeWeightedInvestment: new Big('145.10285714285714285714'), timeWeightedInvestmentWithCurrencyEffect: new Big( '145.10285714285714285714' diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts index 28920ece7..be3f75dc2 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -175,6 +175,7 @@ describe('PortfolioCalculator', () => { marketPriceInBaseCurrency: 87.8, quantity: new Big('0'), symbol: 'NOVN.SW', + tags: [], timeWeightedInvestment: new Big('151.6'), timeWeightedInvestmentWithCurrencyEffect: new Big('151.6'), transactionCount: 2, diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 3b8a42d89..fc13ea8e6 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -63,8 +63,7 @@ import { DataSource, Order, Platform, - Prisma, - Tag + Prisma } from '@prisma/client'; import { Big } from 'big.js'; import { isUUID } from 'class-validator'; @@ -701,11 +700,8 @@ export class PortfolioService { ); }); - let tags: Tag[] = []; - if (orders.length <= 0) { return { - tags, accounts: [], averagePrice: undefined, dataProviderInfo: undefined, @@ -730,6 +726,7 @@ export class PortfolioService { orders: [], quantity: undefined, SymbolProfile: undefined, + tags: [], transactionCount: undefined, value: undefined }; @@ -741,16 +738,12 @@ export class PortfolioService { const portfolioCalculator = this.calculatorFactory.createCalculator({ activities: orders.filter((order) => { - tags = tags.concat(order.tags); - return ['BUY', 'DIVIDEND', 'ITEM', 'SELL'].includes(order.type); }), calculationType: PerformanceCalculationType.TWR, currency: userCurrency }); - tags = uniqBy(tags, 'id'); - const portfolioStart = portfolioCalculator.getStartDate(); const transactionPoints = portfolioCalculator.getTransactionPoints(); @@ -771,6 +764,7 @@ export class PortfolioService { firstBuyDate, marketPrice, quantity, + tags, timeWeightedInvestment, timeWeightedInvestmentWithCurrencyEffect, transactionCount @@ -947,7 +941,6 @@ export class PortfolioService { minPrice, orders, SymbolProfile, - tags, accounts: [], averagePrice: 0, dataProviderInfo: undefined, @@ -967,6 +960,7 @@ export class PortfolioService { netPerformancePercentWithCurrencyEffect: undefined, netPerformanceWithCurrencyEffect: undefined, quantity: 0, + tags: [], transactionCount: undefined, value: 0 };