Browse Source

Feature/optimize portfolio calculations with smarter date interval selection (#3829)

* Optimize portfolio calculations with smarter date interval selection

* Update changelog
pull/3862/head
ceroma 4 months ago
committed by GitHub
parent
commit
2ad91e5796
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 42
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts

1
CHANGELOG.md

@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Optimized the portfolio calculations with smarter date interval selection
- Improved the language localization for German (`de`) - Improved the language localization for German (`de`)
## 2.111.0 - 2024-09-28 ## 2.111.0 - 2024-09-28

42
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts

@ -16,13 +16,14 @@ import {
addDays, addDays,
addMilliseconds, addMilliseconds,
differenceInDays, differenceInDays,
eachDayOfInterval,
format, format,
isBefore isBefore
} from 'date-fns'; } from 'date-fns';
import { cloneDeep, first, last, sortBy } from 'lodash'; import { cloneDeep, first, last, sortBy } from 'lodash';
export class TWRPortfolioCalculator extends PortfolioCalculator { export class TWRPortfolioCalculator extends PortfolioCalculator {
private chartDatesDescending: string[];
protected calculateOverallPerformance( protected calculateOverallPerformance(
positions: TimelinePosition[] positions: TimelinePosition[]
): PortfolioSnapshot { ): PortfolioSnapshot {
@ -820,31 +821,35 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
startDate = start; startDate = start;
} }
const endDateString = format(endDate, DATE_FORMAT);
const startDateString = format(startDate, DATE_FORMAT);
const currentValuesAtDateRangeStartWithCurrencyEffect = const currentValuesAtDateRangeStartWithCurrencyEffect =
currentValuesWithCurrencyEffect[format(startDate, DATE_FORMAT)] ?? currentValuesWithCurrencyEffect[startDateString] ?? new Big(0);
new Big(0);
const investmentValuesAccumulatedAtStartDateWithCurrencyEffect = const investmentValuesAccumulatedAtStartDateWithCurrencyEffect =
investmentValuesAccumulatedWithCurrencyEffect[ investmentValuesAccumulatedWithCurrencyEffect[startDateString] ??
format(startDate, DATE_FORMAT) new Big(0);
] ?? new Big(0);
const grossPerformanceAtDateRangeStartWithCurrencyEffect = const grossPerformanceAtDateRangeStartWithCurrencyEffect =
currentValuesAtDateRangeStartWithCurrencyEffect.minus( currentValuesAtDateRangeStartWithCurrencyEffect.minus(
investmentValuesAccumulatedAtStartDateWithCurrencyEffect investmentValuesAccumulatedAtStartDateWithCurrencyEffect
); );
const dates = eachDayOfInterval({
end: endDate,
start: startDate
}).map((date) => {
return format(date, DATE_FORMAT);
});
let average = new Big(0); let average = new Big(0);
let dayCount = 0; let dayCount = 0;
for (const date of dates) { if (!this.chartDatesDescending) {
this.chartDatesDescending = Object.keys(chartDateMap).sort().reverse();
}
for (const date of this.chartDatesDescending) {
if (date > endDateString) {
continue;
} else if (date < startDateString) {
break;
}
if ( if (
investmentValuesAccumulatedWithCurrencyEffect[date] instanceof Big && investmentValuesAccumulatedWithCurrencyEffect[date] instanceof Big &&
investmentValuesAccumulatedWithCurrencyEffect[date].gt(0) investmentValuesAccumulatedWithCurrencyEffect[date].gt(0)
@ -864,17 +869,14 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
} }
netPerformanceWithCurrencyEffectMap[dateRange] = netPerformanceWithCurrencyEffectMap[dateRange] =
netPerformanceValuesWithCurrencyEffect[ netPerformanceValuesWithCurrencyEffect[endDateString]?.minus(
format(endDate, DATE_FORMAT)
]?.minus(
// If the date range is 'max', take 0 as a start value. Otherwise, // If the date range is 'max', take 0 as a start value. Otherwise,
// the value of the end of the day of the start date is taken which // the value of the end of the day of the start date is taken which
// differs from the buying price. // differs from the buying price.
dateRange === 'max' dateRange === 'max'
? new Big(0) ? new Big(0)
: (netPerformanceValuesWithCurrencyEffect[ : (netPerformanceValuesWithCurrencyEffect[startDateString] ??
format(startDate, DATE_FORMAT) new Big(0))
] ?? new Big(0))
) ?? new Big(0); ) ?? new Big(0);
netPerformancePercentageWithCurrencyEffectMap[dateRange] = average.gt(0) netPerformancePercentageWithCurrencyEffectMap[dateRange] = average.gt(0)

Loading…
Cancel
Save