diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 4f6d4f02d..3a759e443 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -247,16 +247,12 @@ export class PortfolioController { this.request.user.id ); - const portfolio = await this.portfolioService.createPortfolio( - impersonationUserId || this.request.user.id + const performanceInformation = await this.portfolioService.getPerformance( + impersonationUserId, + range ); - let performance = await portfolio.getPerformance(range); - - if (hasNotDefinedValuesInObject(performance)) { - res.status(StatusCodes.ACCEPTED); - } - + let performance = performanceInformation.performance; if ( impersonationId && !hasPermission( diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 93d0114c3..2cd1259d9 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -15,6 +15,7 @@ import { RulesService } from '@ghostfolio/api/services/rules.service'; import { PortfolioItem, PortfolioOverview, + PortfolioPerformance, Position } from '@ghostfolio/common/interfaces'; import { DateRange, RequestWithUser } from '@ghostfolio/common/types'; @@ -438,6 +439,64 @@ export class PortfolioService { }; } + public async getPerformance( + aImpersonationId: string, + aDateRange: DateRange = 'max' + ): Promise<{ hasErrors: boolean; performance: PortfolioPerformance }> { + const impersonationUserId = + await this.impersonationService.validateImpersonationId( + aImpersonationId, + this.request.user.id + ); + const userId = impersonationUserId || this.request.user.id; + + const portfolioCalculator = new PortfolioCalculator( + this.currentRateService, + this.request.user.Settings.currency + ); + + const transactionPoints = await this.getTransactionPoints(userId); + + portfolioCalculator.setTransactionPoints(transactionPoints); + + const portfolioStart = parseDate(transactionPoints[0].date); + const startDate = this.getStartDate(aDateRange, portfolioStart); + const currentPositions = await portfolioCalculator.getCurrentPositions( + startDate + ); + + let currentValue = new Big(0); + let grossPerformance = new Big(0); + let grossPerformancePercentage = new Big(1); + for (const currentPosition of currentPositions.positions) { + currentValue = currentValue.add( + new Big(currentPosition.marketPrice).mul(currentPosition.quantity) + ); + grossPerformance = grossPerformance.plus( + currentPosition.grossPerformance + ); + grossPerformancePercentage = grossPerformancePercentage.mul( + currentPosition.grossPerformancePercentage.plus(1) + ); + } + + const currentGrossPerformance = grossPerformance.toNumber(); + const currentGrossPerformancePercent = grossPerformancePercentage + .minus(1) + .toNumber(); + return { + hasErrors: currentPositions.hasErrors, + performance: { + currentGrossPerformance, + currentGrossPerformancePercent, + // TODO: the next two should include fees + currentNetPerformance: currentGrossPerformance, + currentNetPerformancePercent: currentGrossPerformancePercent, + currentValue: currentValue.toNumber() + } + }; + } + private getStartDate(aDateRange: DateRange, portfolioStart: Date) { switch (aDateRange) { case '1d':