From 27147fa551fa154fe2575d9f7b654ffb5fa99485 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 31 Mar 2024 19:36:46 +0200 Subject: [PATCH] Refactoring --- .../calculator/mwr/portfolio-calculator.ts | 4 +- .../portfolio-calculator-test-utils.ts | 30 +++++++-------- .../portfolio-calculator.factory.ts | 16 ++++---- .../calculator/portfolio-calculator.ts | 22 ++++++----- ...aln-buy-and-sell-in-two-activities.spec.ts | 19 +++++----- ...folio-calculator-baln-buy-and-sell.spec.ts | 19 +++++----- .../twr/portfolio-calculator-baln-buy.spec.ts | 19 +++++----- ...ator-btcusd-buy-and-sell-partially.spec.ts | 19 +++++----- .../portfolio-calculator-googl-buy.spec.ts | 19 +++++----- ...-calculator-msft-buy-with-dividend.spec.ts | 19 +++++----- .../portfolio-calculator-no-orders.spec.ts | 14 +++---- ...ulator-novn-buy-and-sell-partially.spec.ts | 19 +++++----- ...folio-calculator-novn-buy-and-sell.spec.ts | 19 +++++----- .../twr/portfolio-calculator.spec.ts | 11 +++--- .../calculator/twr/portfolio-calculator.ts | 3 +- .../interfaces/current-positions.interface.ts | 2 +- .../src/app/portfolio/portfolio.service.ts | 37 +++++++------------ 17 files changed, 136 insertions(+), 155 deletions(-) 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 9bdf02152..7426807c0 100644 --- a/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts @@ -1,3 +1,4 @@ +import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { TimelinePosition, @@ -5,14 +6,13 @@ import { SymbolMetrics } from '@ghostfolio/common/interfaces'; -import { PortfolioCalculator } from '../portfolio-calculator'; - export class MWRPortfolioCalculator extends PortfolioCalculator { protected calculateOverallPerformance( positions: TimelinePosition[] ): CurrentPositions { throw new Error('Method not implemented.'); } + protected getSymbolMetrics({ dataSource, end, diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts index 508608ed9..6d1939fcd 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts @@ -1,3 +1,18 @@ +export const activityDummyData = { + accountId: undefined, + accountUserId: undefined, + comment: undefined, + createdAt: new Date(), + feeInBaseCurrency: undefined, + id: undefined, + isDraft: false, + symbolProfileId: undefined, + updatedAt: new Date(), + userId: undefined, + value: undefined, + valueInBaseCurrency: undefined +}; + export const symbolProfileDummyData = { activitiesCount: undefined, assetClass: undefined, @@ -8,18 +23,3 @@ export const symbolProfileDummyData = { sectors: [], updatedAt: undefined }; - -export const activityDummyData = { - value: undefined, - valueInBaseCurrency: undefined, - accountId: undefined, - id: undefined, - userId: undefined, - createdAt: new Date(), - updatedAt: new Date(), - accountUserId: undefined, - comment: undefined, - feeInBaseCurrency: undefined, - isDraft: false, - symbolProfileId: undefined -}; diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts index 27fc779a1..5b34ca205 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts @@ -15,30 +15,30 @@ export enum PerformanceCalculationType { @Injectable() export class PortfolioCalculatorFactory { - constructor( + public constructor( private readonly currentRateService: CurrentRateService, private readonly exchangeRateDataService: ExchangeRateDataService ) {} - createCalculator({ - calculationType, + public createCalculator({ activities, + calculationType, currency }: { - calculationType: PerformanceCalculationType; activities: Activity[]; + calculationType: PerformanceCalculationType; currency: string; }): PortfolioCalculator { switch (calculationType) { - case PerformanceCalculationType.TWR: - return new TWRPortfolioCalculator({ + case PerformanceCalculationType.MWR: + return new MWRPortfolioCalculator({ activities, currency, currentRateService: this.currentRateService, exchangeRateDataService: this.exchangeRateDataService }); - case PerformanceCalculationType.MWR: - return new MWRPortfolioCalculator({ + case PerformanceCalculationType.TWR: + return new TWRPortfolioCalculator({ activities, currency, currentRateService: this.currentRateService, diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 08b1342f2..c3edc86d9 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -34,11 +34,12 @@ import { isNumber, last, uniq } from 'lodash'; export abstract class PortfolioCalculator { protected static readonly ENABLE_LOGGING = false; + protected orders: PortfolioOrder[]; + private currency: string; private currentRateService: CurrentRateService; private dataProviderInfos: DataProviderInfo[]; private exchangeRateDataService: ExchangeRateDataService; - protected orders: PortfolioOrder[]; private transactionPoints: TransactionPoint[]; public constructor({ @@ -75,6 +76,10 @@ export abstract class PortfolioCalculator { this.computeTransactionPoints(); } + protected abstract calculateOverallPerformance( + positions: TimelinePosition[] + ): CurrentPositions; + public getAnnualizedPerformancePercent({ daysInMarket, netPerformancePercent @@ -394,7 +399,8 @@ export abstract class PortfolioCalculator { netPerformancePercentageWithCurrencyEffect: new Big(0), netPerformanceWithCurrencyEffect: new Big(0), positions: [], - totalInvestment: new Big(0) + totalInvestment: new Big(0), + totalInvestmentWithCurrencyEffect: new Big(0) }; } @@ -652,20 +658,12 @@ export abstract class PortfolioCalculator { })); } - public getTransactionPoints() { - return this.transactionPoints; - } - public getStartDate() { return this.transactionPoints.length > 0 ? parseDate(this.transactionPoints[0].date) : new Date(); } - protected abstract calculateOverallPerformance( - positions: TimelinePosition[] - ): CurrentPositions; - protected abstract getSymbolMetrics({ dataSource, end, @@ -686,6 +684,10 @@ export abstract class PortfolioCalculator { step?: number; } & UniqueAsset): SymbolMetrics; + public getTransactionPoints() { + return this.transactionPoints; + } + private computeTransactionPoints() { this.transactionPoints = []; const symbols: { [symbol: string]: TransactionPointSymbol } = {}; diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts index 8fd5482c4..ee71a1fb3 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts @@ -1,19 +1,18 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; -import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; -import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; -import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { parseDate } from '@ghostfolio/common/helper'; - -import { Big } from 'big.js'; - import { activityDummyData, symbolProfileDummyData -} from '../portfolio-calculator-test-utils'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory, PerformanceCalculationType -} from '../portfolio-calculator.factory'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { parseDate } from '@ghostfolio/common/helper'; + +import { Big } from 'big.js'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -96,8 +95,8 @@ describe('PortfolioCalculator', () => { ]; const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: 'CHF' }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts index 0d41dbaf3..69078be7c 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts @@ -1,19 +1,18 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; -import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; -import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; -import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { parseDate } from '@ghostfolio/common/helper'; - -import { Big } from 'big.js'; - import { activityDummyData, symbolProfileDummyData -} from '../portfolio-calculator-test-utils'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PerformanceCalculationType, PortfolioCalculatorFactory -} from '../portfolio-calculator.factory'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { parseDate } from '@ghostfolio/common/helper'; + +import { Big } from 'big.js'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -81,8 +80,8 @@ describe('PortfolioCalculator', () => { ]; const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: 'CHF' }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts index faab46f8f..b52aac68d 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts @@ -1,19 +1,18 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; -import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; -import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; -import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { parseDate } from '@ghostfolio/common/helper'; - -import { Big } from 'big.js'; - import { activityDummyData, symbolProfileDummyData -} from '../portfolio-calculator-test-utils'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory, PerformanceCalculationType -} from '../portfolio-calculator.factory'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { parseDate } from '@ghostfolio/common/helper'; + +import { Big } from 'big.js'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -66,8 +65,8 @@ describe('PortfolioCalculator', () => { ]; const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: 'CHF' }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts index c2a38bcae..420ba48f1 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts @@ -1,4 +1,12 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { + activityDummyData, + symbolProfileDummyData +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; +import { + PortfolioCalculatorFactory, + PerformanceCalculationType +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; @@ -7,15 +15,6 @@ import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { - activityDummyData, - symbolProfileDummyData -} from '../portfolio-calculator-test-utils'; -import { - PortfolioCalculatorFactory, - PerformanceCalculationType -} from '../portfolio-calculator.factory'; - jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { // eslint-disable-next-line @typescript-eslint/naming-convention @@ -94,8 +93,8 @@ describe('PortfolioCalculator', () => { ]; const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: 'CHF' }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts index 0ce1647c7..5f33d771b 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts @@ -1,4 +1,12 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { + activityDummyData, + symbolProfileDummyData +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; +import { + PortfolioCalculatorFactory, + PerformanceCalculationType +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; @@ -7,15 +15,6 @@ import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { - activityDummyData, - symbolProfileDummyData -} from '../portfolio-calculator-test-utils'; -import { - PortfolioCalculatorFactory, - PerformanceCalculationType -} from '../portfolio-calculator.factory'; - jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { // eslint-disable-next-line @typescript-eslint/naming-convention @@ -79,8 +78,8 @@ describe('PortfolioCalculator', () => { ]; const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: 'CHF' }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts index d9e6c639a..a2c106784 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -1,4 +1,12 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { + activityDummyData, + symbolProfileDummyData +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; +import { + PerformanceCalculationType, + PortfolioCalculatorFactory +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; @@ -7,15 +15,6 @@ import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { - activityDummyData, - symbolProfileDummyData -} from '../portfolio-calculator-test-utils'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from '../portfolio-calculator.factory'; - jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { // eslint-disable-next-line @typescript-eslint/naming-convention @@ -94,8 +93,8 @@ describe('PortfolioCalculator', () => { ]; const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: 'USD' }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts index 8626553ef..905747519 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts @@ -1,3 +1,7 @@ +import { + PerformanceCalculationType, + PortfolioCalculatorFactory +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; @@ -6,11 +10,6 @@ import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; import { subDays } from 'date-fns'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from '../portfolio-calculator.factory'; - jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { // eslint-disable-next-line @typescript-eslint/naming-convention @@ -44,8 +43,8 @@ describe('PortfolioCalculator', () => { describe('get current positions', () => { it('with no orders', async () => { const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities: [], + calculationType: PerformanceCalculationType.TWR, currency: 'CHF' }); @@ -81,7 +80,8 @@ describe('PortfolioCalculator', () => { netPerformancePercentageWithCurrencyEffect: new Big(0), netPerformanceWithCurrencyEffect: new Big(0), positions: [], - totalInvestment: new Big(0) + totalInvestment: new Big(0), + totalInvestmentWithCurrencyEffect: new Big(0) }); expect(investments).toEqual([]); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts index 1e61f6886..21e0bb499 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts @@ -1,19 +1,18 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; -import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; -import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; -import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { parseDate } from '@ghostfolio/common/helper'; - -import { Big } from 'big.js'; - import { activityDummyData, symbolProfileDummyData -} from '../portfolio-calculator-test-utils'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PerformanceCalculationType, PortfolioCalculatorFactory -} from '../portfolio-calculator.factory'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { parseDate } from '@ghostfolio/common/helper'; + +import { Big } from 'big.js'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -81,8 +80,8 @@ describe('PortfolioCalculator', () => { ]; const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: 'CHF' }); const spy = jest diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts index 491c6f3ac..28920ece7 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -1,19 +1,18 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; -import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; -import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; -import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { parseDate } from '@ghostfolio/common/helper'; - -import { Big } from 'big.js'; - import { activityDummyData, symbolProfileDummyData -} from '../portfolio-calculator-test-utils'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PerformanceCalculationType, PortfolioCalculatorFactory -} from '../portfolio-calculator.factory'; +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { parseDate } from '@ghostfolio/common/helper'; + +import { Big } from 'big.js'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -81,8 +80,8 @@ describe('PortfolioCalculator', () => { ]; const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: 'CHF' }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts index 3fb38b3d5..b68f4358d 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts @@ -1,13 +1,12 @@ +import { + PerformanceCalculationType, + PortfolioCalculatorFactory +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { Big } from 'big.js'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from '../portfolio-calculator.factory'; - describe('PortfolioCalculator', () => { let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; @@ -32,8 +31,8 @@ describe('PortfolioCalculator', () => { describe('annualized performance percentage', () => { it('Get annualized performance', async () => { const portfolioCalculator = factory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities: [], + calculationType: PerformanceCalculationType.TWR, currency: 'CHF' }); 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 4ff7d8cd9..0fee9c5c7 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts @@ -1,3 +1,4 @@ +import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { PortfolioOrderItem } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order-item.interface'; import { getFactor } from '@ghostfolio/api/helper/portfolio.helper'; @@ -19,8 +20,6 @@ import { } from 'date-fns'; import { cloneDeep, first, last, sortBy } from 'lodash'; -import { PortfolioCalculator } from '../portfolio-calculator'; - export class TWRPortfolioCalculator extends PortfolioCalculator { protected calculateOverallPerformance( positions: TimelinePosition[] diff --git a/apps/api/src/app/portfolio/interfaces/current-positions.interface.ts b/apps/api/src/app/portfolio/interfaces/current-positions.interface.ts index e76b62e44..308cc4037 100644 --- a/apps/api/src/app/portfolio/interfaces/current-positions.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/current-positions.interface.ts @@ -16,5 +16,5 @@ export interface CurrentPositions extends ResponseError { netPerformancePercentageWithCurrencyEffect: Big; positions: TimelinePosition[]; totalInvestment: Big; - totalInvestmentWithCurrencyEffect?: Big; + totalInvestmentWithCurrencyEffect: Big; } diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index fe6195f76..37c28cc3c 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -3,7 +3,6 @@ import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { CashDetails } from '@ghostfolio/api/app/account/interfaces/cash-details.interface'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { OrderService } from '@ghostfolio/api/app/order/order.service'; -import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { UserService } from '@ghostfolio/api/app/user/user.service'; import { getFactor, @@ -76,16 +75,8 @@ import { isBefore, isSameMonth, isSameYear, - isValid, - max, - min, parseISO, - set, - startOfWeek, - startOfMonth, - startOfYear, - subDays, - subYears + set } from 'date-fns'; import { isEmpty, last, uniq, uniqBy } from 'lodash'; @@ -110,7 +101,7 @@ export class PortfolioService { public constructor( private readonly accountBalanceService: AccountBalanceService, private readonly accountService: AccountService, - private readonly currentRateService: CurrentRateService, + private readonly calculatorFactory: PortfolioCalculatorFactory, private readonly dataProviderService: DataProviderService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly impersonationService: ImpersonationService, @@ -118,8 +109,7 @@ export class PortfolioService { @Inject(REQUEST) private readonly request: RequestWithUser, private readonly rulesService: RulesService, private readonly symbolProfileService: SymbolProfileService, - private readonly userService: UserService, - private readonly calculatorFactory: PortfolioCalculatorFactory + private readonly userService: UserService ) {} public async getAccounts({ @@ -279,8 +269,8 @@ export class PortfolioService { } const portfolioCalculator = this.calculatorFactory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: this.request.user.Settings.settings.baseCurrency }); @@ -367,8 +357,8 @@ export class PortfolioService { }); const portfolioCalculator = this.calculatorFactory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: userCurrency }); @@ -731,14 +721,13 @@ export class PortfolioService { tags = uniqBy(tags, 'id'); - const filteredActivities = orders.filter((order) => { - tags = tags.concat(order.tags); - return ['BUY', 'DIVIDEND', 'ITEM', 'SELL'].includes(order.type); - }); - const portfolioCalculator = this.calculatorFactory.createCalculator({ + activities: orders.filter((order) => { + tags = tags.concat(order.tags); + + return ['BUY', 'DIVIDEND', 'ITEM', 'SELL'].includes(order.type); + }), calculationType: PerformanceCalculationType.TWR, - activities: filteredActivities, currency: userCurrency }); @@ -974,8 +963,8 @@ export class PortfolioService { } const portfolioCalculator = this.calculatorFactory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: this.request.user.Settings.settings.baseCurrency }); @@ -1161,8 +1150,8 @@ export class PortfolioService { } const portfolioCalculator = this.calculatorFactory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: userCurrency }); @@ -1278,8 +1267,8 @@ export class PortfolioService { }); const portfolioCalculator = this.calculatorFactory.createCalculator({ - calculationType: PerformanceCalculationType.TWR, activities, + calculationType: PerformanceCalculationType.TWR, currency: this.request.user.Settings.settings.baseCurrency });