Browse Source

Resolve error when fetching dividends for date ranges without events

pull/7612/head
Thomas Kaul 2 weeks ago
parent
commit
8dbab6cfa8
  1. 49
      apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts

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

@ -1,3 +1,4 @@
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { CryptocurrencyService } from '@ghostfolio/api/services/cryptocurrency/cryptocurrency.service';
import { YahooFinanceDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service';
import { AssetProfileDelistedError } from '@ghostfolio/api/services/data-provider/errors/asset-profile-delisted.error';
@ -21,8 +22,8 @@ import {
import { Injectable, Logger } from '@nestjs/common';
import { DataSource, SymbolProfile } from '@prisma/client';
import { addDays, format, isSameDay } from 'date-fns';
import { getReasonPhrase, StatusCodes } from 'http-status-codes';
import { addDays, format, isSameDay, isValid } 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';
@ -45,6 +46,9 @@ 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({
@ -52,6 +56,7 @@ export class YahooFinanceService implements DataProviderInterface {
});
public constructor(
private readonly configurationService: ConfigurationService,
private readonly cryptocurrencyService: CryptocurrencyService,
private readonly yahooFinanceDataEnhancerService: YahooFinanceDataEnhancerService
) {}
@ -78,9 +83,18 @@ export class YahooFinanceService implements DataProviderInterface {
public async getDividends({
from,
granularity = 'day',
requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'),
symbol,
to
}: GetDividendsParams) {
if (!isValid(from) || !isValid(to)) {
this.logger.error(
`Could not get dividends for ${symbol} (${this.getName()}): Invalid date range`
);
return {};
}
try {
const historicalResult = this.convertToDividendResult(
await this.yahooFinance.chart(
@ -95,6 +109,9 @@ export class YahooFinanceService implements DataProviderInterface {
isSameDay(from, to) ? addDays(to, 1) : to,
DATE_FORMAT
)
},
{
fetchOptions: { signal: AbortSignal.timeout(requestTimeout) }
}
)
);
@ -113,16 +130,22 @@ export class YahooFinanceService implements DataProviderInterface {
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?.code === StatusCodes.TOO_MANY_REQUESTS ||
error?.message === YahooFinanceService.DELISTED_ERROR_MESSAGE ||
error?.message?.includes(getReasonPhrase(StatusCodes.TOO_MANY_REQUESTS))
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);
this.logger.warn(
`${message}: ${YahooFinanceService.RATE_LIMIT_ERROR_MESSAGE}`
);
} else {
this.logger.error(message);
this.logger.error(`${message}: [${error?.name}] ${error?.message}`);
}
return {};
@ -131,6 +154,7 @@ export class YahooFinanceService implements DataProviderInterface {
public async getHistorical({
from,
requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'),
symbol,
to
}: GetHistoricalParams): Promise<{
@ -149,6 +173,9 @@ export class YahooFinanceService implements DataProviderInterface {
isSameDay(from, to) ? addDays(to, 1) : to,
DATE_FORMAT
)
},
{
fetchOptions: { signal: AbortSignal.timeout(requestTimeout) }
}
)
);
@ -165,7 +192,7 @@ export class YahooFinanceService implements DataProviderInterface {
return response;
} catch (error) {
if (error.message === YahooFinanceService.DELISTED_ERROR_MESSAGE) {
if (error?.message === YahooFinanceService.DELISTED_ERROR_MESSAGE) {
throw new AssetProfileDelistedError(
`No data found, ${symbol} (${this.getName()}) may be delisted`
);
@ -174,7 +201,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}`
);
}
}

Loading…
Cancel
Save