From 07fac08405c50e1cfd28e0fffa57774a31bdcbbb Mon Sep 17 00:00:00 2001 From: Dhoni77 Date: Wed, 1 Nov 2023 22:20:45 +0530 Subject: [PATCH] feat: extend the benchmark --- .../src/app/benchmark/benchmark.service.ts | 64 +++++++++++++++---- .../market-data/market-data.service.ts | 4 +- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/apps/api/src/app/benchmark/benchmark.service.ts b/apps/api/src/app/benchmark/benchmark.service.ts index 2547e57cc..8c0f6c8c2 100644 --- a/apps/api/src/app/benchmark/benchmark.service.ts +++ b/apps/api/src/app/benchmark/benchmark.service.ts @@ -9,17 +9,21 @@ import { MAX_CHART_ITEMS, PROPERTY_BENCHMARKS } from '@ghostfolio/common/config'; -import { DATE_FORMAT } from '@ghostfolio/common/helper'; +import { + DATE_FORMAT, + calculateBenchmarkTrend, +} from '@ghostfolio/common/helper'; import { BenchmarkMarketDataDetails, BenchmarkProperty, BenchmarkResponse, UniqueAsset } from '@ghostfolio/common/interfaces'; -import { Injectable } from '@nestjs/common'; -import { SymbolProfile } from '@prisma/client'; +import { BenchmarkTrend } from '@ghostfolio/common/types/benchmark-trend-type.type'; +import { Injectable, Logger } from '@nestjs/common'; +import { DataSource, SymbolProfile } from '@prisma/client'; import Big from 'big.js'; -import { format } from 'date-fns'; +import { format, subDays } from 'date-fns'; import { uniqBy } from 'lodash'; import ms from 'ms'; @@ -35,7 +39,7 @@ export class BenchmarkService { private readonly redisCacheService: RedisCacheService, private readonly symbolProfileService: SymbolProfileService, private readonly symbolService: SymbolService - ) {} + ) { } public calculateChangeInPercentage(baseValue: number, currentValue: number) { if (baseValue && currentValue) { @@ -45,6 +49,31 @@ export class BenchmarkService { return 0; } + public async getBenchMarkTrends(dataSource: DataSource, symbol: string) { + return this.marketDataService + .marketDataItems({ + orderBy: { + date: 'desc' + }, + select: { + date: true, + marketPrice: true + }, + where: { + dataSource, + symbol, + date: { gte: subDays(new Date(), 400) } + } + }) + .then((historicalData) => { + const fiftyDayAvg = calculateBenchmarkTrend(historicalData, 50); + const twoHundrredDayAvg = calculateBenchmarkTrend(historicalData, 200); + Logger.debug(`50d: ${fiftyDayAvg} and 200d: ${twoHundrredDayAvg}`); + + return { trend200d: twoHundrredDayAvg, trend50d: fiftyDayAvg }; + }); + } + public async getBenchmarks({ useCache = true } = {}): Promise< BenchmarkResponse['benchmarks'] > { @@ -59,12 +88,16 @@ export class BenchmarkService { if (benchmarks) { return benchmarks; } - } catch {} + } catch { } } const benchmarkAssetProfiles = await this.getBenchmarkAssetProfiles(); const promises: Promise<{ date: Date; marketPrice: number }>[] = []; + const movingAvgPromises: Promise<{ + trend50d: BenchmarkTrend; + trend200d: BenchmarkTrend; + }>[] = []; const quotes = await this.dataProviderService.getQuotes({ items: benchmarkAssetProfiles.map(({ dataSource, symbol }) => { @@ -74,9 +107,13 @@ export class BenchmarkService { for (const { dataSource, symbol } of benchmarkAssetProfiles) { promises.push(this.marketDataService.getMax({ dataSource, symbol })); + movingAvgPromises.push(this.getBenchMarkTrends(dataSource, symbol)); } - const allTimeHighs = await Promise.all(promises); + const [allTimeHighs, benchmarkTrends] = await Promise.all([ + Promise.all(promises), + Promise.all(movingAvgPromises) + ]); let storeInCache = true; benchmarks = allTimeHighs.map((allTimeHigh, index) => { @@ -93,6 +130,7 @@ export class BenchmarkService { } else { storeInCache = false; } + return { marketCondition: this.getMarketCondition( performancePercentFromAllTimeHigh @@ -100,8 +138,10 @@ export class BenchmarkService { name: benchmarkAssetProfiles[index].name, performances: { allTimeHigh: { - date: allTimeHigh.date, - performancePercent: performancePercentFromAllTimeHigh + date: allTimeHigh?.date || new Date(), + performancePercent: performancePercentFromAllTimeHigh, + trend50d: benchmarkTrends[index].trend50d, + trend200d: benchmarkTrends[index].trend200d } } }; @@ -186,9 +226,9 @@ export class BenchmarkService { marketPriceAtStartDate === 0 ? 0 : this.calculateChangeInPercentage( - marketPriceAtStartDate, - marketDataItem.marketPrice - ) * 100 + marketPriceAtStartDate, + marketDataItem.marketPrice + ) * 100 }; }) ] diff --git a/apps/api/src/services/market-data/market-data.service.ts b/apps/api/src/services/market-data/market-data.service.ts index 52c833784..01f8bb9aa 100644 --- a/apps/api/src/services/market-data/market-data.service.ts +++ b/apps/api/src/services/market-data/market-data.service.ts @@ -90,15 +90,17 @@ export class MarketDataService { } public async marketDataItems(params: { + select?: Prisma.MarketDataSelectScalar; skip?: number; take?: number; cursor?: Prisma.MarketDataWhereUniqueInput; where?: Prisma.MarketDataWhereInput; orderBy?: Prisma.MarketDataOrderByWithRelationInput; }): Promise { - const { skip, take, cursor, where, orderBy } = params; + const { select, skip, take, cursor, where, orderBy } = params; return this.prismaService.marketData.findMany({ + select, cursor, orderBy, skip,