Browse Source

Introduce getExchangeRates() for multiple dates

pull/2790/head
Thomas Kaul 2 years ago
parent
commit
a7d6fce98b
  1. 4
      apps/api/src/app/benchmark/benchmark.controller.ts
  2. 32
      apps/api/src/app/benchmark/benchmark.service.ts
  3. 108
      apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts

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

@ -8,6 +8,7 @@ import type {
UniqueAsset
} from '@ghostfolio/common/interfaces';
import { permissions } from '@ghostfolio/common/permissions';
import type { RequestWithUser } from '@ghostfolio/common/types';
import {
Body,
Controller,
@ -20,13 +21,12 @@ import {
UseGuards,
UseInterceptors
} from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { DataSource } from '@prisma/client';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { BenchmarkService } from './benchmark.service';
import { REQUEST } from '@nestjs/core';
import { RequestWithUser } from '@ghostfolio/common/types';
@Controller('benchmark')
export class BenchmarkController {

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

@ -232,13 +232,16 @@ export class BenchmarkService {
})
]);
const exchangeRates = await this.exchangeRateDataService.getExchangeRates({
currencyFrom: currentSymbolItem.currency,
currencyTo: baseCurrency,
dates: marketDataItems.map(({ date }) => {
return format(date, DATE_FORMAT);
})
});
const exchangeRateAtStartDate =
await this.exchangeRateDataService.toCurrencyAtDate(
1,
currentSymbolItem.currency,
baseCurrency,
startDate
);
exchangeRates[format(startDate, DATE_FORMAT)];
const step = Math.round(
marketDataItems.length / Math.min(marketDataItems.length, MAX_CHART_ITEMS)
@ -249,16 +252,12 @@ export class BenchmarkService {
let i = 0;
for (let marketDataItem of marketDataItems) {
if (i % step != 0) {
if (i % step !== 0) {
continue;
}
const exchangeRate = await this.exchangeRateDataService.toCurrencyAtDate(
1,
currentSymbolItem.currency,
baseCurrency,
marketDataItem.date
);
const exchangeRate =
exchangeRates[format(marketDataItem.date, DATE_FORMAT)];
const exchangeRateFactor =
isNumber(exchangeRateAtStartDate) && isNumber(exchangeRate)
@ -278,12 +277,7 @@ export class BenchmarkService {
}
if (currentSymbolItem?.marketPrice) {
const exchangeRate = await this.exchangeRateDataService.toCurrencyAtDate(
1,
currentSymbolItem.currency,
baseCurrency,
new Date()
);
const exchangeRate = exchangeRates[format(new Date(), DATE_FORMAT)];
const exchangeRateFactor =
isNumber(exchangeRateAtStartDate) && isNumber(exchangeRate)

108
apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts

@ -7,7 +7,11 @@ import {
DEFAULT_CURRENCY,
PROPERTY_CURRENCIES
} from '@ghostfolio/common/config';
import { DATE_FORMAT, getYesterday } from '@ghostfolio/common/helper';
import {
DATE_FORMAT,
getYesterday,
parseDate
} from '@ghostfolio/common/helper';
import { Injectable, Logger } from '@nestjs/common';
import { format, isToday } from 'date-fns';
import { isNumber, uniq } from 'lodash';
@ -33,6 +37,108 @@ export class ExchangeRateDataService {
return this.currencyPairs;
}
public async getExchangeRates({
currencyFrom,
currencyTo,
dates
}: {
currencyFrom: string;
currencyTo: string;
dates: string[];
}) {
let factors: { [dateString: string]: number } = {};
const startDate = parseDate(dates[0]);
if (currencyFrom === currencyTo) {
for (const date of dates) {
factors[date] = 1;
}
} else {
const dataSource =
this.dataProviderService.getDataSourceForExchangeRates();
const symbol = `${currencyFrom}${currencyTo}`;
const marketData = await this.marketDataService.getRange({
dateQuery: { gte: startDate },
uniqueAssets: [
{
dataSource,
symbol
}
]
});
if (marketData?.length > 0) {
for (const { date, marketPrice } of marketData) {
factors[format(date, DATE_FORMAT)] = marketPrice;
}
} else {
// Calculate indirectly via base currency
let marketPriceBaseCurrencyFromCurrency: {
[dateString: string]: number;
} = {};
let marketPriceBaseCurrencyToCurrency: {
[dateString: string]: number;
} = {};
try {
if (currencyFrom === DEFAULT_CURRENCY) {
for (const date of dates) {
marketPriceBaseCurrencyFromCurrency[date] = 1;
}
} else {
const marketData = await this.marketDataService.getRange({
dateQuery: { gte: startDate },
uniqueAssets: [
{
dataSource,
symbol: `${DEFAULT_CURRENCY}${currencyFrom}`
}
]
});
for (const { date, marketPrice } of marketData) {
marketPriceBaseCurrencyFromCurrency[format(date, DATE_FORMAT)] =
marketPrice;
}
}
} catch {}
try {
if (currencyTo === DEFAULT_CURRENCY) {
for (const date of dates) {
marketPriceBaseCurrencyToCurrency[date] = 1;
}
} else {
const marketData = await this.marketDataService.getRange({
dateQuery: { gte: startDate },
uniqueAssets: [
{
dataSource,
symbol: `${DEFAULT_CURRENCY}${currencyTo}`
}
]
});
for (const { date, marketPrice } of marketData) {
marketPriceBaseCurrencyToCurrency[format(date, DATE_FORMAT)] =
marketPrice;
}
}
} catch {}
for (const date of dates) {
factors[date] =
(1 / marketPriceBaseCurrencyFromCurrency[date]) *
marketPriceBaseCurrencyToCurrency[date];
}
}
}
return factors;
}
public hasCurrencyPair(currency1: string, currency2: string) {
return this.currencyPairs.some(({ symbol }) => {
return (

Loading…
Cancel
Save