diff --git a/CHANGELOG.md b/CHANGELOG.md index 695f93110..70a2ab12f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added the historical data and search functionality for the `FINANCIAL_MODELING_PREP` data source type + ### Changed - Improved the local number formatting in the value component diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index d4fe3325b..bcee3c5e7 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -5,11 +5,13 @@ import { IDataProviderHistoricalResponse, IDataProviderResponse } from '@ghostfolio/api/services/interfaces/interfaces'; +import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper'; import { DataProviderInfo } from '@ghostfolio/common/interfaces'; import { Granularity } from '@ghostfolio/common/types'; import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; import bent from 'bent'; +import { format, isAfter, isBefore, isSameDay } from 'date-fns'; @Injectable() export class FinancialModelingPrepService implements DataProviderInterface { @@ -61,9 +63,42 @@ export class FinancialModelingPrepService implements DataProviderInterface { ): Promise<{ [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; }> { - return { - [aSymbol]: {} - }; + try { + const get = bent( + `${this.URL}/historical-price-full/${aSymbol}?apikey=${this.apiKey}`, + 'GET', + 'json', + 200 + ); + const { historical } = await get(); + + const result: { + [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; + } = { + [aSymbol]: {} + }; + + for (const { close, date } of historical) { + if ( + (isSameDay(parseDate(date), from) || + isAfter(parseDate(date), from)) && + isBefore(parseDate(date), to) + ) { + result[aSymbol][date] = { + marketPrice: close + }; + } + } + + return result; + } catch (error) { + throw new Error( + `Could not get historical market data for ${aSymbol} (${this.getName()}) from ${format( + from, + DATE_FORMAT + )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}` + ); + } } public getName(): DataSource { @@ -109,7 +144,32 @@ export class FinancialModelingPrepService implements DataProviderInterface { } public async search(aQuery: string): Promise<{ items: LookupItem[] }> { - return { items: [] }; + let items: LookupItem[] = []; + + try { + const get = bent( + `${this.URL}/search?query=${aQuery}&apikey=${this.apiKey}`, + 'GET', + 'json', + 200 + ); + const result = await get(); + + items = result.map(({ currency, name, symbol }) => { + return { + // TODO: Add assetClass + // TODO: Add assetSubClass + currency, + name, + symbol, + dataSource: this.getName() + }; + }); + } catch (error) { + Logger.error(error, 'FinancialModelingPrepService'); + } + + return { items }; } private getDataProviderInfo(): DataProviderInfo { 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 b0d94baf6..e47713680 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 @@ -138,8 +138,7 @@ export class YahooFinanceService implements DataProviderInterface { marketPrice: this.getConvertedValue({ symbol: aSymbol, value: historicalItem.close - }), - performance: historicalItem.open - historicalItem.close + }) }; } diff --git a/apps/api/src/services/interfaces/interfaces.ts b/apps/api/src/services/interfaces/interfaces.ts index 58f25243c..15505db63 100644 --- a/apps/api/src/services/interfaces/interfaces.ts +++ b/apps/api/src/services/interfaces/interfaces.ts @@ -23,7 +23,6 @@ export interface IOrder { export interface IDataProviderHistoricalResponse { marketPrice: number; - performance?: number; } export interface IDataProviderResponse {