Browse Source

Convert benchmark performance to base currency

pull/2790/head
Reto Kaul 2 years ago
parent
commit
24f9bfb1d0
  1. 10
      apps/api/src/app/benchmark/benchmark.controller.ts
  2. 2
      apps/api/src/app/benchmark/benchmark.module.ts
  3. 73
      apps/api/src/app/benchmark/benchmark.service.ts

10
apps/api/src/app/benchmark/benchmark.controller.ts

@ -25,10 +25,15 @@ import { DataSource } from '@prisma/client';
import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { BenchmarkService } from './benchmark.service'; import { BenchmarkService } from './benchmark.service';
import { REQUEST } from '@nestjs/core';
import { RequestWithUser } from '@ghostfolio/common/types';
@Controller('benchmark') @Controller('benchmark')
export class BenchmarkController { export class BenchmarkController {
public constructor(private readonly benchmarkService: BenchmarkService) {} public constructor(
private readonly benchmarkService: BenchmarkService,
@Inject(REQUEST) private readonly request: RequestWithUser
) {}
@HasPermission(permissions.accessAdminControl) @HasPermission(permissions.accessAdminControl)
@Post() @Post()
@ -107,7 +112,8 @@ export class BenchmarkController {
return this.benchmarkService.getMarketDataBySymbol({ return this.benchmarkService.getMarketDataBySymbol({
dataSource, dataSource,
startDate, startDate,
symbol symbol,
baseCurrency: this.request.user.Settings.settings.baseCurrency
}); });
} }
} }

2
apps/api/src/app/benchmark/benchmark.module.ts

@ -2,6 +2,7 @@ import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.mo
import { SymbolModule } from '@ghostfolio/api/app/symbol/symbol.module'; import { SymbolModule } from '@ghostfolio/api/app/symbol/symbol.module';
import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module';
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.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 { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module';
import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module';
import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; import { PropertyModule } from '@ghostfolio/api/services/property/property.module';
@ -17,6 +18,7 @@ import { BenchmarkService } from './benchmark.service';
imports: [ imports: [
ConfigurationModule, ConfigurationModule,
DataProviderModule, DataProviderModule,
ExchangeRateDataModule,
MarketDataModule, MarketDataModule,
PrismaModule, PrismaModule,
PropertyModule, PropertyModule,

73
apps/api/src/app/benchmark/benchmark.service.ts

@ -1,6 +1,7 @@
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
import { SymbolService } from '@ghostfolio/api/app/symbol/symbol.service'; import { SymbolService } from '@ghostfolio/api/app/symbol/symbol.service';
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.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'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service';
@ -25,7 +26,7 @@ import { Injectable } from '@nestjs/common';
import { SymbolProfile } from '@prisma/client'; import { SymbolProfile } from '@prisma/client';
import Big from 'big.js'; import Big from 'big.js';
import { format, subDays } from 'date-fns'; import { format, subDays } from 'date-fns';
import { uniqBy } from 'lodash'; import { isNumber, uniqBy } from 'lodash';
import ms from 'ms'; import ms from 'ms';
@Injectable() @Injectable()
@ -34,6 +35,7 @@ export class BenchmarkService {
public constructor( public constructor(
private readonly dataProviderService: DataProviderService, private readonly dataProviderService: DataProviderService,
private readonly exchangeRateDataService: ExchangeRateDataService,
private readonly marketDataService: MarketDataService, private readonly marketDataService: MarketDataService,
private readonly prismaService: PrismaService, private readonly prismaService: PrismaService,
private readonly propertyService: PropertyService, private readonly propertyService: PropertyService,
@ -201,10 +203,14 @@ export class BenchmarkService {
} }
public async getMarketDataBySymbol({ public async getMarketDataBySymbol({
baseCurrency,
dataSource, dataSource,
startDate, startDate,
symbol symbol
}: { startDate: Date } & UniqueAsset): Promise<BenchmarkMarketDataDetails> { }: {
baseCurrency: string;
startDate: Date;
} & UniqueAsset): Promise<BenchmarkMarketDataDetails> {
const [currentSymbolItem, marketDataItems] = await Promise.all([ const [currentSymbolItem, marketDataItems] = await Promise.all([
this.symbolService.get({ this.symbolService.get({
dataGatheringItem: { dataGatheringItem: {
@ -226,44 +232,75 @@ export class BenchmarkService {
}) })
]); ]);
const exchangeRateAtStartDate =
await this.exchangeRateDataService.toCurrencyAtDate(
1,
currentSymbolItem.currency,
baseCurrency,
startDate
);
const step = Math.round( const step = Math.round(
marketDataItems.length / Math.min(marketDataItems.length, MAX_CHART_ITEMS) marketDataItems.length / Math.min(marketDataItems.length, MAX_CHART_ITEMS)
); );
const marketPriceAtStartDate = marketDataItems?.[0]?.marketPrice ?? 0; const marketPriceAtStartDate = marketDataItems?.[0]?.marketPrice ?? 0;
const response = { const marketData: { date: string; value: number }[] = [];
marketData: [
...marketDataItems let i = 0;
.filter((marketDataItem, index) => { for (let marketDataItem of marketDataItems) {
return index % step === 0; if (i % step != 0) {
}) continue;
.map((marketDataItem) => { }
return {
const exchangeRate = await this.exchangeRateDataService.toCurrencyAtDate(
1,
currentSymbolItem.currency,
baseCurrency,
marketDataItem.date
);
const exchangeRateFactor = isNumber(exchangeRate)
? exchangeRate / exchangeRateAtStartDate
: 1;
marketData.push({
date: format(marketDataItem.date, DATE_FORMAT), date: format(marketDataItem.date, DATE_FORMAT),
value: value:
marketPriceAtStartDate === 0 marketPriceAtStartDate === 0
? 0 ? 0
: this.calculateChangeInPercentage( : this.calculateChangeInPercentage(
marketPriceAtStartDate, marketPriceAtStartDate,
marketDataItem.marketPrice marketDataItem.marketPrice * exchangeRateFactor
) * 100 ) * 100
}; });
}) }
]
};
if (currentSymbolItem?.marketPrice) { if (currentSymbolItem?.marketPrice) {
response.marketData.push({ const exchangeRate = await this.exchangeRateDataService.toCurrencyAtDate(
1,
currentSymbolItem.currency,
baseCurrency,
new Date()
);
const exchangeRateFactor = isNumber(exchangeRate)
? exchangeRate / exchangeRateAtStartDate
: 1;
marketData.push({
date: format(new Date(), DATE_FORMAT), date: format(new Date(), DATE_FORMAT),
value: value:
this.calculateChangeInPercentage( this.calculateChangeInPercentage(
marketPriceAtStartDate, marketPriceAtStartDate,
currentSymbolItem.marketPrice currentSymbolItem.marketPrice * exchangeRateFactor
) * 100 ) * 100
}); });
} }
return response; return {
marketData
};
} }
public async addBenchmark({ public async addBenchmark({

Loading…
Cancel
Save