Bugfix/add missing tags in portfolio calculator (#3243)
* Add missing tags * Update changelog
This commit is contained in:
parent
5c480109d5
commit
ca2e748c56
@ -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
|
||||||
|
@ -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 ?? [];
|
||||||
|
@ -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'
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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'
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -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'
|
||||||
|
@ -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,
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user