diff --git a/apps/api/src/app/benchmark/benchmark.service.ts b/apps/api/src/app/benchmark/benchmark.service.ts index 9609183ab..696e2f511 100644 --- a/apps/api/src/app/benchmark/benchmark.service.ts +++ b/apps/api/src/app/benchmark/benchmark.service.ts @@ -235,14 +235,17 @@ export class BenchmarkService { }) ]); - const exchangeRates = await this.exchangeRateDataService.getExchangeRates({ - startDate, - currencyFrom: currentSymbolItem.currency, - currencyTo: userCurrency - }); + const exchangeRates = + await this.exchangeRateDataService.getExchangeRatesByCurrency({ + startDate, + currencies: [currentSymbolItem.currency], + targetCurrency: userCurrency + }); const exchangeRateAtStartDate = - exchangeRates[format(startDate, DATE_FORMAT)]; + exchangeRates[currentSymbolItem.currency]?.[ + format(startDate, DATE_FORMAT) + ]; if (!exchangeRateAtStartDate) { Logger.error( diff --git a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts index 4c29c8ae1..f9c9874b5 100644 --- a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts +++ b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts @@ -57,7 +57,7 @@ export class ExchangeRateDataService { [currency: string]: { [dateString: string]: number }; } = {}; - for (let currency of uniq(currencies)) { + for (let currency of currencies) { exchangeRatesByCurrency[currency] = await this.getExchangeRates({ startDate, currencyFrom: currency, @@ -83,129 +83,6 @@ export class ExchangeRateDataService { return exchangeRatesByCurrency; } - public async getExchangeRates({ - currencyFrom, - currencyTo, - endDate = new Date(), - startDate - }: { - currencyFrom: string; - currencyTo: string; - endDate?: Date; - startDate: Date; - }) { - const dates = eachDayOfInterval({ end: endDate, start: startDate }); - let factors: { [dateString: string]: number } = {}; - - if (currencyFrom === currencyTo) { - for (const date of dates) { - factors[format(date, DATE_FORMAT)] = 1; - } - } else { - const dataSource = - this.dataProviderService.getDataSourceForExchangeRates(); - const symbol = `${currencyFrom}${currencyTo}`; - - const marketData = await this.marketDataService.getRange({ - dateQuery: { gte: startDate, lt: endDate }, - 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[format(date, DATE_FORMAT)] = - 1; - } - } else { - const marketData = await this.marketDataService.getRange({ - dateQuery: { gte: startDate, lt: endDate }, - 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[format(date, DATE_FORMAT)] = 1; - } - } else { - const marketData = await this.marketDataService.getRange({ - dateQuery: { - gte: startDate, - lt: endDate - }, - uniqueAssets: [ - { - dataSource, - symbol: `${DEFAULT_CURRENCY}${currencyTo}` - } - ] - }); - - for (const { date, marketPrice } of marketData) { - marketPriceBaseCurrencyToCurrency[format(date, DATE_FORMAT)] = - marketPrice; - } - } - } catch {} - - for (const date of dates) { - try { - const factor = - (1 / - marketPriceBaseCurrencyFromCurrency[ - format(date, DATE_FORMAT) - ]) * - marketPriceBaseCurrencyToCurrency[format(date, DATE_FORMAT)]; - - factors[format(date, DATE_FORMAT)] = factor; - } catch { - Logger.error( - `No exchange rate has been found for ${currencyFrom}${currencyTo} at ${format( - date, - DATE_FORMAT - )}`, - 'ExchangeRateDataService' - ); - } - } - } - } - - return factors; - } - public hasCurrencyPair(currency1: string, currency2: string) { return this.currencyPairs.some(({ symbol }) => { return ( @@ -449,6 +326,129 @@ export class ExchangeRateDataService { return undefined; } + private async getExchangeRates({ + currencyFrom, + currencyTo, + endDate = new Date(), + startDate + }: { + currencyFrom: string; + currencyTo: string; + endDate?: Date; + startDate: Date; + }) { + const dates = eachDayOfInterval({ end: endDate, start: startDate }); + let factors: { [dateString: string]: number } = {}; + + if (currencyFrom === currencyTo) { + for (const date of dates) { + factors[format(date, DATE_FORMAT)] = 1; + } + } else { + const dataSource = + this.dataProviderService.getDataSourceForExchangeRates(); + const symbol = `${currencyFrom}${currencyTo}`; + + const marketData = await this.marketDataService.getRange({ + dateQuery: { gte: startDate, lt: endDate }, + 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[format(date, DATE_FORMAT)] = + 1; + } + } else { + const marketData = await this.marketDataService.getRange({ + dateQuery: { gte: startDate, lt: endDate }, + 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[format(date, DATE_FORMAT)] = 1; + } + } else { + const marketData = await this.marketDataService.getRange({ + dateQuery: { + gte: startDate, + lt: endDate + }, + uniqueAssets: [ + { + dataSource, + symbol: `${DEFAULT_CURRENCY}${currencyTo}` + } + ] + }); + + for (const { date, marketPrice } of marketData) { + marketPriceBaseCurrencyToCurrency[format(date, DATE_FORMAT)] = + marketPrice; + } + } + } catch {} + + for (const date of dates) { + try { + const factor = + (1 / + marketPriceBaseCurrencyFromCurrency[ + format(date, DATE_FORMAT) + ]) * + marketPriceBaseCurrencyToCurrency[format(date, DATE_FORMAT)]; + + factors[format(date, DATE_FORMAT)] = factor; + } catch { + Logger.error( + `No exchange rate has been found for ${currencyFrom}${currencyTo} at ${format( + date, + DATE_FORMAT + )}`, + 'ExchangeRateDataService' + ); + } + } + } + } + + return factors; + } + private async prepareCurrencies(): Promise { let currencies: string[] = [];