Feature/extend financial modeling prep service (#1989)
* Add getHistorical() and search() logic * Update changelog
This commit is contained in:
parent
655a68a847
commit
db29e2b666
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added the historical data and search functionality for the `FINANCIAL_MODELING_PREP` data source type
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Improved the local number formatting in the value component
|
- Improved the local number formatting in the value component
|
||||||
|
@ -5,11 +5,13 @@ import {
|
|||||||
IDataProviderHistoricalResponse,
|
IDataProviderHistoricalResponse,
|
||||||
IDataProviderResponse
|
IDataProviderResponse
|
||||||
} from '@ghostfolio/api/services/interfaces/interfaces';
|
} from '@ghostfolio/api/services/interfaces/interfaces';
|
||||||
|
import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper';
|
||||||
import { DataProviderInfo } from '@ghostfolio/common/interfaces';
|
import { DataProviderInfo } from '@ghostfolio/common/interfaces';
|
||||||
import { Granularity } from '@ghostfolio/common/types';
|
import { Granularity } from '@ghostfolio/common/types';
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { DataSource, SymbolProfile } from '@prisma/client';
|
import { DataSource, SymbolProfile } from '@prisma/client';
|
||||||
import bent from 'bent';
|
import bent from 'bent';
|
||||||
|
import { format, isAfter, isBefore, isSameDay } from 'date-fns';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FinancialModelingPrepService implements DataProviderInterface {
|
export class FinancialModelingPrepService implements DataProviderInterface {
|
||||||
@ -61,9 +63,42 @@ export class FinancialModelingPrepService implements DataProviderInterface {
|
|||||||
): Promise<{
|
): Promise<{
|
||||||
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
|
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
|
||||||
}> {
|
}> {
|
||||||
return {
|
try {
|
||||||
[aSymbol]: {}
|
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 {
|
public getName(): DataSource {
|
||||||
@ -109,7 +144,32 @@ export class FinancialModelingPrepService implements DataProviderInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async search(aQuery: string): Promise<{ items: LookupItem[] }> {
|
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 {
|
private getDataProviderInfo(): DataProviderInfo {
|
||||||
|
@ -138,8 +138,7 @@ export class YahooFinanceService implements DataProviderInterface {
|
|||||||
marketPrice: this.getConvertedValue({
|
marketPrice: this.getConvertedValue({
|
||||||
symbol: aSymbol,
|
symbol: aSymbol,
|
||||||
value: historicalItem.close
|
value: historicalItem.close
|
||||||
}),
|
})
|
||||||
performance: historicalItem.open - historicalItem.close
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ export interface IOrder {
|
|||||||
|
|
||||||
export interface IDataProviderHistoricalResponse {
|
export interface IDataProviderHistoricalResponse {
|
||||||
marketPrice: number;
|
marketPrice: number;
|
||||||
performance?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDataProviderResponse {
|
export interface IDataProviderResponse {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user