From 7e952ca9ea5f9c23b16986f3eddea06500e546d7 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 10 Feb 2025 17:54:39 +0100 Subject: [PATCH] Fix benchmark interval --- .../src/app/benchmark/benchmark.controller.ts | 8 ++- .../api/src/app/benchmark/benchmark.module.ts | 28 +++++++++- .../src/app/benchmark/benchmark.service.ts | 52 ++++++++----------- 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/apps/api/src/app/benchmark/benchmark.controller.ts b/apps/api/src/app/benchmark/benchmark.controller.ts index 66c268b9b..8f819c0fd 100644 --- a/apps/api/src/app/benchmark/benchmark.controller.ts +++ b/apps/api/src/app/benchmark/benchmark.controller.ts @@ -3,6 +3,7 @@ import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard' import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor'; import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; +import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; import type { AssetProfileIdentifier, BenchmarkMarketDataDetails, @@ -16,6 +17,7 @@ import { Controller, Delete, Get, + Headers, HttpException, Inject, Param, @@ -108,6 +110,7 @@ export class BenchmarkController { @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(TransformDataSourceInRequestInterceptor) public async getBenchmarkMarketDataForUser( + @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Param('dataSource') dataSource: DataSource, @Param('startDateString') startDateString: string, @Param('symbol') symbol: string, @@ -117,14 +120,15 @@ export class BenchmarkController { dateRange, new Date(startDateString) ); - const userCurrency = this.request.user.Settings.settings.baseCurrency; return this.benchmarkService.getMarketDataForUser({ dataSource, + dateRange, endDate, + impersonationId, startDate, symbol, - userCurrency + user: this.request.user }); } } diff --git a/apps/api/src/app/benchmark/benchmark.module.ts b/apps/api/src/app/benchmark/benchmark.module.ts index 4c5f4d58e..65be732a6 100644 --- a/apps/api/src/app/benchmark/benchmark.module.ts +++ b/apps/api/src/app/benchmark/benchmark.module.ts @@ -1,13 +1,24 @@ +import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; +import { AccountService } from '@ghostfolio/api/app/account/account.service'; +import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; +import { RulesService } from '@ghostfolio/api/app/portfolio/rules.service'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { SymbolModule } from '@ghostfolio/api/app/symbol/symbol.module'; +import { UserModule } from '@ghostfolio/api/app/user/user.module'; import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; +import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; +import { PortfolioSnapshotQueueModule } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.module'; import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; import { Module } from '@nestjs/common'; @@ -22,15 +33,28 @@ import { BenchmarkService } from './benchmark.service'; ConfigurationModule, DataProviderModule, ExchangeRateDataModule, + ImpersonationModule, MarketDataModule, + OrderModule, + PortfolioSnapshotQueueModule, PrismaModule, PropertyModule, RedisCacheModule, SymbolModule, SymbolProfileModule, TransformDataSourceInRequestModule, - TransformDataSourceInResponseModule + TransformDataSourceInResponseModule, + UserModule ], - providers: [BenchmarkService] + providers: [ + AccountBalanceService, + AccountService, + BenchmarkService, + CurrentRateService, + MarketDataService, + PortfolioCalculatorFactory, + PortfolioService, + RulesService + ] }) export class BenchmarkModule {} diff --git a/apps/api/src/app/benchmark/benchmark.service.ts b/apps/api/src/app/benchmark/benchmark.service.ts index 4e466668c..5c71562b6 100644 --- a/apps/api/src/app/benchmark/benchmark.service.ts +++ b/apps/api/src/app/benchmark/benchmark.service.ts @@ -1,6 +1,6 @@ +import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; import { SymbolService } from '@ghostfolio/api/app/symbol/symbol.service'; -import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; @@ -24,20 +24,16 @@ import { BenchmarkProperty, BenchmarkResponse } from '@ghostfolio/common/interfaces'; -import { BenchmarkTrend } from '@ghostfolio/common/types'; +import { + BenchmarkTrend, + DateRange, + UserWithSettings +} from '@ghostfolio/common/types'; import { Injectable, Logger } from '@nestjs/common'; import { SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; -import { - addHours, - differenceInDays, - eachDayOfInterval, - format, - isAfter, - isSameDay, - subDays -} from 'date-fns'; +import { addHours, format, isAfter, isSameDay, subDays } from 'date-fns'; import { isNumber, uniqBy } from 'lodash'; import ms from 'ms'; @@ -48,11 +44,11 @@ export class BenchmarkService { private readonly CACHE_KEY_BENCHMARKS = 'BENCHMARKS'; public constructor( - private readonly configurationService: ConfigurationService, private readonly dataProviderService: DataProviderService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly marketDataService: MarketDataService, private readonly prismaService: PrismaService, + private readonly portfolioService: PortfolioService, private readonly propertyService: PropertyService, private readonly redisCacheService: RedisCacheService, private readonly symbolProfileService: SymbolProfileService, @@ -158,31 +154,27 @@ export class BenchmarkService { public async getMarketDataForUser({ dataSource, + dateRange, endDate = new Date(), + impersonationId, startDate, symbol, - userCurrency + user }: { + dateRange: DateRange; endDate?: Date; + impersonationId: string; startDate: Date; - userCurrency: string; + user: UserWithSettings; } & AssetProfileIdentifier): Promise { const marketData: { date: string; value: number }[] = []; + const userCurrency = user.Settings.settings.baseCurrency; + const userId = user.id; - const days = differenceInDays(endDate, startDate) + 1; - const dates = eachDayOfInterval( - { - start: startDate, - end: endDate - }, - { - step: Math.round( - days / - Math.min(days, this.configurationService.get('MAX_CHART_ITEMS')) - ) - } - ).map((date) => { - return resetHours(date); + const { chart } = await this.portfolioService.getPerformance({ + dateRange, + impersonationId, + userId }); const [currentSymbolItem, marketDataItems] = await Promise.all([ @@ -200,7 +192,9 @@ export class BenchmarkService { dataSource, symbol, date: { - in: dates + in: chart.map(({ date }) => { + return resetHours(parseDate(date)); + }) } } })