Browse Source

Task/simplify getHistorical() function response in data provider interface (#7369)

* Simplify getHistorical() function response

* Update changelog
pull/7371/head^2
Thomas Kaul 24 hours ago
committed by GitHub
parent
commit
37bd17d3c1
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      CHANGELOG.md
  2. 4
      apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts
  3. 8
      apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts
  4. 10
      apps/api/src/services/data-provider/coingecko/coingecko.service.ts
  5. 2
      apps/api/src/services/data-provider/data-provider.service.ts
  6. 29
      apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts
  7. 10
      apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts
  8. 6
      apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts
  9. 6
      apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts
  10. 4
      apps/api/src/services/data-provider/interfaces/data-provider.interface.ts
  11. 17
      apps/api/src/services/data-provider/manual/manual.service.ts
  12. 8
      apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts
  13. 8
      apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts

6
CHANGELOG.md

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Changed
- Simplified the `getHistorical()` function response in the data provider interface
## 3.29.0 - 2026-07-18 ## 3.29.0 - 2026-07-18
### Added ### Added

4
apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts

@ -171,7 +171,7 @@ export class GhostfolioService {
try { try {
const promises: Promise<{ const promises: Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}>[] = []; }>[] = [];
for (const dataProviderService of this.getDataProviderServices()) { for (const dataProviderService of this.getDataProviderServices()) {
@ -185,7 +185,7 @@ export class GhostfolioService {
to to
}) })
.then((historicalData) => { .then((historicalData) => {
result.historicalData = historicalData[symbol]; result.historicalData = historicalData;
return historicalData; return historicalData;
}) })

8
apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts

@ -70,7 +70,7 @@ export class AlphaVantageService
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}> { }> {
try { try {
const historicalData: { const historicalData: {
@ -83,11 +83,9 @@ export class AlphaVantageService
); );
const response: { const response: {
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
} = {}; } = {};
response[symbol] = {};
for (const [key, timeSeries] of Object.entries( for (const [key, timeSeries] of Object.entries(
historicalData['Time Series (Digital Currency Daily)'] historicalData['Time Series (Digital Currency Daily)']
).sort()) { ).sort()) {
@ -95,7 +93,7 @@ export class AlphaVantageService
isAfter(from, parse(key, DATE_FORMAT, new Date())) && isAfter(from, parse(key, DATE_FORMAT, new Date())) &&
isBefore(to, parse(key, DATE_FORMAT, new Date())) isBefore(to, parse(key, DATE_FORMAT, new Date()))
) { ) {
response[symbol][key] = { response[key] = {
marketPrice: parseFloat(timeSeries['4a. close (USD)']) marketPrice: parseFloat(timeSeries['4a. close (USD)'])
}; };
} }

10
apps/api/src/services/data-provider/coingecko/coingecko.service.ts

@ -115,7 +115,7 @@ export class CoinGeckoService implements DataProviderInterface, OnModuleInit {
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}> { }> {
try { try {
const queryParams = new URLSearchParams({ const queryParams = new URLSearchParams({
@ -143,13 +143,11 @@ export class CoinGeckoService implements DataProviderInterface, OnModuleInit {
} }
const result: { const result: {
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
} = { } = {};
[symbol]: {}
};
for (const [timestamp, marketPrice] of prices) { for (const [timestamp, marketPrice] of prices) {
result[symbol][format(fromUnixTime(timestamp / 1000), DATE_FORMAT)] = { result[format(fromUnixTime(timestamp / 1000), DATE_FORMAT)] = {
marketPrice marketPrice
}; };
} }

2
apps/api/src/services/data-provider/data-provider.service.ts

@ -508,7 +508,7 @@ export class DataProviderService implements OnModuleInit {
requestTimeout: ms('30 seconds') requestTimeout: ms('30 seconds')
}) })
.then((data) => { .then((data) => {
return { dataSource, symbol, data: data?.[symbol] }; return { data, dataSource, symbol };
}) })
); );
} }

29
apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts

@ -147,7 +147,7 @@ export class EodHistoricalDataService
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}> { }> {
symbol = this.convertToEodSymbol(symbol); symbol = this.convertToEodSymbol(symbol);
@ -166,22 +166,19 @@ export class EodHistoricalDataService
}) })
.then((res) => res.json()); .then((res) => res.json());
return response.reduce( return response.reduce((result, { adjusted_close, date }) => {
(result, { adjusted_close, date }) => { if (isNumber(adjusted_close)) {
if (isNumber(adjusted_close)) { result[date] = {
result[this.convertFromEodSymbol(symbol)][date] = { marketPrice: adjusted_close
marketPrice: adjusted_close };
}; } else {
} else { this.logger.error(
this.logger.error( `Could not get historical market data for ${symbol} (${this.getName()}) at ${date}`
`Could not get historical market data for ${symbol} (${this.getName()}) at ${date}` );
); }
}
return result; return result;
}, }, {});
{ [this.convertFromEodSymbol(symbol)]: {} }
);
} catch (error) { } catch (error) {
throw new Error( throw new Error(
`Could not get historical market data for ${symbol} (${this.getName()}) from ${format( `Could not get historical market data for ${symbol} (${this.getName()}) from ${format(

10
apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts

@ -336,14 +336,12 @@ export class FinancialModelingPrepService
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}> { }> {
const MAX_YEARS_PER_REQUEST = 5; const MAX_YEARS_PER_REQUEST = 5;
const result: { const result: {
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
} = { } = {};
[symbol]: {}
};
let currentFrom = from; let currentFrom = from;
@ -378,7 +376,7 @@ export class FinancialModelingPrepService
isAfter(parseDate(date), currentFrom)) && isAfter(parseDate(date), currentFrom)) &&
isBefore(parseDate(date), currentTo) isBefore(parseDate(date), currentTo)
) { ) {
result[symbol][date] = { result[date] = {
marketPrice: close marketPrice: close
}; };
} }

6
apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts

@ -172,7 +172,7 @@ export class GhostfolioService implements DataProviderInterface {
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}> { }> {
try { try {
const queryParams = new URLSearchParams({ const queryParams = new URLSearchParams({
@ -198,9 +198,7 @@ export class GhostfolioService implements DataProviderInterface {
const { historicalData } = (await response.json()) as HistoricalResponse; const { historicalData } = (await response.json()) as HistoricalResponse;
return { return historicalData;
[symbol]: historicalData
};
} catch (error) { } catch (error) {
if (error?.status === StatusCodes.TOO_MANY_REQUESTS) { if (error?.status === StatusCodes.TOO_MANY_REQUESTS) {
error.name = 'RequestError'; error.name = 'RequestError';

6
apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts

@ -60,7 +60,7 @@ export class GoogleSheetsService implements DataProviderInterface {
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}> { }> {
try { try {
const sheet = await this.getSheet({ const sheet = await this.getSheet({
@ -85,9 +85,7 @@ export class GoogleSheetsService implements DataProviderInterface {
historicalData[format(date, DATE_FORMAT)] = { marketPrice: close }; historicalData[format(date, DATE_FORMAT)] = { marketPrice: close };
}); });
return { return historicalData;
[symbol]: historicalData
};
} catch (error) { } catch (error) {
throw new Error( throw new Error(
`Could not get historical market data for ${symbol} (${this.getName()}) from ${format( `Could not get historical market data for ${symbol} (${this.getName()}) from ${format(

4
apps/api/src/services/data-provider/interfaces/data-provider.interface.ts

@ -35,8 +35,8 @@ export interface DataProviderInterface {
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}>; // TODO: Return only one symbol }>;
getMarketDataOfMarkets?({ getMarketDataOfMarkets?({
includeHistoricalData, includeHistoricalData,

17
apps/api/src/services/data-provider/manual/manual.service.ts

@ -79,7 +79,7 @@ export class ManualService implements DataProviderInterface {
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}> { }> {
try { try {
const [symbolProfile] = await this.symbolProfileService.getSymbolProfiles( const [symbolProfile] = await this.symbolProfileService.getSymbolProfiles(
@ -90,14 +90,13 @@ export class ManualService implements DataProviderInterface {
if (defaultMarketPrice) { if (defaultMarketPrice) {
const historical: { const historical: {
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
} = { } = {};
[symbol]: {}
};
let date = from; let date = from;
while (isBefore(date, to)) { while (isBefore(date, to)) {
historical[symbol][format(date, DATE_FORMAT)] = { historical[format(date, DATE_FORMAT)] = {
marketPrice: defaultMarketPrice marketPrice: defaultMarketPrice
}; };
@ -115,10 +114,8 @@ export class ManualService implements DataProviderInterface {
}); });
return { return {
[symbol]: { [format(getYesterday(), DATE_FORMAT)]: {
[format(getYesterday(), DATE_FORMAT)]: { marketPrice: value
marketPrice: value
}
} }
}; };
} catch (error) { } catch (error) {

8
apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts

@ -58,7 +58,7 @@ export class RapidApiService implements DataProviderInterface {
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}> { }> {
try { try {
if (symbol === ghostfolioFearAndGreedIndexSymbolStocks) { if (symbol === ghostfolioFearAndGreedIndexSymbolStocks) {
@ -66,10 +66,8 @@ export class RapidApiService implements DataProviderInterface {
if (fgi) { if (fgi) {
return { return {
[symbol]: { [format(getYesterday(), DATE_FORMAT)]: {
[format(getYesterday(), DATE_FORMAT)]: { marketPrice: fgi.previousClose.value
marketPrice: fgi.previousClose.value
}
} }
}; };
} }

8
apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts

@ -123,7 +123,7 @@ export class YahooFinanceService implements DataProviderInterface {
symbol, symbol,
to to
}: GetHistoricalParams): Promise<{ }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
}> { }> {
if (isSameDay(from, to)) { if (isSameDay(from, to)) {
to = addDays(to, 1); to = addDays(to, 1);
@ -144,13 +144,11 @@ export class YahooFinanceService implements DataProviderInterface {
); );
const response: { const response: {
[symbol: string]: { [date: string]: DataProviderHistoricalResponse }; [date: string]: DataProviderHistoricalResponse;
} = {}; } = {};
response[symbol] = {};
for (const historicalItem of historicalResult) { for (const historicalItem of historicalResult) {
response[symbol][format(historicalItem.date, DATE_FORMAT)] = { response[format(historicalItem.date, DATE_FORMAT)] = {
marketPrice: historicalItem.close marketPrice: historicalItem.close
}; };
} }

Loading…
Cancel
Save