diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts index 8731e709c..1da1b74e4 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts @@ -10,6 +10,7 @@ import { Prisma, SymbolProfile } from '@prisma/client'; +import { isISIN } from 'class-validator'; import { countries } from 'countries-list'; import yahooFinance from 'yahoo-finance2'; import type { Price } from 'yahoo-finance2/dist/esm/src/modules/quoteSummary-iface'; @@ -20,8 +21,18 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { private readonly cryptocurrencyService: CryptocurrencyService ) {} - public convertFromYahooFinanceSymbol(aYahooFinanceSymbol: string) { - let symbol = aYahooFinanceSymbol.replace( + public convertFromYahooFinanceSymbol({ + yahooFinanceSymbol, + yahooFinanceSymbolMap = {} + }: { + yahooFinanceSymbol: string; + yahooFinanceSymbolMap?: { [yahooFinanceSymbol: string]: string }; + }) { + if (yahooFinanceSymbolMap[yahooFinanceSymbol]) { + return yahooFinanceSymbolMap[yahooFinanceSymbol]; + } + + let symbol = yahooFinanceSymbol.replace( new RegExp(`-${DEFAULT_CURRENCY}$`), DEFAULT_CURRENCY ); @@ -36,11 +47,12 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { /** * Converts a symbol to a Yahoo Finance symbol * - * Currency: USDCHF -> USDCHF=X - * Cryptocurrency: BTCUSD -> BTC-USD - * DOGEUSD -> DOGE-USD + * Cryptocurrency: BTCUSD -> BTC-USD + * DOGEUSD -> DOGE-USD + * Currency: USDCHF -> USDCHF=X + * ISIN: US30303M1027 -> META */ - public convertToYahooFinanceSymbol(aSymbol: string) { + public async convertToYahooFinanceSymbol(aSymbol: string) { if ( aSymbol.includes(DEFAULT_CURRENCY) && aSymbol.length > DEFAULT_CURRENCY.length @@ -65,6 +77,11 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { `-${DEFAULT_CURRENCY}` ); } + } else if (isISIN(aSymbol)) { + try { + const { quotes } = await yahooFinance.search(aSymbol); + return quotes[0].symbol; + } catch {} } return aSymbol; @@ -156,7 +173,7 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { const response: Partial = {}; try { - const symbol = this.convertToYahooFinanceSymbol(aSymbol); + const symbol = await this.convertToYahooFinanceSymbol(aSymbol); const assetProfile = await yahooFinance.quoteSummary(symbol, { modules: ['price', 'summaryProfile', 'topHoldings'] }); 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 16d48be8e..44bfe908f 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 @@ -30,16 +30,17 @@ export class YahooFinanceService implements DataProviderInterface { public async getAssetProfile( aSymbol: string ): Promise> { - const { assetClass, assetSubClass, currency, name } = - await this.yahooFinanceDataEnhancerService.getAssetProfile(aSymbol); + let symbol = aSymbol; + let { assetClass, assetSubClass, currency, name } = + await this.yahooFinanceDataEnhancerService.getAssetProfile(symbol); return { assetClass, assetSubClass, currency, name, - dataSource: this.getName(), - symbol: aSymbol + symbol, + dataSource: this.getName() }; } @@ -60,7 +61,7 @@ export class YahooFinanceService implements DataProviderInterface { try { const historicalResult = await yahooFinance.historical( - this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( + await this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( symbol ), { @@ -112,7 +113,7 @@ export class YahooFinanceService implements DataProviderInterface { try { const historicalResult = await yahooFinance.historical( - this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( + await this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( aSymbol ), { @@ -167,9 +168,17 @@ export class YahooFinanceService implements DataProviderInterface { return response; } - const yahooFinanceSymbols = symbols.map((symbol) => - this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol(symbol) - ); + const yahooFinanceSymbols: string[] = []; + const yahooFinanceSymbolMap: { [yahooFinanceSymbol: string]: string } = {}; + + for (const symbol of symbols) { + const yahooFinanceSymbol = + await this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( + symbol + ); + yahooFinanceSymbolMap[yahooFinanceSymbol] = symbol; + yahooFinanceSymbols.push(yahooFinanceSymbol); + } try { let quotes: Pick< @@ -193,9 +202,10 @@ export class YahooFinanceService implements DataProviderInterface { for (const quote of quotes) { // Convert symbols back const symbol = - this.yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol( - quote.symbol - ); + this.yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol({ + yahooFinanceSymbolMap, + yahooFinanceSymbol: quote.symbol + }); response[symbol] = { currency: quote.currency, @@ -332,9 +342,9 @@ export class YahooFinanceService implements DataProviderInterface { }); const symbol = - this.yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol( - marketDataItem.symbol - ); + this.yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol({ + yahooFinanceSymbol: marketDataItem.symbol + }); const { assetClass, assetSubClass } = this.yahooFinanceDataEnhancerService.parseAssetClass({