Bugfix/fix exception in account value calculation (#3109)

* Fix exception in value of account calculation caused by liabilities

* Update changelog
pull/3110/head
Thomas Kaul 12 months ago committed by GitHub
parent f3a8822a77
commit c54392b7bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Fixed
- Fixed an issue in the account value calculation caused by liabilities
## 2.61.0 - 2024-03-04 ## 2.61.0 - 2024-03-04
### Changed ### Changed

@ -439,15 +439,33 @@ export class PortfolioService {
portfolioItemsNow[position.symbol] = position; portfolioItemsNow[position.symbol] = position;
} }
for (const item of currentPositions.positions) { for (const {
if (item.quantity.lte(0)) { currency,
firstBuyDate,
grossPerformance,
grossPerformanceWithCurrencyEffect,
grossPerformancePercentage,
grossPerformancePercentageWithCurrencyEffect,
investment,
marketPrice,
marketPriceInBaseCurrency,
netPerformance,
netPerformancePercentage,
netPerformancePercentageWithCurrencyEffect,
netPerformanceWithCurrencyEffect,
quantity,
symbol,
tags,
transactionCount
} of currentPositions.positions) {
if (quantity.eq(0)) {
// Ignore positions without any quantity // Ignore positions without any quantity
continue; continue;
} }
const value = item.quantity.mul(item.marketPriceInBaseCurrency ?? 0); const value = quantity.mul(marketPriceInBaseCurrency ?? 0);
const symbolProfile = symbolProfileMap[item.symbol]; const symbolProfile = symbolProfileMap[symbol];
const dataProviderResponse = dataProviderResponses[item.symbol]; const dataProviderResponse = dataProviderResponses[symbol];
const markets: PortfolioPosition['markets'] = { const markets: PortfolioPosition['markets'] = {
[UNKNOWN_KEY]: 0, [UNKNOWN_KEY]: 0,
@ -519,40 +537,39 @@ export class PortfolioService {
.toNumber(); .toNumber();
} }
holdings[item.symbol] = { holdings[symbol] = {
currency,
markets, markets,
marketsAdvanced, marketsAdvanced,
marketPrice,
symbol,
tags,
transactionCount,
allocationInPercentage: filteredValueInBaseCurrency.eq(0) allocationInPercentage: filteredValueInBaseCurrency.eq(0)
? 0 ? 0
: value.div(filteredValueInBaseCurrency).toNumber(), : value.div(filteredValueInBaseCurrency).toNumber(),
assetClass: symbolProfile.assetClass, assetClass: symbolProfile.assetClass,
assetSubClass: symbolProfile.assetSubClass, assetSubClass: symbolProfile.assetSubClass,
countries: symbolProfile.countries, countries: symbolProfile.countries,
currency: item.currency,
dataSource: symbolProfile.dataSource, dataSource: symbolProfile.dataSource,
dateOfFirstActivity: parseDate(item.firstBuyDate), dateOfFirstActivity: parseDate(firstBuyDate),
grossPerformance: item.grossPerformance?.toNumber() ?? 0, grossPerformance: grossPerformance?.toNumber() ?? 0,
grossPerformancePercent: grossPerformancePercent: grossPerformancePercentage?.toNumber() ?? 0,
item.grossPerformancePercentage?.toNumber() ?? 0,
grossPerformancePercentWithCurrencyEffect: grossPerformancePercentWithCurrencyEffect:
item.grossPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0, grossPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0,
grossPerformanceWithCurrencyEffect: grossPerformanceWithCurrencyEffect:
item.grossPerformanceWithCurrencyEffect?.toNumber() ?? 0, grossPerformanceWithCurrencyEffect?.toNumber() ?? 0,
investment: item.investment.toNumber(), investment: investment.toNumber(),
marketPrice: item.marketPrice,
marketState: dataProviderResponse?.marketState ?? 'delayed', marketState: dataProviderResponse?.marketState ?? 'delayed',
name: symbolProfile.name, name: symbolProfile.name,
netPerformance: item.netPerformance?.toNumber() ?? 0, netPerformance: netPerformance?.toNumber() ?? 0,
netPerformancePercent: item.netPerformancePercentage?.toNumber() ?? 0, netPerformancePercent: netPerformancePercentage?.toNumber() ?? 0,
netPerformancePercentWithCurrencyEffect: netPerformancePercentWithCurrencyEffect:
item.netPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0, netPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0,
netPerformanceWithCurrencyEffect: netPerformanceWithCurrencyEffect:
item.netPerformanceWithCurrencyEffect?.toNumber() ?? 0, netPerformanceWithCurrencyEffect?.toNumber() ?? 0,
quantity: item.quantity.toNumber(), quantity: quantity.toNumber(),
sectors: symbolProfile.sectors, sectors: symbolProfile.sectors,
symbol: item.symbol,
tags: item.tags,
transactionCount: item.transactionCount,
url: symbolProfile.url, url: symbolProfile.url,
valueInBaseCurrency: value.toNumber() valueInBaseCurrency: value.toNumber()
}; };
@ -1770,24 +1787,33 @@ export class PortfolioService {
activityType: 'INTEREST' activityType: 'INTEREST'
}).toNumber(); }).toNumber();
const items = Object.keys(holdings) const items = getSum(
.filter((symbol) => { Object.keys(holdings)
return isUUID(symbol) && holdings[symbol].dataSource === 'MANUAL'; .filter((symbol) => {
}) return (
.map((symbol) => { isUUID(symbol) &&
return holdings[symbol].valueInBaseCurrency; holdings[symbol].dataSource === 'MANUAL' &&
}) holdings[symbol].valueInBaseCurrency > 0
.reduce( );
(previous, current) => new Big(previous).plus(current), })
new Big(0) .map((symbol) => {
) return new Big(holdings[symbol].valueInBaseCurrency).abs();
.toNumber(); })
).toNumber();
const liabilities = this.getSumOfActivityType({
activities, const liabilities = getSum(
userCurrency, Object.keys(holdings)
activityType: 'LIABILITY' .filter((symbol) => {
}).toNumber(); return (
isUUID(symbol) &&
holdings[symbol].dataSource === 'MANUAL' &&
holdings[symbol].valueInBaseCurrency < 0
);
})
.map((symbol) => {
return new Big(holdings[symbol].valueInBaseCurrency).abs();
})
).toNumber();
const totalBuy = this.getSumOfActivityType({ const totalBuy = this.getSumOfActivityType({
userCurrency, userCurrency,
@ -1941,7 +1967,7 @@ export class PortfolioService {
private async getTransactionPoints({ private async getTransactionPoints({
filters, filters,
includeDrafts = false, includeDrafts = false,
types = ['BUY', 'ITEM', 'SELL'], types = ['BUY', 'ITEM', 'LIABILITY', 'SELL'],
userId, userId,
withExcludedAccounts = false withExcludedAccounts = false
}: { }: {
@ -2076,19 +2102,10 @@ export class PortfolioService {
}); });
for (const account of currentAccounts) { for (const account of currentAccounts) {
let ordersByAccount = orders.filter(({ accountId }) => { const ordersByAccount = orders.filter(({ accountId }) => {
return accountId === account.id; return accountId === account.id;
}); });
const ordersOfTypeItemOrLiabilityByAccount =
ordersOfTypeItemOrLiability.filter(({ accountId }) => {
return accountId === account.id;
});
ordersByAccount = ordersByAccount.concat(
ordersOfTypeItemOrLiabilityByAccount
);
accounts[account.id] = { accounts[account.id] = {
balance: account.balance, balance: account.balance,
currency: account.currency, currency: account.currency,
@ -2128,8 +2145,8 @@ export class PortfolioService {
} of ordersByAccount) { } of ordersByAccount) {
let currentValueOfSymbolInBaseCurrency = let currentValueOfSymbolInBaseCurrency =
quantity * quantity *
portfolioItemsNow[SymbolProfile.symbol] (portfolioItemsNow[SymbolProfile.symbol]?.marketPriceInBaseCurrency ??
?.marketPriceInBaseCurrency ?? 0; 0);
if (['LIABILITY', 'SELL'].includes(type)) { if (['LIABILITY', 'SELL'].includes(type)) {
currentValueOfSymbolInBaseCurrency *= getFactor(type); currentValueOfSymbolInBaseCurrency *= getFactor(type);

Loading…
Cancel
Save