|
|
@ -11,6 +11,7 @@ import { |
|
|
|
IDataProviderHistoricalResponse, |
|
|
|
IDataProviderResponse |
|
|
|
} from '@ghostfolio/api/services/interfaces/interfaces'; |
|
|
|
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; |
|
|
|
import { |
|
|
|
DEFAULT_CURRENCY, |
|
|
|
REPLACE_NAME_PARTS |
|
|
@ -35,7 +36,8 @@ export class EodHistoricalDataService implements DataProviderInterface { |
|
|
|
private readonly URL = 'https://eodhistoricaldata.com/api'; |
|
|
|
|
|
|
|
public constructor( |
|
|
|
private readonly configurationService: ConfigurationService |
|
|
|
private readonly configurationService: ConfigurationService, |
|
|
|
private readonly symbolProfileService: SymbolProfileService |
|
|
|
) { |
|
|
|
this.apiKey = this.configurationService.get('API_KEY_EOD_HISTORICAL_DATA'); |
|
|
|
} |
|
|
@ -230,41 +232,53 @@ export class EodHistoricalDataService implements DataProviderInterface { |
|
|
|
? [realTimeResponse] |
|
|
|
: realTimeResponse; |
|
|
|
|
|
|
|
response = quotes.reduce( |
|
|
|
async ( |
|
|
|
result: { [symbol: string]: IDataProviderResponse }, |
|
|
|
{ close, code, timestamp } |
|
|
|
) => { |
|
|
|
let currency: string; |
|
|
|
const symbolProfiles = await this.symbolProfileService.getSymbolProfiles( |
|
|
|
symbols.map((symbol) => { |
|
|
|
return { |
|
|
|
symbol, |
|
|
|
dataSource: this.getName() |
|
|
|
}; |
|
|
|
}) |
|
|
|
); |
|
|
|
|
|
|
|
if (symbols.length === 1) { |
|
|
|
const { items } = await this.search({ query: symbols[0] }); |
|
|
|
for (const { close, code, timestamp } of quotes) { |
|
|
|
let currency: string; |
|
|
|
|
|
|
|
if (items.length === 1) { |
|
|
|
currency = items[0].currency; |
|
|
|
} |
|
|
|
} |
|
|
|
if (code.endsWith('.FOREX')) { |
|
|
|
currency = this.convertFromEodSymbol(code)?.replace( |
|
|
|
DEFAULT_CURRENCY, |
|
|
|
'' |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
if (isNumber(close)) { |
|
|
|
result[this.convertFromEodSymbol(code)] = { |
|
|
|
currency, |
|
|
|
dataSource: this.getName(), |
|
|
|
marketPrice: close, |
|
|
|
marketState: isToday(new Date(timestamp * 1000)) |
|
|
|
? 'open' |
|
|
|
: 'closed' |
|
|
|
}; |
|
|
|
} else { |
|
|
|
Logger.error( |
|
|
|
`Could not get quote for ${this.convertFromEodSymbol(code)} (${this.getName()})`, |
|
|
|
'EodHistoricalDataService' |
|
|
|
); |
|
|
|
if (!currency) { |
|
|
|
currency = symbolProfiles.find(({ symbol }) => { |
|
|
|
return symbol === code; |
|
|
|
})?.currency; |
|
|
|
} |
|
|
|
|
|
|
|
if (!currency) { |
|
|
|
const { items } = await this.search({ query: code }); |
|
|
|
|
|
|
|
if (items.length === 1) { |
|
|
|
currency = items[0].currency; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
}, |
|
|
|
{} |
|
|
|
); |
|
|
|
if (isNumber(close)) { |
|
|
|
response[this.convertFromEodSymbol(code)] = { |
|
|
|
currency, |
|
|
|
dataSource: this.getName(), |
|
|
|
marketPrice: close, |
|
|
|
marketState: isToday(new Date(timestamp * 1000)) ? 'open' : 'closed' |
|
|
|
}; |
|
|
|
} else { |
|
|
|
Logger.error( |
|
|
|
`Could not get quote for ${this.convertFromEodSymbol(code)} (${this.getName()})`, |
|
|
|
'EodHistoricalDataService' |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return response; |
|
|
|
} catch (error) { |
|
|
|