Browse Source

Bugfix/start date of calendar year date ranges in portfolio performance (#8077)

* Fix start date of calendar year date ranges in portfolio performance

* Update changelog
pull/8078/head
Thomas Kaul 2 days ago
committed by GitHub
parent
commit
a0b3d1f71a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 4
      apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts
  3. 7
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  4. 21
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts

1
CHANGELOG.md

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed the visibility of the asset class, asset sub class, fee and quantity fields of a valuable in the create activity dialog
- Fixed the missing mapping for Aland Islands in the country weightings of the _Financial Modeling Prep_ service
- Fixed the net performance percentage of date ranges in the portfolio performance calculation by weighting the average investment by the number of days between the chart dates
- Fixed the start date of calendar year date ranges in the portfolio performance calculation
## 3.80.2 - 2026-10-06

4
apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts

@ -13,7 +13,7 @@ import {
import { DateRange } from '@ghostfolio/common/types';
import { Injectable, Logger } from '@nestjs/common';
import { format, isSameDay } from 'date-fns';
import { format, isSameDay, min } from 'date-fns';
import { isNumber } from 'lodash-es';
@Injectable()
@ -96,8 +96,8 @@ export class BenchmarksService {
const exchangeRates =
await this.exchangeRateDataService.getExchangeRatesByCurrency({
startDate,
currencies: [currentSymbolItem.currency],
startDate: min([baselineDate, startDate]),
targetCurrency: userCurrency
});

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

@ -64,6 +64,7 @@ import {
format,
isAfter,
isBefore,
isEqual,
isFuture,
isPast,
isWithinInterval,
@ -1417,10 +1418,14 @@ export abstract class PortfolioCalculator {
let netPerformanceAtStartDate: number;
let netPerformanceWithCurrencyEffectAtStartDate: number;
const startDate = isEqual(start, endOfDay(start))
? resetHours(start)
: start;
for (const historicalDataItem of historicalData) {
const date = resetHours(parseDate(historicalDataItem.date));
if (!isBefore(date, start) && !isAfter(date, end)) {
if (!isBefore(date, startDate) && !isAfter(date, end)) {
// Take the values at the start date from the first day of the date
// range
if (historicalDataItemsOfDateRange.length === 0) {

21
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts

@ -13,6 +13,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service.mock';
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper';
import { parseDate } from '@ghostfolio/common/helper';
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
@ -168,6 +169,7 @@ describe('PortfolioCalculator', () => {
},
netPerformanceWithCurrencyEffectMap: {
'1d': new Big('-556.443324'),
'2017': new Big('27081.23736'),
max: new Big('26516.208701400000064086'),
ytd: new Big('-556.443324')
},
@ -262,8 +264,8 @@ describe('PortfolioCalculator', () => {
'2017': {
date: '2017-12-31',
netPerformance: 26957.033439,
netPerformanceInPercentage: 44.109822737327406,
netPerformanceInPercentageWithCurrencyEffect: 43.14859823223876,
netPerformanceInPercentage: 44.10965416175681,
netPerformanceInPercentageWithCurrencyEffect: 43.148434302822835,
netPerformanceWithCurrencyEffect: 27081.23736,
totalInvestmentValueWithCurrencyEffect: 318.54266729999995,
valueWithCurrencyEffect: 13854.86868
@ -287,6 +289,17 @@ describe('PortfolioCalculator', () => {
valueWithCurrencyEffect: 13298.425356
}
});
const { endDate, startDate } = getIntervalFromDateRange({
dateRange: '2017'
});
const { chart } = await portfolioCalculator.getPerformance({
end: endDate,
start: startDate
});
expect(chart[0].date).toBe('2016-12-31');
});
it.only('with BTCUSD buy and sell partially and fewer chart items', async () => {
@ -333,12 +346,12 @@ describe('PortfolioCalculator', () => {
// Other weights give another rounding of the floating point numbers
expect(
performanceByDateRange['2017'].netPerformanceInPercentage
).toBeCloseTo(44.109822737327406, 10);
).toBeCloseTo(44.10965416175681, 10);
expect(
performanceByDateRange['2017']
.netPerformanceInPercentageWithCurrencyEffect
).toBeCloseTo(43.14859823223876, 10);
).toBeCloseTo(43.148434302822835, 10);
expect(performanceByDateRange.max.netPerformanceInPercentage).toBeCloseTo(
42.43911719562077,

Loading…
Cancel
Save