diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 1bc9c2e02..d2b48daf0 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -202,6 +202,7 @@ export abstract class PortfolioCalculator { }; } + const cashSymbols = new Set(); const currencies: { [symbol: string]: string } = {}; const dataGatheringItems: DataGatheringItem[] = []; let firstIndex = transactionPoints.length; @@ -315,12 +316,11 @@ export abstract class PortfolioCalculator { const accumulatedValuesByDate: { [date: string]: { investmentValueWithCurrencyEffect: Big; - totalAccountBalanceWithCurrencyEffect: Big; + totalCashValueWithCurrencyEffect: Big; totalCurrentValue: Big; totalCurrentValueWithCurrencyEffect: Big; totalInvestmentValue: Big; totalInvestmentValueWithCurrencyEffect: Big; - totalLiabilitiesWithCurrencyEffect: Big; totalNetPerformanceValue: Big; totalNetPerformanceValueWithCurrencyEffect: Big; totalTimeWeightedInvestmentValue: Big; @@ -351,6 +351,8 @@ export abstract class PortfolioCalculator { ] ?? 1 ); + const valueInBaseCurrency = marketPriceInBaseCurrency.mul(item.quantity); + const { currentValues, currentValuesWithCurrencyEffect, @@ -444,15 +446,14 @@ export abstract class PortfolioCalculator { quantity: item.quantity, symbol: item.symbol, tags: item.tags, - valueInBaseCurrency: new Big(marketPriceInBaseCurrency).mul( - item.quantity - ) + valueInBaseCurrency }); if (item.assetSubClass === 'CASH') { - totalCashInBaseCurrency = totalCashInBaseCurrency.plus( - marketPriceInBaseCurrency.mul(item.quantity) - ); + cashSymbols.add(item.symbol); + + totalCashInBaseCurrency = + totalCashInBaseCurrency.plus(valueInBaseCurrency); } totalInterestWithCurrencyEffect = totalInterestWithCurrencyEffect.plus( @@ -474,56 +475,7 @@ export abstract class PortfolioCalculator { } } - const accountBalanceItemsMap = this.accountBalanceItems.reduce( - (map, { date, value }) => { - map[date] = new Big(value); - - return map; - }, - {} as { [date: string]: Big } - ); - - const liabilityItemsMap = this.activities.reduce( - (map, { assetProfile, date, quantity, type, unitPrice }) => { - if (type === 'LIABILITY') { - const exchangeRate = - exchangeRatesByCurrency[ - `${assetProfile.currency}${this.currency}` - ]?.[date] ?? 1; - - map[date] = (map[date] ?? new Big(0)).plus( - quantity.mul(unitPrice).mul(exchangeRate) - ); - } - - return map; - }, - {} as { [date: string]: Big } - ); - - const accountBalanceMap: { [date: string]: Big } = {}; - const liabilitiesMap: { [date: string]: Big } = {}; - - let accumulatedLiabilities = new Big(0); - let lastKnownBalance = new Big(0); - for (const dateString of chartDates) { - if (accountBalanceItemsMap[dateString] !== undefined) { - // If there's an exact balance for this date, update lastKnownBalance - lastKnownBalance = accountBalanceItemsMap[dateString]; - } - - // Add the most recent balance to the accountBalanceMap - accountBalanceMap[dateString] = lastKnownBalance; - - if (liabilityItemsMap[dateString] !== undefined) { - accumulatedLiabilities = accumulatedLiabilities.plus( - liabilityItemsMap[dateString] - ); - } - - liabilitiesMap[dateString] = accumulatedLiabilities; - for (const symbol of Object.keys(valuesBySymbol)) { const symbolValues = valuesBySymbol[symbol]; @@ -566,7 +518,14 @@ export abstract class PortfolioCalculator { accumulatedValuesByDate[dateString] ?.investmentValueWithCurrencyEffect ?? new Big(0) ).add(investmentValueWithCurrencyEffect), - totalAccountBalanceWithCurrencyEffect: accountBalanceMap[dateString], + totalCashValueWithCurrencyEffect: ( + accumulatedValuesByDate[dateString] + ?.totalCashValueWithCurrencyEffect ?? new Big(0) + ).add( + cashSymbols.has(symbol) + ? currentValueWithCurrencyEffect + : new Big(0) + ), totalCurrentValue: ( accumulatedValuesByDate[dateString]?.totalCurrentValue ?? new Big(0) ).add(currentValue), @@ -582,7 +541,6 @@ export abstract class PortfolioCalculator { accumulatedValuesByDate[dateString] ?.totalInvestmentValueWithCurrencyEffect ?? new Big(0) ).add(investmentValueAccumulatedWithCurrencyEffect), - totalLiabilitiesWithCurrencyEffect: liabilitiesMap[dateString], totalNetPerformanceValue: ( accumulatedValuesByDate[dateString]?.totalNetPerformanceValue ?? new Big(0) @@ -608,12 +566,11 @@ export abstract class PortfolioCalculator { ).map(([date, values]) => { const { investmentValueWithCurrencyEffect, - totalAccountBalanceWithCurrencyEffect, + totalCashValueWithCurrencyEffect, totalCurrentValue, totalCurrentValueWithCurrencyEffect, totalInvestmentValue, totalInvestmentValueWithCurrencyEffect, - totalLiabilitiesWithCurrencyEffect, totalNetPerformanceValue, totalNetPerformanceValueWithCurrencyEffect, totalTimeWeightedInvestmentValue, @@ -642,10 +599,8 @@ export abstract class PortfolioCalculator { netPerformance: totalNetPerformanceValue.toNumber(), netPerformanceWithCurrencyEffect: totalNetPerformanceValueWithCurrencyEffect.toNumber(), - netWorth: totalCurrentValueWithCurrencyEffect - .minus(totalLiabilitiesWithCurrencyEffect) - .toNumber(), - totalAccountBalance: totalAccountBalanceWithCurrencyEffect.toNumber(), + netWorth: totalCurrentValueWithCurrencyEffect.toNumber(), + totalCashInBaseCurrency: totalCashValueWithCurrencyEffect.toNumber(), totalInvestment: totalInvestmentValue.toNumber(), totalInvestmentValueWithCurrencyEffect: totalInvestmentValueWithCurrencyEffect.toNumber(), diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts index bc80e8996..4f5da58b8 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts @@ -145,7 +145,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: 0, netPerformanceWithCurrencyEffect: 0, netWorth: 0, - totalAccountBalance: 0, + totalCashInBaseCurrency: 0, totalInvestment: 0, totalInvestmentValueWithCurrencyEffect: 0, value: 0, @@ -163,7 +163,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: 0.12422837255001412, // 5535.42 ÷ 44558.42 = 0.12422837255001412 netPerformanceWithCurrencyEffect: 5535.42, netWorth: 50098.3, // 1 * 50098.3 = 50098.3 - totalAccountBalance: 0, + totalCashInBaseCurrency: 0, totalInvestment: 44558.42, totalInvestmentValueWithCurrencyEffect: 44558.42, value: 50098.3, // 1 * 50098.3 = 50098.3 @@ -182,7 +182,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: -0.032837340282712, netPerformanceWithCurrencyEffect: -1463.18, netWorth: 43099.7, - totalAccountBalance: 0, + totalCashInBaseCurrency: 0, totalInvestment: 44558.42, totalInvestmentValueWithCurrencyEffect: 44558.42, value: 43099.7, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts index 18b0e6d64..eb5571feb 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts @@ -145,7 +145,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: 0, netPerformanceWithCurrencyEffect: 0, netWorth: 0, - totalAccountBalance: 0, + totalCashInBaseCurrency: 0, totalInvestment: 0, totalInvestmentValueWithCurrencyEffect: 0, value: 0, @@ -163,7 +163,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: 0.12422837255001412, // 5535.42 ÷ 44558.42 = 0.12422837255001412 netPerformanceWithCurrencyEffect: 5535.42, // 1 * (50098.3 - 44558.42) - 4.46 = 5535.42 netWorth: 50098.3, // 1 * 50098.3 = 50098.3 - totalAccountBalance: 0, + totalCashInBaseCurrency: 0, totalInvestment: 44558.42, totalInvestmentValueWithCurrencyEffect: 44558.42, value: 50098.3, // 1 * 50098.3 = 50098.3 @@ -182,7 +182,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: -0.032837340282712, netPerformanceWithCurrencyEffect: -1463.18, netWorth: 43099.7, - totalAccountBalance: 0, + totalCashInBaseCurrency: 0, totalInvestment: 44558.42, totalInvestmentValueWithCurrencyEffect: 44558.42, value: 43099.7, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts index d5d5ef439..5ae61590b 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts @@ -301,8 +301,10 @@ describe('PortfolioCalculator', () => { /** * Value with currency effect: 2000 USD * 0.91 = 1820 CHF - * Net worth: 1820 CHF - 0 CHF (liabilities) = 1820 CHF - * Total account balance: 1800 CHF (balance in base currency on 2024-12-31) + * Net worth: 1820 CHF (the cash is included in the value and therefore + * not added on top of it again) + * Cash in base currency: 2000 USD * 0.91 = 1820 CHF (the whole portfolio + * consists of cash, hence it matches the value) * Net performance with currency effect: 70 CHF / 852.45 CHF ≈ 8.21 % */ expect(lastDataItem).toEqual({ @@ -313,7 +315,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: 0.08211603004634808, netPerformanceWithCurrencyEffect: 70, netWorth: 1820, - totalAccountBalance: 1800, + totalCashInBaseCurrency: 1820, totalInvestment: 1820, totalInvestmentValueWithCurrencyEffect: 1750, value: 1820, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts index 51a4c0368..94654af61 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts @@ -113,14 +113,6 @@ describe('PortfolioCalculator', () => { expect(portfolioSnapshot.totalLiabilitiesWithCurrencyEffect).toEqual( new Big(3000) ); - - /** - * Net worth: 0 USD (current value) - 3000 USD (liabilities) = -3000 USD - */ - expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject({ - netWorth: -3000, - valueWithCurrencyEffect: 0 - }); }); }); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts index f86b23d9a..10cc2da01 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -142,7 +142,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: 0, netPerformanceWithCurrencyEffect: 0, netWorth: 0, - totalAccountBalance: 0, + totalCashInBaseCurrency: 0, totalInvestment: 0, totalInvestmentValueWithCurrencyEffect: 0, value: 0, @@ -161,7 +161,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: 0.158311345646438, // 24 ÷ 151.6 = 0.158311345646438 netPerformanceWithCurrencyEffect: 24, netWorth: 175.6, // 2 * 87.8 = 175.6 - totalAccountBalance: 0, + totalCashInBaseCurrency: 0, totalInvestment: 151.6, totalInvestmentValueWithCurrencyEffect: 151.6, value: 175.6, // 2 * 87.8 = 175.6 @@ -180,7 +180,7 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentageWithCurrencyEffect: 0.13100263852242744, netPerformanceWithCurrencyEffect: 19.86, netWorth: 0, - totalAccountBalance: 0, + totalCashInBaseCurrency: 0, totalInvestment: 0, totalInvestmentValueWithCurrencyEffect: 0, value: 0, diff --git a/libs/common/src/lib/interfaces/historical-data-item.interface.ts b/libs/common/src/lib/interfaces/historical-data-item.interface.ts index 0b45cf0b7..adb5b7e65 100644 --- a/libs/common/src/lib/interfaces/historical-data-item.interface.ts +++ b/libs/common/src/lib/interfaces/historical-data-item.interface.ts @@ -11,7 +11,7 @@ export interface HistoricalDataItem { netWorth?: number; netWorthInPercentage?: number; quantity?: number; - totalAccountBalance?: number; + totalCashInBaseCurrency?: number; totalInvestment?: number; totalInvestmentValueWithCurrencyEffect?: number; value?: number;