From ac633051b876af4376a5e7fe19e17086459cb09b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 17 Jan 2024 18:05:34 +0100 Subject: [PATCH] Improve handling of derived currencies --- .../data-provider/data-provider.service.ts | 100 ++++++++++++++++-- .../eod-historical-data.service.ts | 54 +--------- .../yahoo-finance/yahoo-finance.service.ts | 2 + .../exchange-rate-data.service.ts | 50 ++++----- 4 files changed, 118 insertions(+), 88 deletions(-) diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts index aee33d729..8397f7902 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -9,12 +9,16 @@ import { import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; -import { PROPERTY_DATA_SOURCE_MAPPING } from '@ghostfolio/common/config'; +import { + DEFAULT_CURRENCY, + PROPERTY_DATA_SOURCE_MAPPING +} from '@ghostfolio/common/config'; import { DATE_FORMAT, getStartOfUtcDate } from '@ghostfolio/common/helper'; import { UniqueAsset } from '@ghostfolio/common/interfaces'; import type { Granularity, UserWithSettings } from '@ghostfolio/common/types'; import { Inject, Injectable, Logger } from '@nestjs/common'; import { DataSource, MarketData, SymbolProfile } from '@prisma/client'; +import Big from 'big.js'; import { format, isValid } from 'date-fns'; import { groupBy, isEmpty, isNumber } from 'lodash'; import ms from 'ms'; @@ -205,6 +209,8 @@ export class DataProviderService { ): Promise<{ [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; }> { + // TODO + const result: { [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; } = {}; @@ -326,19 +332,99 @@ export class DataProviderService { promises.push( promise.then(async (result) => { - for (const [symbol, dataProviderResponse] of Object.entries( - result - )) { + for (let [symbol, dataProviderResponse] of Object.entries(result)) { + if (symbol === `${DEFAULT_CURRENCY}USX`) { + dataProviderResponse = { + ...dataProviderResponse, + marketPrice: new Big(1).mul(100).toNumber(), + marketState: 'open' + }; + } + + if ( + [ + `${DEFAULT_CURRENCY}GBp`, + `${DEFAULT_CURRENCY}ILA`, + `${DEFAULT_CURRENCY}ZAc` + ].includes(symbol) + ) { + continue; + } + response[symbol] = dataProviderResponse; this.redisCacheService.set( this.redisCacheService.getQuoteKey({ - dataSource: DataSource[dataSource], - symbol + symbol, + dataSource: DataSource[dataSource] }), - JSON.stringify(dataProviderResponse), + JSON.stringify(response[symbol]), this.configurationService.get('CACHE_QUOTES_TTL') ); + + if (symbol === `${DEFAULT_CURRENCY}GBP`) { + response[`${DEFAULT_CURRENCY}GBp`] = { + ...dataProviderResponse, + currency: 'GBp', + marketPrice: new Big( + result[`${DEFAULT_CURRENCY}GBP`].marketPrice + ) + .mul(100) + .toNumber(), + marketState: 'open' + }; + + this.redisCacheService.set( + this.redisCacheService.getQuoteKey({ + dataSource: DataSource[dataSource], + symbol: `${DEFAULT_CURRENCY}GBp` + }), + JSON.stringify(response[`${DEFAULT_CURRENCY}GBp`]), + this.configurationService.get('CACHE_QUOTES_TTL') + ); + } else if (symbol === `${DEFAULT_CURRENCY}ILS`) { + response[`${DEFAULT_CURRENCY}ILA`] = { + ...dataProviderResponse, + currency: 'ILA', + marketPrice: new Big( + result[`${DEFAULT_CURRENCY}ILS`].marketPrice + ) + .mul(100) + .toNumber(), + marketState: 'open' + }; + + this.redisCacheService.set( + this.redisCacheService.getQuoteKey({ + dataSource: DataSource[dataSource], + symbol: `${DEFAULT_CURRENCY}ILA` + }), + JSON.stringify(response[`${DEFAULT_CURRENCY}ILA`]), + this.configurationService.get('CACHE_QUOTES_TTL') + ); + } else if (symbol === `${DEFAULT_CURRENCY}ZAR`) { + response[`${DEFAULT_CURRENCY}ZAc`] = { + ...dataProviderResponse, + currency: 'ZAc', + marketPrice: new Big( + result[`${DEFAULT_CURRENCY}ZAR`].marketPrice + ) + .mul(100) + .toNumber(), + marketState: 'open' + }; + + this.redisCacheService.set( + this.redisCacheService.getQuoteKey({ + dataSource: DataSource[dataSource], + symbol: `${DEFAULT_CURRENCY}ZAc` + }), + JSON.stringify(response[`${DEFAULT_CURRENCY}ZAc`]), + this.configurationService.get('CACHE_QUOTES_TTL') + ); + } + + console.log({ response }); } Logger.debug( diff --git a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts index 173994df7..797389a6c 100644 --- a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts +++ b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts @@ -196,48 +196,6 @@ export class EodHistoricalDataService implements DataProviderInterface { {} ); - if (response[`${DEFAULT_CURRENCY}GBP`]) { - response[`${DEFAULT_CURRENCY}GBp`] = { - ...response[`${DEFAULT_CURRENCY}GBP`], - currency: 'GBp', - marketPrice: this.getConvertedValue({ - symbol: `${DEFAULT_CURRENCY}GBp`, - value: response[`${DEFAULT_CURRENCY}GBP`].marketPrice - }) - }; - } - - if (response[`${DEFAULT_CURRENCY}ILS`]) { - response[`${DEFAULT_CURRENCY}ILA`] = { - ...response[`${DEFAULT_CURRENCY}ILS`], - currency: 'ILA', - marketPrice: this.getConvertedValue({ - symbol: `${DEFAULT_CURRENCY}ILA`, - value: response[`${DEFAULT_CURRENCY}ILS`].marketPrice - }) - }; - } - - if (response[`${DEFAULT_CURRENCY}USX`]) { - response[`${DEFAULT_CURRENCY}USX`] = { - currency: 'USX', - dataSource: this.getName(), - marketPrice: new Big(1).mul(100).toNumber(), - marketState: 'open' - }; - } - - if (response[`${DEFAULT_CURRENCY}ZAR`]) { - response[`${DEFAULT_CURRENCY}ZAc`] = { - ...response[`${DEFAULT_CURRENCY}ZAR`], - currency: 'ZAc', - marketPrice: this.getConvertedValue({ - symbol: `${DEFAULT_CURRENCY}ZAc`, - value: response[`${DEFAULT_CURRENCY}ZAR`].marketPrice - }) - }; - } - return response; } catch (error) { let message = error; @@ -337,6 +295,7 @@ export class EodHistoricalDataService implements DataProviderInterface { return aSymbol; } + // TODO: Eliminate private getConvertedValue({ symbol, value @@ -344,17 +303,6 @@ export class EodHistoricalDataService implements DataProviderInterface { symbol: string; value: number; }) { - if (symbol === `${DEFAULT_CURRENCY}GBp`) { - // Convert GPB to GBp (pence) - return new Big(value).mul(100).toNumber(); - } else if (symbol === `${DEFAULT_CURRENCY}ILA`) { - // Convert ILS to ILA - return new Big(value).mul(100).toNumber(); - } else if (symbol === `${DEFAULT_CURRENCY}ZAc`) { - // Convert ZAR to ZAc - return new Big(value).mul(100).toNumber(); - } - return value; } diff --git a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts index e027c227f..04c3934cf 100644 --- a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts @@ -1,3 +1,5 @@ +// TODO + import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface'; import { CryptocurrencyService } from '@ghostfolio/api/services/cryptocurrency/cryptocurrency.service'; import { YahooFinanceDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service'; 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 36dd5c0a2..953a3dcd5 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 @@ -168,30 +168,6 @@ export class ExchangeRateDataService { const [currency1, currency2] = symbol.match(/.{1,3}/g); const [date] = Object.keys(result[symbol]); - // Add derived currencies - if (currency2 === 'GBP') { - resultExtended[`${currency1}GBp`] = { - [date]: { - marketPrice: - result[`${currency1}${currency2}`][date].marketPrice * 100 - } - }; - } else if (currency2 === 'ILS') { - resultExtended[`${currency1}ILA`] = { - [date]: { - marketPrice: - result[`${currency1}${currency2}`][date].marketPrice * 100 - } - }; - } else if (currency2 === 'ZAR') { - resultExtended[`${currency1}ZAc`] = { - [date]: { - marketPrice: - result[`${currency1}${currency2}`][date].marketPrice * 100 - } - }; - } - // Calculate the opposite direction resultExtended[`${currency2}${currency1}`] = { [date]: { @@ -486,8 +462,8 @@ export class ExchangeRateDataService { } } }) - ).forEach((account) => { - currencies.push(account.currency); + ).forEach(({ currency }) => { + currencies.push(currency); }); ( @@ -496,8 +472,8 @@ export class ExchangeRateDataService { orderBy: [{ currency: 'asc' }], select: { currency: true } }) - ).forEach((symbolProfile) => { - currencies.push(symbolProfile.currency); + ).forEach(({ currency }) => { + currencies.push(currency); }); const customCurrencies = (await this.propertyService.getByKey( @@ -508,6 +484,24 @@ export class ExchangeRateDataService { currencies = currencies.concat(customCurrencies); } + // Add derived currencies + currencies.push('USX'); + + if (currencies.includes('GBP') || currencies.includes('GBp')) { + currencies.push('GBP'); + currencies.push('GBp'); + } + + if (currencies.includes('ILS') || currencies.includes('ILA')) { + currencies.push('ILS'); + currencies.push('ILA'); + } + + if (currencies.includes('ZAR') || currencies.includes('ZAc')) { + currencies.push('ZAR'); + currencies.push('ZAc'); + } + return uniq(currencies).filter(Boolean).sort(); }