diff --git a/apps/api/src/app/account-balance/account-balance.service.ts b/apps/api/src/app/account-balance/account-balance.service.ts index 321624003..d81dc5208 100644 --- a/apps/api/src/app/account-balance/account-balance.service.ts +++ b/apps/api/src/app/account-balance/account-balance.service.ts @@ -14,7 +14,7 @@ import { Injectable } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { AccountBalance, Prisma } from '@prisma/client'; import { Big } from 'big.js'; -import { format, parseISO } from 'date-fns'; +import { endOfDay, format, parseISO } from 'date-fns'; @Injectable() export class AccountBalanceService { @@ -109,11 +109,19 @@ export class AccountBalanceService { userId, withExcludedAccounts: false // TODO }); + + // Exclude future-dated balances so they do not affect portfolio calculation (fixes #6185) + const asOfDate = endOfDay(new Date()); + const asOfTime = asOfDate.getTime(); + const balancesUpToToday = balances.filter(({ date }) => { + return date.getTime() <= asOfTime; + }); + const accumulatedBalancesByDate: { [date: string]: HistoricalDataItem } = {}; const lastBalancesByAccount: { [accountId: string]: Big } = {}; - for (const { accountId, date, valueInBaseCurrency } of balances) { + for (const { accountId, date, valueInBaseCurrency } of balancesUpToToday) { const formattedDate = format(date, DATE_FORMAT); lastBalancesByAccount[accountId] = new Big(valueInBaseCurrency); diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index 9a4f1e46b..e9da1ade8 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -371,10 +371,16 @@ export class OrderService { filters: [{ id: account.id, type: 'ACCOUNT' }] }); + // Exclude future-dated balances so they do not affect portfolio calculation (fixes #6185) + const asOfDate = endOfToday(); + const balancesUpToToday = balances.filter(({ date }) => { + return date <= asOfDate; + }); + let currentBalance = 0; let currentBalanceInBaseCurrency = 0; - for (const balanceItem of balances) { + for (const balanceItem of balancesUpToToday) { const syntheticActivityTemplate: Activity = { userId, accountId: account.id, 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 a53ebcf05..77413cac1 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 @@ -157,6 +157,14 @@ describe('PortfolioCalculator', () => { date: parseDate('2024-12-31'), value: 2000, valueInBaseCurrency: 1800 + }, + { + // Future-dated balance: should be ignored (issue #6185) + accountId, + date: parseDate('2050-12-31'), + id: randomUUID(), + value: 0, + valueInBaseCurrency: 0 } ] });