diff --git a/CHANGELOG.md b/CHANGELOG.md index cdd0e3ee3..c2ff6e59c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Moved the benchmark comparator from experimental to general availability - Improved the user interface of the benchmark comparator ### Fixed diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index de682d33c..680b4cd93 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -12,7 +12,6 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration.ser import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; import { - PortfolioChart, PortfolioDetails, PortfolioInvestments, PortfolioPerformanceResponse, @@ -61,55 +60,6 @@ export class PortfolioController { this.baseCurrency = this.configurationService.get('BASE_CURRENCY'); } - @Get('chart') - @UseGuards(AuthGuard('jwt')) - public async getChart( - @Headers('impersonation-id') impersonationId: string, - @Query('range') range - ): Promise { - const historicalDataContainer = await this.portfolioService.getChart( - impersonationId, - range - ); - - let chartData = historicalDataContainer.items; - - let hasError = false; - - chartData.forEach((chartDataItem) => { - if (hasNotDefinedValuesInObject(chartDataItem)) { - hasError = true; - } - }); - - if ( - impersonationId || - this.userService.isRestrictedView(this.request.user) - ) { - let maxValue = 0; - - chartData.forEach((portfolioItem) => { - if (portfolioItem.value > maxValue) { - maxValue = portfolioItem.value; - } - }); - - chartData = chartData.map((historicalDataItem) => { - return { - ...historicalDataItem, - marketPrice: Number((historicalDataItem.value / maxValue).toFixed(2)) - }; - }); - } - - return { - hasError, - chart: chartData, - isAllTimeHigh: historicalDataContainer.isAllTimeHigh, - isAllTimeLow: historicalDataContainer.isAllTimeLow - }; - } - @Get('details') @UseGuards(AuthGuard('jwt')) @UseInterceptors(RedactValuesInResponseInterceptor) @@ -274,32 +224,6 @@ export class PortfolioController { return { firstOrderDate: parseDate(investments[0]?.date), investments }; } - @Get('performance') - @UseGuards(AuthGuard('jwt')) - @UseInterceptors(TransformDataSourceInResponseInterceptor) - public async getPerformance( - @Headers('impersonation-id') impersonationId: string, - @Query('range') range - ): Promise { - const performanceInformation = await this.portfolioService.getPerformance( - impersonationId, - range - ); - - if ( - impersonationId || - this.request.user.Settings.settings.viewMode === 'ZEN' || - this.userService.isRestrictedView(this.request.user) - ) { - performanceInformation.performance = nullifyValuesInObject( - performanceInformation.performance, - ['currentGrossPerformance', 'currentValue'] - ); - } - - return performanceInformation; - } - @Get('performance') @UseGuards(AuthGuard('jwt')) @UseInterceptors(TransformDataSourceInResponseInterceptor) diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 7fc77eff0..636b8f39c 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -615,7 +615,7 @@ export class PortfolioService { withExcludedAccounts }); - const summary = await this.getSummary(impersonationId); + const summary = await this.getSummary({ impersonationId }); return { accounts, @@ -956,77 +956,6 @@ export class PortfolioService { }; } - public async getPerformance( - aImpersonationId: string, - aDateRange: DateRange = 'max' - ): Promise { - const userId = await this.getUserId(aImpersonationId, this.request.user.id); - - const { portfolioOrders, transactionPoints } = - await this.getTransactionPoints({ - userId - }); - - const portfolioCalculator = new PortfolioCalculator({ - currency: this.request.user.Settings.settings.baseCurrency, - currentRateService: this.currentRateService, - orders: portfolioOrders - }); - - if (transactionPoints?.length <= 0) { - return { - hasErrors: false, - performance: { - currentGrossPerformance: 0, - currentGrossPerformancePercent: 0, - currentNetPerformance: 0, - currentNetPerformancePercent: 0, - currentValue: 0 - } - }; - } - - portfolioCalculator.setTransactionPoints(transactionPoints); - - const portfolioStart = parseDate(transactionPoints[0].date); - const startDate = this.getStartDate(aDateRange, portfolioStart); - const currentPositions = await portfolioCalculator.getCurrentPositions( - startDate - ); - - const hasErrors = currentPositions.hasErrors; - const currentValue = currentPositions.currentValue.toNumber(); - const currentGrossPerformance = currentPositions.grossPerformance; - let currentGrossPerformancePercent = - currentPositions.grossPerformancePercentage; - const currentNetPerformance = currentPositions.netPerformance; - let currentNetPerformancePercent = - currentPositions.netPerformancePercentage; - - if (currentGrossPerformance.mul(currentGrossPerformancePercent).lt(0)) { - // If algebraic sign is different, harmonize it - currentGrossPerformancePercent = currentGrossPerformancePercent.mul(-1); - } - - if (currentNetPerformance.mul(currentNetPerformancePercent).lt(0)) { - // If algebraic sign is different, harmonize it - currentNetPerformancePercent = currentNetPerformancePercent.mul(-1); - } - - return { - errors: currentPositions.errors, - hasErrors: currentPositions.hasErrors || hasErrors, - performance: { - currentValue, - currentGrossPerformance: currentGrossPerformance.toNumber(), - currentGrossPerformancePercent: - currentGrossPerformancePercent.toNumber(), - currentNetPerformance: currentNetPerformance.toNumber(), - currentNetPerformancePercent: currentNetPerformancePercent.toNumber() - } - }; - } - public async getPerformanceV2({ dateRange = 'max', impersonationId @@ -1393,14 +1322,18 @@ export class PortfolioService { return portfolioStart; } - private async getSummary( - aImpersonationId: string - ): Promise { + private async getSummary({ + impersonationId + }: { + impersonationId: string; + }): Promise { const userCurrency = this.request.user.Settings.settings.baseCurrency; - const userId = await this.getUserId(aImpersonationId, this.request.user.id); + const userId = await this.getUserId(impersonationId, this.request.user.id); const user = await this.userService.user({ id: userId }); - const performanceInformation = await this.getPerformance(aImpersonationId); + const performanceInformation = await this.getPerformanceV2({ + impersonationId + }); const { balanceInBaseCurrency } = await this.accountService.getCashDetails({ userId, diff --git a/apps/client/src/app/components/home-overview/home-overview.component.ts b/apps/client/src/app/components/home-overview/home-overview.component.ts index 9c35fe8c5..72bbc4162 100644 --- a/apps/client/src/app/components/home-overview/home-overview.component.ts +++ b/apps/client/src/app/components/home-overview/home-overview.component.ts @@ -107,8 +107,7 @@ export class HomeOverviewComponent implements OnDestroy, OnInit { this.dataService .fetchPortfolioPerformance({ - range: this.user?.settings?.dateRange, - version: this.user?.settings?.isExperimentalFeatures ? 2 : 1 + range: this.user?.settings?.dateRange }) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((response) => { @@ -117,35 +116,12 @@ export class HomeOverviewComponent implements OnDestroy, OnInit { this.performance = response.performance; this.isLoadingPerformance = false; - if (this.user?.settings?.isExperimentalFeatures) { - this.historicalDataItems = response.chart.map(({ date, value }) => { - return { - date, - value - }; - }); - } else { - this.dataService - .fetchChart({ - range: this.user?.settings?.dateRange, - version: 1 - }) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((chartData) => { - this.historicalDataItems = chartData.chart.map( - ({ date, value }) => { - return { - date, - value - }; - } - ); - this.isAllTimeHigh = chartData.isAllTimeHigh; - this.isAllTimeLow = chartData.isAllTimeLow; - - this.changeDetectorRef.markForCheck(); - }); - } + this.historicalDataItems = response.chart.map(({ date, value }) => { + return { + date, + value + }; + }); this.changeDetectorRef.markForCheck(); }); diff --git a/apps/client/src/app/components/home-overview/home-overview.html b/apps/client/src/app/components/home-overview/home-overview.html index 0a47689c8..f714b45b3 100644 --- a/apps/client/src/app/components/home-overview/home-overview.html +++ b/apps/client/src/app/components/home-overview/home-overview.html @@ -15,7 +15,7 @@ diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index f669b457b..f9640521c 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -122,24 +122,21 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { } private update() { - if (this.user.settings.isExperimentalFeatures) { - this.isLoadingBenchmarkComparator = true; + this.isLoadingBenchmarkComparator = true; - this.dataService - .fetchPortfolioPerformance({ - range: this.user?.settings?.dateRange, - version: 2 - }) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ chart }) => { - this.firstOrderDate = new Date(chart?.[0]?.date ?? new Date()); - this.performanceDataItems = chart; + this.dataService + .fetchPortfolioPerformance({ + range: this.user?.settings?.dateRange + }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ chart }) => { + this.firstOrderDate = new Date(chart?.[0]?.date ?? new Date()); + this.performanceDataItems = chart; - this.updateBenchmarkDataItems(); + this.updateBenchmarkDataItems(); - this.changeDetectorRef.markForCheck(); - }); - } + this.changeDetectorRef.markForCheck(); + }); this.dataService .fetchInvestments() diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html index 66970cc50..828fea343 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -1,6 +1,6 @@

Analysis

-
+
('/api/v1/benchmark'); } - public fetchChart({ range, version }: { range: DateRange; version: number }) { - return this.http.get(`/api/v${version}/portfolio/chart`, { - params: { range } - }); - } - public fetchExport(activityIds?: string[]) { let params = new HttpParams(); @@ -259,15 +252,9 @@ export class DataService { ); } - public fetchPortfolioPerformance({ - range, - version - }: { - range: DateRange; - version: number; - }) { + public fetchPortfolioPerformance({ range }: { range: DateRange }) { return this.http.get( - `/api/v${version}/portfolio/performance`, + `/api/v2/portfolio/performance`, { params: { range } } ); }