Browse Source

Bugfix/fix search for cryptocurrencies (#348)

* Fix the search for cryptocurrency symbols

* Update changelog
pull/349/head
Thomas Kaul 3 years ago
committed by GitHub
parent
commit
bf8856ad19
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      CHANGELOG.md
  2. 8
      apps/api/src/services/data-provider/data-provider.service.ts
  3. 109
      apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts

6
CHANGELOG.md

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Fixed
- Fixed the search functionality for cryptocurrency symbols
## 1.46.0 - 05.09.2021 ## 1.46.0 - 05.09.2021
### Added ### Added

8
apps/api/src/services/data-provider/data-provider.service.ts

@ -19,7 +19,10 @@ import { format } from 'date-fns';
import { AlphaVantageService } from './alpha-vantage/alpha-vantage.service'; import { AlphaVantageService } from './alpha-vantage/alpha-vantage.service';
import { GhostfolioScraperApiService } from './ghostfolio-scraper-api/ghostfolio-scraper-api.service'; import { GhostfolioScraperApiService } from './ghostfolio-scraper-api/ghostfolio-scraper-api.service';
import { RakutenRapidApiService } from './rakuten-rapid-api/rakuten-rapid-api.service'; import { RakutenRapidApiService } from './rakuten-rapid-api/rakuten-rapid-api.service';
import { YahooFinanceService } from './yahoo-finance/yahoo-finance.service'; import {
convertToYahooFinanceSymbol,
YahooFinanceService
} from './yahoo-finance/yahoo-finance.service';
@Injectable() @Injectable()
export class DataProviderService { export class DataProviderService {
@ -44,6 +47,9 @@ export class DataProviderService {
return this.ghostfolioScraperApiService.get(aSymbols); return this.ghostfolioScraperApiService.get(aSymbols);
} else if (isRakutenRapidApiSymbol(symbol)) { } else if (isRakutenRapidApiSymbol(symbol)) {
return this.rakutenRapidApiService.get(aSymbols); return this.rakutenRapidApiService.get(aSymbols);
} else {
const yahooFinanceSymbol = convertToYahooFinanceSymbol(symbol);
return this.yahooFinanceService.get([yahooFinanceSymbol]);
} }
} }

109
apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts

@ -43,16 +43,12 @@ export class YahooFinanceService implements DataProviderInterface {
} }
public async get( public async get(
aSymbols: string[] aYahooFinanceSymbols: string[]
): Promise<{ [symbol: string]: IDataProviderResponse }> { ): Promise<{ [symbol: string]: IDataProviderResponse }> {
if (aSymbols.length <= 0) { if (aYahooFinanceSymbols.length <= 0) {
return {}; return {};
} }
const yahooSymbols = aSymbols.map((symbol) => {
return this.convertToYahooSymbol(symbol);
});
try { try {
const response: { [symbol: string]: IDataProviderResponse } = {}; const response: { [symbol: string]: IDataProviderResponse } = {};
@ -60,12 +56,12 @@ export class YahooFinanceService implements DataProviderInterface {
[symbol: string]: IYahooFinanceQuoteResponse; [symbol: string]: IYahooFinanceQuoteResponse;
} = await yahooFinance.quote({ } = await yahooFinance.quote({
modules: ['price', 'summaryProfile'], modules: ['price', 'summaryProfile'],
symbols: yahooSymbols symbols: aYahooFinanceSymbols
}); });
for (const [yahooSymbol, value] of Object.entries(data)) { for (const [yahooFinanceSymbol, value] of Object.entries(data)) {
// Convert symbols back // Convert symbols back
const symbol = convertFromYahooSymbol(yahooSymbol); const symbol = convertFromYahooFinanceSymbol(yahooFinanceSymbol);
const { assetClass, assetSubClass } = this.parseAssetClass(value.price); const { assetClass, assetSubClass } = this.parseAssetClass(value.price);
@ -136,15 +132,15 @@ export class YahooFinanceService implements DataProviderInterface {
return {}; return {};
} }
const yahooSymbols = aSymbols.map((symbol) => { const yahooFinanceSymbols = aSymbols.map((symbol) => {
return this.convertToYahooSymbol(symbol); return convertToYahooFinanceSymbol(symbol);
}); });
try { try {
const historicalData: { const historicalData: {
[symbol: string]: IYahooFinanceHistoricalResponse[]; [symbol: string]: IYahooFinanceHistoricalResponse[];
} = await yahooFinance.historical({ } = await yahooFinance.historical({
symbols: yahooSymbols, symbols: yahooFinanceSymbols,
from: format(from, DATE_FORMAT), from: format(from, DATE_FORMAT),
to: format(to, DATE_FORMAT) to: format(to, DATE_FORMAT)
}); });
@ -153,9 +149,11 @@ export class YahooFinanceService implements DataProviderInterface {
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; [symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
} = {}; } = {};
for (const [yahooSymbol, timeSeries] of Object.entries(historicalData)) { for (const [yahooFinanceSymbol, timeSeries] of Object.entries(
historicalData
)) {
// Convert symbols back // Convert symbols back
const symbol = convertFromYahooSymbol(yahooSymbol); const symbol = convertFromYahooFinanceSymbol(yahooFinanceSymbol);
response[symbol] = {}; response[symbol] = {};
timeSeries.forEach((timeSerie) => { timeSeries.forEach((timeSerie) => {
@ -175,7 +173,7 @@ export class YahooFinanceService implements DataProviderInterface {
} }
public async search(aSymbol: string): Promise<{ items: LookupItem[] }> { public async search(aSymbol: string): Promise<{ items: LookupItem[] }> {
let items: LookupItem[] = []; const items: LookupItem[] = [];
try { try {
const get = bent( const get = bent(
@ -192,19 +190,6 @@ export class YahooFinanceService implements DataProviderInterface {
// filter out undefined symbols // filter out undefined symbols
return quote.symbol; return quote.symbol;
}) })
.filter(({ quoteType }) => {
return quoteType === 'EQUITY' || quoteType === 'ETF';
})
.map(({ symbol }) => {
return symbol;
});
const marketData = await this.get(symbols);
items = searchResult.quotes
.filter((quote) => {
return quote.isYahooFinance;
})
.filter(({ quoteType }) => { .filter(({ quoteType }) => {
return ( return (
quoteType === 'CRYPTOCURRENCY' || quoteType === 'CRYPTOCURRENCY' ||
@ -220,40 +205,23 @@ export class YahooFinanceService implements DataProviderInterface {
return true; return true;
}) })
.map(({ longname, shortname, symbol }) => { .map(({ symbol }) => {
return { return symbol;
currency: marketData[symbol]?.currency,
dataSource: DataSource.YAHOO,
name: longname || shortname,
symbol: convertFromYahooSymbol(symbol)
};
}); });
} catch {}
return { items }; const marketData = await this.get(symbols);
}
/** for (const [symbol, value] of Object.entries(marketData)) {
* Converts a symbol to a Yahoo symbol items.push({
* symbol,
* Currency: USDCHF=X currency: value.currency,
* Cryptocurrency: BTC-USD dataSource: DataSource.YAHOO,
*/ name: value.name
private convertToYahooSymbol(aSymbol: string) { });
if (isCurrency(aSymbol)) {
if (isCrypto(aSymbol)) {
// Add a dash before the last three characters
// BTCUSD -> BTC-USD
// DOGEUSD -> DOGE-USD
return `${aSymbol.substring(0, aSymbol.length - 3)}-${aSymbol.substring(
aSymbol.length - 3
)}`;
} }
} catch {}
return `${aSymbol}=X`; return { items };
}
return aSymbol;
} }
private parseAssetClass(aPrice: IYahooFinancePrice): { private parseAssetClass(aPrice: IYahooFinancePrice): {
@ -290,7 +258,30 @@ export class YahooFinanceService implements DataProviderInterface {
} }
} }
export const convertFromYahooSymbol = (aSymbol: string) => { export const convertFromYahooFinanceSymbol = (aYahooFinanceSymbol: string) => {
const symbol = aSymbol.replace('-', ''); const symbol = aYahooFinanceSymbol.replace('-', '');
return symbol.replace('=X', ''); return symbol.replace('=X', '');
}; };
/**
* Converts a symbol to a Yahoo Finance symbol
*
* Currency: USDCHF=X
* Cryptocurrency: BTC-USD
*/
export const convertToYahooFinanceSymbol = (aSymbol: string) => {
if (isCurrency(aSymbol)) {
if (isCrypto(aSymbol)) {
// Add a dash before the last three characters
// BTCUSD -> BTC-USD
// DOGEUSD -> DOGE-USD
return `${aSymbol.substring(0, aSymbol.length - 3)}-${aSymbol.substring(
aSymbol.length - 3
)}`;
}
return `${aSymbol}=X`;
}
return aSymbol;
};

Loading…
Cancel
Save