From d91e3084fdedadcafbfd38a73b85ef91ddbdf9f7 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 20 Sep 2026 16:33:15 +0200 Subject: [PATCH] Task/rename NetPerformancePercentages to PerformancePercentages (#7927) Rename NetPerformancePercentages to PerformancePercentages --- .../calculator/mwr/portfolio-calculator.ts | 14 +- .../calculator/portfolio-calculator.ts | 31 +-- .../calculator/roai/portfolio-calculator.ts | 212 +++++++++--------- .../calculator/roi/portfolio-calculator.ts | 14 +- .../calculator/twr/portfolio-calculator.ts | 14 +- ...ype.ts => performance-percentages.type.ts} | 2 +- 6 files changed, 144 insertions(+), 143 deletions(-) rename apps/api/src/app/portfolio/types/{net-performance-percentages.type.ts => performance-percentages.type.ts} (79%) diff --git a/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts index e9f24ccd9b..f83b175128 100644 --- a/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts @@ -1,24 +1,24 @@ import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; import { HoldingPerformance } from '@ghostfolio/api/app/portfolio/interfaces/holding-performance.interface'; -import { NetPerformancePercentages } from '@ghostfolio/api/app/portfolio/types/net-performance-percentages.type'; +import { PerformancePercentages } from '@ghostfolio/api/app/portfolio/types/performance-percentages.type'; import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; import { PortfolioSnapshot } from '@ghostfolio/common/models'; import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; export class MwrPortfolioCalculator extends PortfolioCalculator { - protected calculateNetPerformancePercentages(): { - [date: string]: NetPerformancePercentages; - } { + protected calculateOverallPerformance(): PortfolioSnapshot { throw new Error('Method not implemented.'); } - protected calculateNetPerformancePercentagesForDateRange(): { - [date: string]: NetPerformancePercentages; + protected calculatePerformancePercentages(): { + [date: string]: PerformancePercentages; } { throw new Error('Method not implemented.'); } - protected calculateOverallPerformance(): PortfolioSnapshot { + protected calculatePerformancePercentagesForDateRange(): { + [date: string]: PerformancePercentages; + } { throw new Error('Method not implemented.'); } diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index f2ea3a959c..d9efa9f86c 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -10,7 +10,7 @@ import { PortfolioCalculatorActivityItem } from '@ghostfolio/api/app/portfolio/i import { PortfolioCalculatorActivity } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-calculator-activity.interface'; import { PortfolioCalculatorHolding } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-calculator-holding.interface'; import { PortfolioSnapshotValue } from '@ghostfolio/api/app/portfolio/interfaces/snapshot-value.interface'; -import { NetPerformancePercentages } from '@ghostfolio/api/app/portfolio/types/net-performance-percentages.type'; +import { PerformancePercentages } from '@ghostfolio/api/app/portfolio/types/performance-percentages.type'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; import { getFactor } from '@ghostfolio/api/helper/portfolio.helper'; import { LogPerformance } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.interceptor'; @@ -218,21 +218,21 @@ export abstract class PortfolioCalculator { this.snapshotPromise.catch(() => undefined); } - protected abstract calculateNetPerformancePercentages({ + protected abstract calculateOverallPerformance( + positions: PortfolioCalculatorHolding[] + ): PortfolioSnapshot; + + protected abstract calculatePerformancePercentages({ accumulatedValuesByDate }: { accumulatedValuesByDate: { [date: string]: AccumulatedValues }; - }): { [date: string]: NetPerformancePercentages }; + }): { [date: string]: PerformancePercentages }; - protected abstract calculateNetPerformancePercentagesForDateRange({ + protected abstract calculatePerformancePercentagesForDateRange({ historicalDataItems }: { historicalDataItems: HistoricalDataItem[]; - }): { [date: string]: NetPerformancePercentages }; - - protected abstract calculateOverallPerformance( - positions: PortfolioCalculatorHolding[] - ): PortfolioSnapshot; + }): { [date: string]: PerformancePercentages }; @LogPerformance public async computeSnapshot(): Promise { @@ -644,8 +644,9 @@ export abstract class PortfolioCalculator { } } - const netPerformancePercentagesByDate = - this.calculateNetPerformancePercentages({ accumulatedValuesByDate }); + const performancePercentagesByDate = this.calculatePerformancePercentages({ + accumulatedValuesByDate + }); const historicalData: HistoricalDataItem[] = Object.entries( accumulatedValuesByDate @@ -663,7 +664,7 @@ export abstract class PortfolioCalculator { } = values; return { - ...netPerformancePercentagesByDate[date], + ...performancePercentagesByDate[date], date, investmentValueWithCurrencyEffect: investmentValueWithCurrencyEffect.toNumber(), @@ -1369,15 +1370,15 @@ export abstract class PortfolioCalculator { } } - const netPerformancePercentagesByDate = - this.calculateNetPerformancePercentagesForDateRange({ + const performancePercentagesByDate = + this.calculatePerformancePercentagesForDateRange({ historicalDataItems: historicalDataItemsOfDateRange }); const chart = historicalDataItemsOfDateRange.map((historicalDataItem) => { return { ...historicalDataItem, - ...netPerformancePercentagesByDate[historicalDataItem.date] + ...performancePercentagesByDate[historicalDataItem.date] }; }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts index cd4f474ec0..39a1b4188b 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts @@ -3,7 +3,7 @@ import { AccumulatedValues } from '@ghostfolio/api/app/portfolio/interfaces/accu import { HoldingPerformance } from '@ghostfolio/api/app/portfolio/interfaces/holding-performance.interface'; import { PortfolioCalculatorActivityItem } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-calculator-activity-item.interface'; import { PortfolioCalculatorHolding } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-calculator-holding.interface'; -import { NetPerformancePercentages } from '@ghostfolio/api/app/portfolio/types/net-performance-percentages.type'; +import { PerformancePercentages } from '@ghostfolio/api/app/portfolio/types/performance-percentages.type'; import { getAnnualizedPerformancePercent, getIntervalFromDateRange @@ -32,111 +32,6 @@ import { import { sum } from 'lodash'; export class RoaiPortfolioCalculator extends PortfolioCalculator { - protected calculateNetPerformancePercentages({ - accumulatedValuesByDate - }: { - accumulatedValuesByDate: { [date: string]: AccumulatedValues }; - }): { [date: string]: NetPerformancePercentages } { - const netPerformancePercentagesByDate: { - [date: string]: NetPerformancePercentages; - } = {}; - - for (const [ - date, - { - totalAverageInvestmentValue, - totalAverageInvestmentValueWithCurrencyEffect, - totalNetPerformanceValue, - totalNetPerformanceValueWithCurrencyEffect - } - ] of Object.entries(accumulatedValuesByDate)) { - netPerformancePercentagesByDate[date] = { - netPerformanceInPercentage: totalAverageInvestmentValue.eq(0) - ? 0 - : totalNetPerformanceValue - .div(totalAverageInvestmentValue) - .toNumber(), - netPerformanceInPercentageWithCurrencyEffect: - totalAverageInvestmentValueWithCurrencyEffect.eq(0) - ? 0 - : totalNetPerformanceValueWithCurrencyEffect - .div(totalAverageInvestmentValueWithCurrencyEffect) - .toNumber() - }; - } - - return netPerformancePercentagesByDate; - } - - protected calculateNetPerformancePercentagesForDateRange({ - historicalDataItems - }: { - historicalDataItems: HistoricalDataItem[]; - }): { [date: string]: NetPerformancePercentages } { - const averageInvestmentValues: number[] = []; - const averageInvestmentValuesWithCurrencyEffect: number[] = []; - let grossPerformanceAtStartDate: number; - let grossPerformanceWithCurrencyEffectAtStartDate: number; - - const netPerformancePercentagesByDate: { - [date: string]: NetPerformancePercentages; - } = {}; - - for (const [index, historicalDataItem] of historicalDataItems.entries()) { - // Take the values at the start date from the first day of the date - // range - if (index === 0) { - grossPerformanceAtStartDate = - historicalDataItem.value - historicalDataItem.totalInvestment; - - grossPerformanceWithCurrencyEffectAtStartDate = - historicalDataItem.valueWithCurrencyEffect - - historicalDataItem.totalInvestmentValueWithCurrencyEffect; - } - - // Add the gross performance at the start date of the range to the - // investment of each day. Thus the range starts with the value of its - // first day, and subsequent buy and sell activities stay included. - if (historicalDataItem.totalInvestment > 0) { - averageInvestmentValues.push( - historicalDataItem.totalInvestment + grossPerformanceAtStartDate - ); - } - - if (historicalDataItem.totalInvestmentValueWithCurrencyEffect > 0) { - averageInvestmentValuesWithCurrencyEffect.push( - historicalDataItem.totalInvestmentValueWithCurrencyEffect + - grossPerformanceWithCurrencyEffectAtStartDate - ); - } - - const averageInvestmentValue = - averageInvestmentValues.length > 0 - ? sum(averageInvestmentValues) / averageInvestmentValues.length - : 0; - - const averageInvestmentValueWithCurrencyEffect = - averageInvestmentValuesWithCurrencyEffect.length > 0 - ? sum(averageInvestmentValuesWithCurrencyEffect) / - averageInvestmentValuesWithCurrencyEffect.length - : 0; - - netPerformancePercentagesByDate[historicalDataItem.date] = { - netPerformanceInPercentage: - averageInvestmentValue > 0 - ? historicalDataItem.netPerformance / averageInvestmentValue - : 0, - netPerformanceInPercentageWithCurrencyEffect: - averageInvestmentValueWithCurrencyEffect > 0 - ? historicalDataItem.netPerformanceWithCurrencyEffect / - averageInvestmentValueWithCurrencyEffect - : 0 - }; - } - - return netPerformancePercentagesByDate; - } - protected calculateOverallPerformance( positions: PortfolioCalculatorHolding[] ): PortfolioSnapshot { @@ -269,6 +164,111 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { }; } + protected calculatePerformancePercentages({ + accumulatedValuesByDate + }: { + accumulatedValuesByDate: { [date: string]: AccumulatedValues }; + }): { [date: string]: PerformancePercentages } { + const performancePercentagesByDate: { + [date: string]: PerformancePercentages; + } = {}; + + for (const [ + date, + { + totalAverageInvestmentValue, + totalAverageInvestmentValueWithCurrencyEffect, + totalNetPerformanceValue, + totalNetPerformanceValueWithCurrencyEffect + } + ] of Object.entries(accumulatedValuesByDate)) { + performancePercentagesByDate[date] = { + netPerformanceInPercentage: totalAverageInvestmentValue.eq(0) + ? 0 + : totalNetPerformanceValue + .div(totalAverageInvestmentValue) + .toNumber(), + netPerformanceInPercentageWithCurrencyEffect: + totalAverageInvestmentValueWithCurrencyEffect.eq(0) + ? 0 + : totalNetPerformanceValueWithCurrencyEffect + .div(totalAverageInvestmentValueWithCurrencyEffect) + .toNumber() + }; + } + + return performancePercentagesByDate; + } + + protected calculatePerformancePercentagesForDateRange({ + historicalDataItems + }: { + historicalDataItems: HistoricalDataItem[]; + }): { [date: string]: PerformancePercentages } { + const averageInvestmentValues: number[] = []; + const averageInvestmentValuesWithCurrencyEffect: number[] = []; + let grossPerformanceAtStartDate: number; + let grossPerformanceWithCurrencyEffectAtStartDate: number; + + const performancePercentagesByDate: { + [date: string]: PerformancePercentages; + } = {}; + + for (const [index, historicalDataItem] of historicalDataItems.entries()) { + // Take the values at the start date from the first day of the date + // range + if (index === 0) { + grossPerformanceAtStartDate = + historicalDataItem.value - historicalDataItem.totalInvestment; + + grossPerformanceWithCurrencyEffectAtStartDate = + historicalDataItem.valueWithCurrencyEffect - + historicalDataItem.totalInvestmentValueWithCurrencyEffect; + } + + // Add the gross performance at the start date of the range to the + // investment of each day. Thus the range starts with the value of its + // first day, and subsequent buy and sell activities stay included. + if (historicalDataItem.totalInvestment > 0) { + averageInvestmentValues.push( + historicalDataItem.totalInvestment + grossPerformanceAtStartDate + ); + } + + if (historicalDataItem.totalInvestmentValueWithCurrencyEffect > 0) { + averageInvestmentValuesWithCurrencyEffect.push( + historicalDataItem.totalInvestmentValueWithCurrencyEffect + + grossPerformanceWithCurrencyEffectAtStartDate + ); + } + + const averageInvestmentValue = + averageInvestmentValues.length > 0 + ? sum(averageInvestmentValues) / averageInvestmentValues.length + : 0; + + const averageInvestmentValueWithCurrencyEffect = + averageInvestmentValuesWithCurrencyEffect.length > 0 + ? sum(averageInvestmentValuesWithCurrencyEffect) / + averageInvestmentValuesWithCurrencyEffect.length + : 0; + + performancePercentagesByDate[historicalDataItem.date] = { + netPerformanceInPercentage: + averageInvestmentValue > 0 + ? historicalDataItem.netPerformance / averageInvestmentValue + : 0, + netPerformanceInPercentageWithCurrencyEffect: + averageInvestmentValueWithCurrencyEffect > 0 + ? historicalDataItem.netPerformanceWithCurrencyEffect / + averageInvestmentValueWithCurrencyEffect + : 0 + }; + } + + return performancePercentagesByDate; + } + protected getHoldingPerformance({ chartDates, dataSource, diff --git a/apps/api/src/app/portfolio/calculator/roi/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/roi/portfolio-calculator.ts index 5829585ed7..862febf5db 100644 --- a/apps/api/src/app/portfolio/calculator/roi/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/roi/portfolio-calculator.ts @@ -1,24 +1,24 @@ import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; import { HoldingPerformance } from '@ghostfolio/api/app/portfolio/interfaces/holding-performance.interface'; -import { NetPerformancePercentages } from '@ghostfolio/api/app/portfolio/types/net-performance-percentages.type'; +import { PerformancePercentages } from '@ghostfolio/api/app/portfolio/types/performance-percentages.type'; import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; import { PortfolioSnapshot } from '@ghostfolio/common/models'; import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; export class RoiPortfolioCalculator extends PortfolioCalculator { - protected calculateNetPerformancePercentages(): { - [date: string]: NetPerformancePercentages; - } { + protected calculateOverallPerformance(): PortfolioSnapshot { throw new Error('Method not implemented.'); } - protected calculateNetPerformancePercentagesForDateRange(): { - [date: string]: NetPerformancePercentages; + protected calculatePerformancePercentages(): { + [date: string]: PerformancePercentages; } { throw new Error('Method not implemented.'); } - protected calculateOverallPerformance(): PortfolioSnapshot { + protected calculatePerformancePercentagesForDateRange(): { + [date: string]: PerformancePercentages; + } { throw new Error('Method not implemented.'); } diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts index c3877a347c..cad53c31ab 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts @@ -1,24 +1,24 @@ import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; import { HoldingPerformance } from '@ghostfolio/api/app/portfolio/interfaces/holding-performance.interface'; -import { NetPerformancePercentages } from '@ghostfolio/api/app/portfolio/types/net-performance-percentages.type'; +import { PerformancePercentages } from '@ghostfolio/api/app/portfolio/types/performance-percentages.type'; import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; import { PortfolioSnapshot } from '@ghostfolio/common/models'; import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; export class TwrPortfolioCalculator extends PortfolioCalculator { - protected calculateNetPerformancePercentages(): { - [date: string]: NetPerformancePercentages; - } { + protected calculateOverallPerformance(): PortfolioSnapshot { throw new Error('Method not implemented.'); } - protected calculateNetPerformancePercentagesForDateRange(): { - [date: string]: NetPerformancePercentages; + protected calculatePerformancePercentages(): { + [date: string]: PerformancePercentages; } { throw new Error('Method not implemented.'); } - protected calculateOverallPerformance(): PortfolioSnapshot { + protected calculatePerformancePercentagesForDateRange(): { + [date: string]: PerformancePercentages; + } { throw new Error('Method not implemented.'); } diff --git a/apps/api/src/app/portfolio/types/net-performance-percentages.type.ts b/apps/api/src/app/portfolio/types/performance-percentages.type.ts similarity index 79% rename from apps/api/src/app/portfolio/types/net-performance-percentages.type.ts rename to apps/api/src/app/portfolio/types/performance-percentages.type.ts index 288f44631d..99521e516e 100644 --- a/apps/api/src/app/portfolio/types/net-performance-percentages.type.ts +++ b/apps/api/src/app/portfolio/types/performance-percentages.type.ts @@ -1,6 +1,6 @@ import { HistoricalDataItem } from '@ghostfolio/common/interfaces'; -export type NetPerformancePercentages = Required< +export type PerformancePercentages = Required< Pick< HistoricalDataItem, | 'netPerformanceInPercentage'