Browse Source

Bugfix/missing close price in historical market data (#7694)

* Fix missing close price in historical market data of Yahoo Finance service

* Discard market prices carried forward beyond the data of the data provider

* Update changelog
pull/7697/head
Thomas Kaul 6 days ago
committed by GitHub
parent
commit
a55b9f212b
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      CHANGELOG.md
  2. 45
      apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts
  3. 23
      apps/api/src/services/queues/data-gathering/data-gathering.processor.ts
  4. 4
      apps/api/src/services/queues/data-gathering/data-gathering.service.ts

2
CHANGELOG.md

@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed the benchmark label in the tooltip of the benchmark comparator on the analysis page
- Fixed the _Storybook_ setup by loading the `@angular/localize` polyfill centrally
- Fixed an issue in the activities import where an unused custom asset profile was created if the related activities were not imported
- Fixed the missing close price in the historical market data of the _Yahoo Finance_ service by falling back to the market price of the quote
- Fixed the historical market data gathering by no longer storing the last known market price for the most recent dates without data from the data provider
## 3.57.0 - 2026-08-21

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

@ -143,30 +143,39 @@ export class YahooFinanceService implements DataProviderInterface {
[date: string]: DataProviderHistoricalResponse;
}> {
try {
const historicalResult = this.convertToHistoricalResult(
await this.yahooFinance.chart(
this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol(
symbol
),
{
interval: '1d',
period1: format(from, DATE_FORMAT),
period2: format(
isSameDay(from, to) ? addDays(to, 1) : to,
DATE_FORMAT
)
}
)
const chartResult = await this.yahooFinance.chart(
this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol(
symbol
),
{
interval: '1d',
period1: format(from, DATE_FORMAT),
period2: format(
isSameDay(from, to) ? addDays(to, 1) : to,
DATE_FORMAT
)
}
);
const historicalResult = this.convertToHistoricalResult(chartResult);
const response: {
[date: string]: DataProviderHistoricalResponse;
} = {};
for (const historicalItem of historicalResult) {
response[format(historicalItem.date, DATE_FORMAT)] = {
marketPrice: historicalItem.close
};
for (const { close, date } of historicalResult) {
// The chart endpoint can omit the close price of a historical item, for
// example if the daily data of an exchange has not been consolidated yet.
// In this case, the market price of the corresponding quote is taken.
const marketPrice =
close ??
(isSameDay(date, chartResult.meta.regularMarketTime)
? chartResult.meta.regularMarketPrice
: undefined);
if (marketPrice) {
response[format(date, DATE_FORMAT)] = { marketPrice };
}
}
return response;

23
apps/api/src/services/queues/data-gathering/data-gathering.processor.ts

@ -125,6 +125,7 @@ export class DataGatheringProcessor {
const data: Prisma.MarketDataUpdateInput[] = [];
let lastMarketPrice: number;
let numberOfMarketDataItemsToKeep = 0;
while (
isBefore(
@ -139,15 +140,13 @@ export class DataGatheringProcessor {
)
)
) {
if (
const marketPriceOfDataProvider =
historicalData[assetProfileIdentifier]?.[
format(currentDate, DATE_FORMAT)
]?.marketPrice
) {
lastMarketPrice =
historicalData[assetProfileIdentifier]?.[
format(currentDate, DATE_FORMAT)
]?.marketPrice;
]?.marketPrice;
if (marketPriceOfDataProvider) {
lastMarketPrice = marketPriceOfDataProvider;
}
if (lastMarketPrice) {
@ -158,11 +157,21 @@ export class DataGatheringProcessor {
marketPrice: lastMarketPrice,
state: 'CLOSE'
});
if (marketPriceOfDataProvider) {
numberOfMarketDataItemsToKeep = data.length;
}
}
currentDate = addDays(currentDate, 1);
}
// A gap at the end means that the market data is not available yet, in
// contrast to a gap in between, which means that the market was closed.
// Therefore, the market prices which are carried forward after the last
// market price of the data provider are discarded.
data.splice(numberOfMarketDataItemsToKeep);
if (force) {
await this.marketDataService.replaceForSymbol({
data,

4
apps/api/src/services/queues/data-gathering/data-gathering.service.ts

@ -310,9 +310,9 @@ export class DataGatheringService {
});
const marketPrice =
historicalData[getAssetProfileIdentifier({ dataSource, symbol })][
historicalData[getAssetProfileIdentifier({ dataSource, symbol })]?.[
format(date, DATE_FORMAT)
].marketPrice;
]?.marketPrice;
if (marketPrice) {
return await this.prismaService.marketData.upsert({

Loading…
Cancel
Save