Browse Source

Bugfix/resolve error when fetching dividends from Yahoo Finance for date ranges without events (#7612)

* Resolve error when fetching dividends for date ranges without events

* Update changelog
pull/7610/head
Thomas Kaul 5 days ago
committed by GitHub
parent
commit
f474f319bf
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      CHANGELOG.md
  2. 8
      apps/api/src/services/data-provider/data-provider.service.ts
  3. 55
      apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts

4
CHANGELOG.md

@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Refreshed the cryptocurrencies list
### Fixed
- Resolved an error when fetching dividends from _Yahoo Finance_ for date ranges without events
## 3.49.0 - 2026-08-12
### Changed

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

@ -340,7 +340,13 @@ export class DataProviderService implements OnModuleInit {
from: Date;
granularity: Granularity;
to: Date;
} & AssetProfileIdentifier) {
} & AssetProfileIdentifier): Promise<{
[date: string]: DataProviderHistoricalResponse;
}> {
if (!isValid(from) || !isValid(to)) {
return {};
}
return this.getDataProvider(DataSource[dataSource]).getDividends({
from,
granularity,

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

@ -22,6 +22,7 @@ import {
import { Injectable, Logger } from '@nestjs/common';
import { DataSource, SymbolProfile } from '@prisma/client';
import { addDays, format, isSameDay } from 'date-fns';
import { ReasonPhrases, StatusCodes } from 'http-status-codes';
import { uniqBy } from 'lodash';
import YahooFinance from 'yahoo-finance2';
import { ChartResultArray } from 'yahoo-finance2/esm/src/modules/chart';
@ -41,6 +42,12 @@ import { SearchQuoteNonYahoo } from 'yahoo-finance2/esm/src/modules/search';
@Injectable()
export class YahooFinanceService implements DataProviderInterface {
private static readonly DELISTED_ERROR_MESSAGE =
'No data found, symbol may be delisted';
private static readonly RATE_LIMIT_ERROR_MESSAGE =
ReasonPhrases.TOO_MANY_REQUESTS;
private readonly logger = new Logger(YahooFinanceService.name);
private readonly yahooFinance = new YahooFinance({
@ -77,10 +84,6 @@ export class YahooFinanceService implements DataProviderInterface {
symbol,
to
}: GetDividendsParams) {
if (isSameDay(from, to)) {
to = addDays(to, 1);
}
try {
const historicalResult = this.convertToDividendResult(
await this.yahooFinance.chart(
@ -91,7 +94,10 @@ export class YahooFinanceService implements DataProviderInterface {
events: 'dividends',
interval: granularity === 'month' ? '1mo' : '1d',
period1: format(from, DATE_FORMAT),
period2: format(to, DATE_FORMAT)
period2: format(
isSameDay(from, to) ? addDays(to, 1) : to,
DATE_FORMAT
)
}
)
);
@ -107,12 +113,26 @@ export class YahooFinanceService implements DataProviderInterface {
return response;
} catch (error) {
this.logger.error(
`Could not get dividends for ${symbol} (${this.getName()}) from ${format(
const message = `Could not get dividends for ${symbol} (${this.getName()}) from ${format(
from,
DATE_FORMAT
)} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}`
)} to ${format(to, DATE_FORMAT)}`;
if (error?.message === YahooFinanceService.DELISTED_ERROR_MESSAGE) {
this.logger.warn(
`${message}: ${YahooFinanceService.DELISTED_ERROR_MESSAGE}`
);
} else if (
(error?.name === 'HTTPError' &&
error?.code === StatusCodes.TOO_MANY_REQUESTS) ||
error?.message?.startsWith(YahooFinanceService.RATE_LIMIT_ERROR_MESSAGE)
) {
this.logger.warn(
`${message}: ${YahooFinanceService.RATE_LIMIT_ERROR_MESSAGE}`
);
} else {
this.logger.error(`${message}: [${error?.name}] ${error?.message}`);
}
return {};
}
@ -125,10 +145,6 @@ export class YahooFinanceService implements DataProviderInterface {
}: GetHistoricalParams): Promise<{
[date: string]: DataProviderHistoricalResponse;
}> {
if (isSameDay(from, to)) {
to = addDays(to, 1);
}
try {
const historicalResult = this.convertToHistoricalResult(
await this.yahooFinance.chart(
@ -138,7 +154,10 @@ export class YahooFinanceService implements DataProviderInterface {
{
interval: '1d',
period1: format(from, DATE_FORMAT),
period2: format(to, DATE_FORMAT)
period2: format(
isSameDay(from, to) ? addDays(to, 1) : to,
DATE_FORMAT
)
}
)
);
@ -155,7 +174,7 @@ export class YahooFinanceService implements DataProviderInterface {
return response;
} catch (error) {
if (error.message === 'No data found, symbol may be delisted') {
if (error?.message === YahooFinanceService.DELISTED_ERROR_MESSAGE) {
throw new AssetProfileDelistedError(
`No data found, ${symbol} (${this.getName()}) may be delisted`
);
@ -164,7 +183,7 @@ export class YahooFinanceService implements DataProviderInterface {
`Could not get historical market data for ${symbol} (${this.getName()}) from ${format(
from,
DATE_FORMAT
)} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}`
)} to ${format(to, DATE_FORMAT)}: [${error?.name}] ${error?.message}`
);
}
}
@ -343,9 +362,11 @@ export class YahooFinanceService implements DataProviderInterface {
private convertToDividendResult(
result: ChartResultArray
): HistoricalDividendsResult {
return result.events.dividends.map(({ amount: dividends, date }) => {
return (result.events?.dividends ?? []).map(
({ amount: dividends, date }) => {
return { date, dividends };
});
}
);
}
private convertToHistoricalResult(

Loading…
Cancel
Save