From 40b628e0e78136b67a98549b010c6a335441ded9 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 18 Jan 2025 10:50:52 +0100 Subject: [PATCH] Feature/extend search by isin in financial modeling prep service (#4204) * Extend search by ISIN * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/symbol/symbol.controller.ts | 2 +- .../financial-modeling-prep.service.ts | 69 +++++++++++++------ 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3598581f..07b37e80b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Extended the search by `isin` in the _Financial Modeling Prep_ service - Switched to _ESLint_’s flat config format - Upgraded `eslint` dependencies diff --git a/apps/api/src/app/symbol/symbol.controller.ts b/apps/api/src/app/symbol/symbol.controller.ts index 89cdd416c..5d9a49a29 100644 --- a/apps/api/src/app/symbol/symbol.controller.ts +++ b/apps/api/src/app/symbol/symbol.controller.ts @@ -47,7 +47,7 @@ export class SymbolController { try { return this.symbolService.lookup({ includeIndices, - query: query.toLowerCase(), + query, user: this.request.user }); } catch { 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 ed55b3c2f..edde92cbb 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 @@ -20,12 +20,13 @@ import { import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; +import { isISIN } from 'class-validator'; import { format, isAfter, isBefore, isSameDay } from 'date-fns'; @Injectable() export class FinancialModelingPrepService implements DataProviderInterface { private apiKey: string; - private readonly URL = 'https://financialmodelingprep.com/api/v3'; + private readonly URL = this.getUrl({ version: 3 }); public constructor( private readonly configurationService: ConfigurationService @@ -161,25 +162,49 @@ export class FinancialModelingPrepService implements DataProviderInterface { let items: LookupItem[] = []; try { - const result = await fetch( - `${this.URL}/search?query=${query}&apikey=${this.apiKey}`, - { - signal: AbortSignal.timeout( - this.configurationService.get('REQUEST_TIMEOUT') - ) - } - ).then((res) => res.json()); - - items = result.map(({ currency, name, symbol }) => { - return { - // TODO: Add assetClass - // TODO: Add assetSubClass - currency, - name, - symbol, - dataSource: this.getName() - }; - }); + if (isISIN(query)) { + const result = await fetch( + `${this.getUrl({ version: 4 })}/search/isin?isin=${query}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout( + this.configurationService.get('REQUEST_TIMEOUT') + ) + } + ).then((res) => res.json()); + + items = result.map(({ companyName, currency, symbol }) => { + return { + currency, + symbol, + assetClass: undefined, // TODO + assetSubClass: undefined, // TODO + dataProviderInfo: this.getDataProviderInfo(), + dataSource: this.getName(), + name: companyName + }; + }); + } else { + const result = await fetch( + `${this.URL}/search?query=${query}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout( + this.configurationService.get('REQUEST_TIMEOUT') + ) + } + ).then((res) => res.json()); + + items = result.map(({ currency, name, symbol }) => { + return { + currency, + name, + symbol, + assetClass: undefined, // TODO + assetSubClass: undefined, // TODO + dataProviderInfo: this.getDataProviderInfo(), + dataSource: this.getName() + }; + }); + } } catch (error) { let message = error; @@ -194,4 +219,8 @@ export class FinancialModelingPrepService implements DataProviderInterface { return { items }; } + + private getUrl({ version }: { version: number }) { + return `https://financialmodelingprep.com/api/v${version}`; + } }