|  |  | @ -13,7 +13,8 @@ import { | 
			
		
	
		
			
				
					|  |  |  | import { | 
			
		
	
		
			
				
					|  |  |  |   DATE_FORMAT, | 
			
		
	
		
			
				
					|  |  |  |   calculateBenchmarkTrend, | 
			
		
	
		
			
				
					|  |  |  |   parseDate | 
			
		
	
		
			
				
					|  |  |  |   parseDate, | 
			
		
	
		
			
				
					|  |  |  |   resetHours | 
			
		
	
		
			
				
					|  |  |  | } from '@ghostfolio/common/helper'; | 
			
		
	
		
			
				
					|  |  |  | import { | 
			
		
	
		
			
				
					|  |  |  |   Benchmark, | 
			
		
	
	
		
			
				
					|  |  | @ -27,7 +28,13 @@ import { BenchmarkTrend } from '@ghostfolio/common/types'; | 
			
		
	
		
			
				
					|  |  |  | import { Injectable, Logger } from '@nestjs/common'; | 
			
		
	
		
			
				
					|  |  |  | import { SymbolProfile } from '@prisma/client'; | 
			
		
	
		
			
				
					|  |  |  | import { Big } from 'big.js'; | 
			
		
	
		
			
				
					|  |  |  | import { format, isSameDay, subDays } from 'date-fns'; | 
			
		
	
		
			
				
					|  |  |  | import { | 
			
		
	
		
			
				
					|  |  |  |   differenceInDays, | 
			
		
	
		
			
				
					|  |  |  |   eachDayOfInterval, | 
			
		
	
		
			
				
					|  |  |  |   format, | 
			
		
	
		
			
				
					|  |  |  |   isSameDay, | 
			
		
	
		
			
				
					|  |  |  |   subDays | 
			
		
	
		
			
				
					|  |  |  | } from 'date-fns'; | 
			
		
	
		
			
				
					|  |  |  | import { isNumber, last, uniqBy } from 'lodash'; | 
			
		
	
		
			
				
					|  |  |  | import ms from 'ms'; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -208,15 +215,28 @@ export class BenchmarkService { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   public async getMarketDataBySymbol({ | 
			
		
	
		
			
				
					|  |  |  |     dataSource, | 
			
		
	
		
			
				
					|  |  |  |     endDate = new Date(), | 
			
		
	
		
			
				
					|  |  |  |     startDate, | 
			
		
	
		
			
				
					|  |  |  |     symbol, | 
			
		
	
		
			
				
					|  |  |  |     userCurrency | 
			
		
	
		
			
				
					|  |  |  |   }: { | 
			
		
	
		
			
				
					|  |  |  |     endDate?: Date; | 
			
		
	
		
			
				
					|  |  |  |     startDate: Date; | 
			
		
	
		
			
				
					|  |  |  |     userCurrency: string; | 
			
		
	
		
			
				
					|  |  |  |   } & UniqueAsset): Promise<BenchmarkMarketDataDetails> { | 
			
		
	
		
			
				
					|  |  |  |     const marketData: { date: string; value: number }[] = []; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const days = differenceInDays(endDate, startDate) + 1; | 
			
		
	
		
			
				
					|  |  |  |     const dates = eachDayOfInterval( | 
			
		
	
		
			
				
					|  |  |  |       { | 
			
		
	
		
			
				
					|  |  |  |         start: startDate, | 
			
		
	
		
			
				
					|  |  |  |         end: endDate | 
			
		
	
		
			
				
					|  |  |  |       }, | 
			
		
	
		
			
				
					|  |  |  |       { step: Math.round(days / Math.min(days, MAX_CHART_ITEMS)) } | 
			
		
	
		
			
				
					|  |  |  |     ).map((date) => { | 
			
		
	
		
			
				
					|  |  |  |       return resetHours(date); | 
			
		
	
		
			
				
					|  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const [currentSymbolItem, marketDataItems] = await Promise.all([ | 
			
		
	
		
			
				
					|  |  |  |       this.symbolService.get({ | 
			
		
	
		
			
				
					|  |  |  |         dataGatheringItem: { | 
			
		
	
	
		
			
				
					|  |  | @ -232,7 +252,7 @@ export class BenchmarkService { | 
			
		
	
		
			
				
					|  |  |  |           dataSource, | 
			
		
	
		
			
				
					|  |  |  |           symbol, | 
			
		
	
		
			
				
					|  |  |  |           date: { | 
			
		
	
		
			
				
					|  |  |  |             gte: startDate | 
			
		
	
		
			
				
					|  |  |  |             in: dates | 
			
		
	
		
			
				
					|  |  |  |           } | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |       }) | 
			
		
	
	
		
			
				
					|  |  | @ -266,17 +286,7 @@ export class BenchmarkService { | 
			
		
	
		
			
				
					|  |  |  |       return { marketData }; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const step = Math.round( | 
			
		
	
		
			
				
					|  |  |  |       marketDataItems.length / Math.min(marketDataItems.length, MAX_CHART_ITEMS) | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let i = 0; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     for (let marketDataItem of marketDataItems) { | 
			
		
	
		
			
				
					|  |  |  |       if (i % step !== 0) { | 
			
		
	
		
			
				
					|  |  |  |         continue; | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       const exchangeRate = | 
			
		
	
		
			
				
					|  |  |  |         exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[ | 
			
		
	
		
			
				
					|  |  |  |           format(marketDataItem.date, DATE_FORMAT) | 
			
		
	
	
		
			
				
					|  |  | @ -299,15 +309,15 @@ export class BenchmarkService { | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const includesToday = isSameDay( | 
			
		
	
		
			
				
					|  |  |  |     const includesEndDate = isSameDay( | 
			
		
	
		
			
				
					|  |  |  |       parseDate(last(marketData).date), | 
			
		
	
		
			
				
					|  |  |  |       new Date() | 
			
		
	
		
			
				
					|  |  |  |       endDate | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (currentSymbolItem?.marketPrice && !includesToday) { | 
			
		
	
		
			
				
					|  |  |  |     if (currentSymbolItem?.marketPrice && !includesEndDate) { | 
			
		
	
		
			
				
					|  |  |  |       const exchangeRate = | 
			
		
	
		
			
				
					|  |  |  |         exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[ | 
			
		
	
		
			
				
					|  |  |  |           format(new Date(), DATE_FORMAT) | 
			
		
	
		
			
				
					|  |  |  |           format(endDate, DATE_FORMAT) | 
			
		
	
		
			
				
					|  |  |  |         ]; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       const exchangeRateFactor = | 
			
		
	
	
		
			
				
					|  |  | @ -316,7 +326,7 @@ export class BenchmarkService { | 
			
		
	
		
			
				
					|  |  |  |           : 1; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       marketData.push({ | 
			
		
	
		
			
				
					|  |  |  |         date: format(new Date(), DATE_FORMAT), | 
			
		
	
		
			
				
					|  |  |  |         date: format(endDate, DATE_FORMAT), | 
			
		
	
		
			
				
					|  |  |  |         value: | 
			
		
	
		
			
				
					|  |  |  |           this.calculateChangeInPercentage( | 
			
		
	
		
			
				
					|  |  |  |             marketPriceAtStartDate, | 
			
		
	
	
		
			
				
					|  |  | 
 |