From 557c280707b8c3b272d88701a81b56f58d4cec76 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Sat, 11 Sep 2021 18:00:17 +0200 Subject: [PATCH] Add annualized performance --- .../app/portfolio/portfolio.service.spec.ts | 45 +++++++++++++++++++ .../src/app/portfolio/portfolio.service.ts | 25 ++++++++++- .../portfolio-summary.component.html | 15 ++++++- .../interfaces/portfolio-summary.interface.ts | 1 + 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 apps/api/src/app/portfolio/portfolio.service.spec.ts diff --git a/apps/api/src/app/portfolio/portfolio.service.spec.ts b/apps/api/src/app/portfolio/portfolio.service.spec.ts new file mode 100644 index 000000000..38af51d88 --- /dev/null +++ b/apps/api/src/app/portfolio/portfolio.service.spec.ts @@ -0,0 +1,45 @@ +import { PortfolioService } from './portfolio.service'; + +describe('PortfolioService', () => { + let portfolioService: PortfolioService; + + beforeAll(async () => { + portfolioService = new PortfolioService( + null, + null, + null, + null, + null, + null, + null, + null, + null + ); + }); + + /** + * Source: https://www.investopedia.com/terms/a/annualized-total-return.asp#annualized-return-formula-and-calculation + */ + fit('Get annualized performance', async () => { + expect( + portfolioService.getAnnualizedPerformancePercent({ + daysInMarket: NaN, + netPerformancePercent: 0 + }) + ).toEqual(0); + + expect( + portfolioService.getAnnualizedPerformancePercent({ + daysInMarket: 0, + netPerformancePercent: 0 + }) + ).toEqual(0); + + expect( + portfolioService.getAnnualizedPerformancePercent({ + daysInMarket: 575, + netPerformancePercent: 0.2374 + }) + ).toEqual(0.1447846830315136); + }); +}); diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 7d9630453..55ee5ee00 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -47,6 +47,7 @@ import { } from '@prisma/client'; import Big from 'big.js'; import { + differenceInDays, endOfToday, format, isAfter, @@ -58,7 +59,7 @@ import { subDays, subYears } from 'date-fns'; -import { isEmpty } from 'lodash'; +import { isEmpty, isNumber } from 'lodash'; import { HistoricalDataItem, @@ -80,6 +81,21 @@ export class PortfolioService { private readonly symbolProfileService: SymbolProfileService ) {} + public getAnnualizedPerformancePercent({ + daysInMarket, + netPerformancePercent + }: { + daysInMarket: number; + netPerformancePercent: number; + }) { + if (isNumber(daysInMarket) && daysInMarket > 0) { + const exponent = new Big(365).div(daysInMarket).toNumber(); + return Math.pow(1 + netPerformancePercent, exponent) - 1; + } + + return 0; + } + public async getInvestments( aImpersonationId: string ): Promise { @@ -715,6 +731,12 @@ export class PortfolioService { const fees = this.getFees(orders); const firstOrderDate = orders[0]?.date; + const annualizedPerformancePercent = this.getAnnualizedPerformancePercent({ + daysInMarket: differenceInDays(new Date(), firstOrderDate), + netPerformancePercent: + performanceInformation.performance.currentNetPerformancePercent + }); + const totalBuy = this.getTotalByType(orders, currency, TypeOfOrder.BUY); const totalSell = this.getTotalByType(orders, currency, TypeOfOrder.SELL); @@ -726,6 +748,7 @@ export class PortfolioService { return { ...performanceInformation.performance, + annualizedPerformancePercent, fees, firstOrderDate, netWorth, diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html index d2551e5fc..9bc6d59c1 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -146,7 +146,7 @@

-
Net Worth
+
Net Worth
+
+
Annualized Performance
+
+ +
+
diff --git a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts index e34bd0e6b..8a771c557 100644 --- a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts @@ -1,6 +1,7 @@ import { PortfolioPerformance } from './portfolio-performance.interface'; export interface PortfolioSummary extends PortfolioPerformance { + annualizedPerformancePercent: number; cash: number; committedFunds: number; fees: number;