Browse Source

Bugfix/add missing tags in portfolio calculator (#3243)

* Add missing tags

* Update changelog
pull/3248/head
Thomas Kaul 10 months ago
committed by GitHub
parent
commit
ca2e748c56
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      CHANGELOG.md
  2. 14
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  3. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts
  4. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts
  5. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts
  6. 2
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts
  7. 2
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts
  8. 2
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts
  9. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts
  10. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts
  11. 14
      apps/api/src/app/portfolio/portfolio.service.ts

4
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 url validation in the create and update platform endpoint
- Improved the language localization for German (`de`) - Improved the language localization for German (`de`)
### Fixed
- Fixed the missing tags in the portfolio calculations
## 2.70.0 - 2024-04-02 ## 2.70.0 - 2024-04-02
### Added ### Added

14
apps/api/src/app/portfolio/calculator/portfolio-calculator.ts

@ -29,7 +29,7 @@ import {
max, max,
subDays subDays
} from 'date-fns'; } from 'date-fns';
import { last, uniq } from 'lodash'; import { last, uniq, uniqBy } from 'lodash';
export abstract class PortfolioCalculator { export abstract class PortfolioCalculator {
protected static readonly ENABLE_LOGGING = false; protected static readonly ENABLE_LOGGING = false;
@ -57,9 +57,10 @@ export abstract class PortfolioCalculator {
this.currentRateService = currentRateService; this.currentRateService = currentRateService;
this.exchangeRateDataService = exchangeRateDataService; this.exchangeRateDataService = exchangeRateDataService;
this.orders = activities.map( this.orders = activities.map(
({ date, fee, quantity, SymbolProfile, type, unitPrice }) => { ({ date, fee, quantity, SymbolProfile, tags = [], type, unitPrice }) => {
return { return {
SymbolProfile, SymbolProfile,
tags,
type, type,
date: format(date, DATE_FORMAT), date: format(date, DATE_FORMAT),
fee: new Big(fee), fee: new Big(fee),
@ -711,17 +712,17 @@ export abstract class PortfolioCalculator {
currentTransactionPointItem = { currentTransactionPointItem = {
investment, investment,
tags,
averagePrice: newQuantity.gt(0) averagePrice: newQuantity.gt(0)
? investment.div(newQuantity) ? investment.div(newQuantity)
: new Big(0), : new Big(0),
currency: SymbolProfile.currency, currency: SymbolProfile.currency,
dataSource: SymbolProfile.dataSource, dataSource: SymbolProfile.dataSource,
dividend: new Big(0), dividend: new Big(0),
fee: fee.plus(oldAccumulatedSymbol.fee), fee: oldAccumulatedSymbol.fee.plus(fee),
firstBuyDate: oldAccumulatedSymbol.firstBuyDate, firstBuyDate: oldAccumulatedSymbol.firstBuyDate,
quantity: newQuantity, quantity: newQuantity,
symbol: SymbolProfile.symbol, symbol: SymbolProfile.symbol,
tags: oldAccumulatedSymbol.tags.concat(tags),
transactionCount: oldAccumulatedSymbol.transactionCount + 1 transactionCount: oldAccumulatedSymbol.transactionCount + 1
}; };
} else { } else {
@ -740,6 +741,11 @@ export abstract class PortfolioCalculator {
}; };
} }
currentTransactionPointItem.tags = uniqBy(
currentTransactionPointItem.tags,
'id'
);
symbols[SymbolProfile.symbol] = currentTransactionPointItem; symbols[SymbolProfile.symbol] = currentTransactionPointItem;
const items = lastTransactionPoint?.items ?? []; const items = lastTransactionPoint?.items ?? [];

1
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, marketPriceInBaseCurrency: 148.9,
quantity: new Big('0'), quantity: new Big('0'),
symbol: 'BALN.SW', symbol: 'BALN.SW',
tags: [],
timeWeightedInvestment: new Big('285.80000000000000396627'), timeWeightedInvestment: new Big('285.80000000000000396627'),
timeWeightedInvestmentWithCurrencyEffect: new Big( timeWeightedInvestmentWithCurrencyEffect: new Big(
'285.80000000000000396627' '285.80000000000000396627'

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts

@ -149,6 +149,7 @@ describe('PortfolioCalculator', () => {
marketPriceInBaseCurrency: 148.9, marketPriceInBaseCurrency: 148.9,
quantity: new Big('0'), quantity: new Big('0'),
symbol: 'BALN.SW', symbol: 'BALN.SW',
tags: [],
timeWeightedInvestment: new Big('285.8'), timeWeightedInvestment: new Big('285.8'),
timeWeightedInvestmentWithCurrencyEffect: new Big('285.8'), timeWeightedInvestmentWithCurrencyEffect: new Big('285.8'),
transactionCount: 2, transactionCount: 2,

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts

@ -134,6 +134,7 @@ describe('PortfolioCalculator', () => {
marketPriceInBaseCurrency: 148.9, marketPriceInBaseCurrency: 148.9,
quantity: new Big('2'), quantity: new Big('2'),
symbol: 'BALN.SW', symbol: 'BALN.SW',
tags: [],
timeWeightedInvestment: new Big('273.2'), timeWeightedInvestment: new Big('273.2'),
timeWeightedInvestmentWithCurrencyEffect: new Big('273.2'), timeWeightedInvestmentWithCurrencyEffect: new Big('273.2'),
transactionCount: 1, transactionCount: 1,

2
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'), quantity: new Big('1'),
symbol: 'BTCUSD', symbol: 'BTCUSD',
tags: undefined, tags: [],
timeWeightedInvestment: new Big('640.56763686131386861314'), timeWeightedInvestment: new Big('640.56763686131386861314'),
timeWeightedInvestmentWithCurrencyEffect: new Big( timeWeightedInvestmentWithCurrencyEffect: new Big(
'636.79469348020066587024' '636.79469348020066587024'

2
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts

@ -147,7 +147,7 @@ describe('PortfolioCalculator', () => {
marketPriceInBaseCurrency: 103.10483, marketPriceInBaseCurrency: 103.10483,
quantity: new Big('1'), quantity: new Big('1'),
symbol: 'GOOGL', symbol: 'GOOGL',
tags: undefined, tags: [],
timeWeightedInvestment: new Big('89.12'), timeWeightedInvestment: new Big('89.12'),
timeWeightedInvestmentWithCurrencyEffect: new Big('82.329056'), timeWeightedInvestmentWithCurrencyEffect: new Big('82.329056'),
transactionCount: 1, transactionCount: 1,

2
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts

@ -126,7 +126,7 @@ describe('PortfolioCalculator', () => {
marketPriceInBaseCurrency: 331.83, marketPriceInBaseCurrency: 331.83,
quantity: new Big('1'), quantity: new Big('1'),
symbol: 'MSFT', symbol: 'MSFT',
tags: undefined, tags: [],
transactionCount: 2 transactionCount: 2
} }
], ],

1
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, marketPriceInBaseCurrency: 87.8,
quantity: new Big('1'), quantity: new Big('1'),
symbol: 'NOVN.SW', symbol: 'NOVN.SW',
tags: [],
timeWeightedInvestment: new Big('145.10285714285714285714'), timeWeightedInvestment: new Big('145.10285714285714285714'),
timeWeightedInvestmentWithCurrencyEffect: new Big( timeWeightedInvestmentWithCurrencyEffect: new Big(
'145.10285714285714285714' '145.10285714285714285714'

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts

@ -175,6 +175,7 @@ describe('PortfolioCalculator', () => {
marketPriceInBaseCurrency: 87.8, marketPriceInBaseCurrency: 87.8,
quantity: new Big('0'), quantity: new Big('0'),
symbol: 'NOVN.SW', symbol: 'NOVN.SW',
tags: [],
timeWeightedInvestment: new Big('151.6'), timeWeightedInvestment: new Big('151.6'),
timeWeightedInvestmentWithCurrencyEffect: new Big('151.6'), timeWeightedInvestmentWithCurrencyEffect: new Big('151.6'),
transactionCount: 2, transactionCount: 2,

14
apps/api/src/app/portfolio/portfolio.service.ts

@ -63,8 +63,7 @@ import {
DataSource, DataSource,
Order, Order,
Platform, Platform,
Prisma, Prisma
Tag
} from '@prisma/client'; } from '@prisma/client';
import { Big } from 'big.js'; import { Big } from 'big.js';
import { isUUID } from 'class-validator'; import { isUUID } from 'class-validator';
@ -701,11 +700,8 @@ export class PortfolioService {
); );
}); });
let tags: Tag[] = [];
if (orders.length <= 0) { if (orders.length <= 0) {
return { return {
tags,
accounts: [], accounts: [],
averagePrice: undefined, averagePrice: undefined,
dataProviderInfo: undefined, dataProviderInfo: undefined,
@ -730,6 +726,7 @@ export class PortfolioService {
orders: [], orders: [],
quantity: undefined, quantity: undefined,
SymbolProfile: undefined, SymbolProfile: undefined,
tags: [],
transactionCount: undefined, transactionCount: undefined,
value: undefined value: undefined
}; };
@ -741,16 +738,12 @@ export class PortfolioService {
const portfolioCalculator = this.calculatorFactory.createCalculator({ const portfolioCalculator = this.calculatorFactory.createCalculator({
activities: orders.filter((order) => { activities: orders.filter((order) => {
tags = tags.concat(order.tags);
return ['BUY', 'DIVIDEND', 'ITEM', 'SELL'].includes(order.type); return ['BUY', 'DIVIDEND', 'ITEM', 'SELL'].includes(order.type);
}), }),
calculationType: PerformanceCalculationType.TWR, calculationType: PerformanceCalculationType.TWR,
currency: userCurrency currency: userCurrency
}); });
tags = uniqBy(tags, 'id');
const portfolioStart = portfolioCalculator.getStartDate(); const portfolioStart = portfolioCalculator.getStartDate();
const transactionPoints = portfolioCalculator.getTransactionPoints(); const transactionPoints = portfolioCalculator.getTransactionPoints();
@ -771,6 +764,7 @@ export class PortfolioService {
firstBuyDate, firstBuyDate,
marketPrice, marketPrice,
quantity, quantity,
tags,
timeWeightedInvestment, timeWeightedInvestment,
timeWeightedInvestmentWithCurrencyEffect, timeWeightedInvestmentWithCurrencyEffect,
transactionCount transactionCount
@ -947,7 +941,6 @@ export class PortfolioService {
minPrice, minPrice,
orders, orders,
SymbolProfile, SymbolProfile,
tags,
accounts: [], accounts: [],
averagePrice: 0, averagePrice: 0,
dataProviderInfo: undefined, dataProviderInfo: undefined,
@ -967,6 +960,7 @@ export class PortfolioService {
netPerformancePercentWithCurrencyEffect: undefined, netPerformancePercentWithCurrencyEffect: undefined,
netPerformanceWithCurrencyEffect: undefined, netPerformanceWithCurrencyEffect: undefined,
quantity: 0, quantity: 0,
tags: [],
transactionCount: undefined, transactionCount: undefined,
value: 0 value: 0
}; };

Loading…
Cancel
Save