Browse Source

Setup OpenFIGI

pull/2526/head
Thomas 2 years ago
parent
commit
c30201b1a9
  1. 9
      apps/api/src/app/import/import.service.ts
  2. 9
      apps/api/src/services/data-gathering/data-gathering.service.ts
  3. 10
      apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts
  4. 73
      apps/api/src/services/data-provider/data-enhancer/openfigi/openfigi.service.ts
  5. 9
      libs/common/src/lib/helper.ts
  6. 5
      prisma/migrations/20231021094346_added_figi_figi_composite_and_figi_share_class_to_symbol_profile/migration.sql
  7. 3
      prisma/schema.prisma

9
apps/api/src/app/import/import.service.ts

@ -280,6 +280,9 @@ export class ImportService {
createdAt, createdAt,
currency, currency,
dataSource, dataSource,
figi,
figiComposite,
figiShareClass,
id, id,
isin, isin,
name, name,
@ -350,6 +353,9 @@ export class ImportService {
createdAt, createdAt,
currency, currency,
dataSource, dataSource,
figi,
figiComposite,
figiShareClass,
id, id,
isin, isin,
name, name,
@ -509,6 +515,9 @@ export class ImportService {
comment: null, comment: null,
countries: null, countries: null,
createdAt: undefined, createdAt: undefined,
figi: null,
figiComposite: null,
figiShareClass: null,
id: undefined, id: undefined,
isin: null, isin: null,
name: null, name: null,

9
apps/api/src/services/data-gathering/data-gathering.service.ts

@ -164,6 +164,9 @@ export class DataGatheringService {
countries, countries,
currency, currency,
dataSource, dataSource,
figi,
figiComposite,
figiShareClass,
isin, isin,
name, name,
sectors, sectors,
@ -178,6 +181,9 @@ export class DataGatheringService {
countries, countries,
currency, currency,
dataSource, dataSource,
figi,
figiComposite,
figiShareClass,
isin, isin,
name, name,
sectors, sectors,
@ -189,6 +195,9 @@ export class DataGatheringService {
assetSubClass, assetSubClass,
countries, countries,
currency, currency,
figi,
figiComposite,
figiShareClass,
isin, isin,
name, name,
sectors, sectors,

10
apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts

@ -1,5 +1,6 @@
import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module';
import { CryptocurrencyModule } from '@ghostfolio/api/services/cryptocurrency/cryptocurrency.module'; import { CryptocurrencyModule } from '@ghostfolio/api/services/cryptocurrency/cryptocurrency.module';
import { OpenFigiDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/openfigi/openfigi.service';
import { TrackinsightDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/trackinsight/trackinsight.service'; import { TrackinsightDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/trackinsight/trackinsight.service';
import { YahooFinanceDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service'; import { YahooFinanceDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
@ -9,6 +10,7 @@ import { DataEnhancerService } from './data-enhancer.service';
@Module({ @Module({
exports: [ exports: [
DataEnhancerService, DataEnhancerService,
OpenFigiDataEnhancerService,
TrackinsightDataEnhancerService, TrackinsightDataEnhancerService,
YahooFinanceDataEnhancerService, YahooFinanceDataEnhancerService,
'DataEnhancers' 'DataEnhancers'
@ -16,15 +18,21 @@ import { DataEnhancerService } from './data-enhancer.service';
imports: [ConfigurationModule, CryptocurrencyModule], imports: [ConfigurationModule, CryptocurrencyModule],
providers: [ providers: [
DataEnhancerService, DataEnhancerService,
OpenFigiDataEnhancerService,
TrackinsightDataEnhancerService, TrackinsightDataEnhancerService,
YahooFinanceDataEnhancerService, YahooFinanceDataEnhancerService,
{ {
inject: [ inject: [
OpenFigiDataEnhancerService,
TrackinsightDataEnhancerService, TrackinsightDataEnhancerService,
YahooFinanceDataEnhancerService YahooFinanceDataEnhancerService
], ],
provide: 'DataEnhancers', provide: 'DataEnhancers',
useFactory: (trackinsight, yahooFinance) => [trackinsight, yahooFinance] useFactory: (openfigi, trackinsight, yahooFinance) => [
openfigi,
trackinsight,
yahooFinance
]
} }
] ]
}) })

73
apps/api/src/services/data-provider/data-enhancer/openfigi/openfigi.service.ts

@ -0,0 +1,73 @@
import { DataEnhancerInterface } from '@ghostfolio/api/services/data-provider/interfaces/data-enhancer.interface';
import { DEFAULT_REQUEST_TIMEOUT } from '@ghostfolio/common/config';
import { parseSymbol } from '@ghostfolio/common/helper';
import { Injectable } from '@nestjs/common';
import { SymbolProfile } from '@prisma/client';
import got from 'got';
@Injectable()
export class OpenFigiDataEnhancerService implements DataEnhancerInterface {
private static baseUrl = 'https://api.openfigi.com';
public async enhance({
response,
symbol
}: {
response: Partial<SymbolProfile>;
symbol: string;
}): Promise<Partial<SymbolProfile>> {
if (
!(
response.assetClass === 'EQUITY' &&
(response.assetSubClass === 'ETF' || response.assetSubClass === 'STOCK')
)
) {
return response;
}
const { exchange, ticker } = parseSymbol({
symbol,
dataSource: response.dataSource
});
let abortController = new AbortController();
setTimeout(() => {
abortController.abort();
}, DEFAULT_REQUEST_TIMEOUT);
const mappings = await got
.post(`${OpenFigiDataEnhancerService.baseUrl}/v3/mapping`, {
json: [{ exchCode: exchange, idType: 'TICKER', idValue: ticker }],
// @ts-ignore
signal: abortController.signal
})
.json<any[]>();
if (mappings?.length === 1 && mappings[0].data?.length === 1) {
const { compositeFIGI, figi, shareClassFIGI } = mappings[0].data[0];
if (figi) {
response.figi = figi;
}
if (compositeFIGI) {
response.figiComposite = compositeFIGI;
}
if (shareClassFIGI) {
response.figiShareClass = shareClassFIGI;
}
}
return response;
}
public getName() {
return 'OPENFIGI';
}
public getTestSymbol() {
return undefined;
}
}

9
libs/common/src/lib/helper.ts

@ -322,6 +322,15 @@ export function parseDate(date: string): Date | null {
return parseISO(date); return parseISO(date);
} }
export function parseSymbol({ dataSource, symbol }: UniqueAsset) {
const [ticker, exchange] = symbol.split('.');
return {
exchange: exchange ?? (dataSource === 'YAHOO' ? 'US' : undefined),
ticker
};
}
export function prettifySymbol(aSymbol: string): string { export function prettifySymbol(aSymbol: string): string {
return aSymbol?.replace(ghostfolioScraperApiSymbolPrefix, ''); return aSymbol?.replace(ghostfolioScraperApiSymbolPrefix, '');
} }

5
prisma/migrations/20231021094346_added_figi_figi_composite_and_figi_share_class_to_symbol_profile/migration.sql

@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE "SymbolProfile"
ADD COLUMN "figi" TEXT,
ADD COLUMN "figiComposite" TEXT,
ADD COLUMN "figiShareClass" TEXT;

3
prisma/schema.prisma

@ -132,6 +132,9 @@ model SymbolProfile {
createdAt DateTime @default(now()) createdAt DateTime @default(now())
currency String currency String
dataSource DataSource dataSource DataSource
figi String?
figiComposite String?
figiShareClass String?
id String @id @default(uuid()) id String @id @default(uuid())
isin String? isin String?
name String? name String?

Loading…
Cancel
Save