Add retry with exponential backoff for yfinance rate limits
When yfinance hits Yahoo Finance rate limits (429 Too Many Requests), the data fetch fails immediately and the Market Analyst agent loops endlessly. This adds a simple retry wrapper with exponential backoff (2s, 4s, 8s) that catches rate limit errors and waits before retrying. Addresses #415
This commit is contained in:
parent
f362a160c3
commit
781dd971ba
|
|
@ -1,10 +1,37 @@
|
|||
from typing import Annotated
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import time
|
||||
import logging
|
||||
import yfinance as yf
|
||||
import os
|
||||
from .stockstats_utils import StockstatsUtils, _clean_dataframe
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _yf_retry(func, max_retries=3, initial_delay=2.0):
|
||||
"""Retry a yfinance call with exponential backoff on rate limit errors."""
|
||||
delay = initial_delay
|
||||
last_error = None
|
||||
for attempt in range(max_retries + 1):
|
||||
try:
|
||||
return func()
|
||||
except Exception as e:
|
||||
last_error = e
|
||||
error_str = str(e).lower()
|
||||
if "rate" in error_str or "too many" in error_str or "429" in error_str:
|
||||
if attempt < max_retries:
|
||||
logger.warning(
|
||||
f"yfinance rate limited, retrying in {delay:.0f}s "
|
||||
f"(attempt {attempt + 1}/{max_retries})"
|
||||
)
|
||||
time.sleep(delay)
|
||||
delay *= 2
|
||||
continue
|
||||
raise
|
||||
raise last_error
|
||||
|
||||
def get_YFin_data_online(
|
||||
symbol: Annotated[str, "ticker symbol of the company"],
|
||||
start_date: Annotated[str, "Start date in yyyy-mm-dd format"],
|
||||
|
|
@ -17,8 +44,8 @@ def get_YFin_data_online(
|
|||
# Create ticker object
|
||||
ticker = yf.Ticker(symbol.upper())
|
||||
|
||||
# Fetch historical data for the specified date range
|
||||
data = ticker.history(start=start_date, end=end_date)
|
||||
# Fetch historical data with retry on rate limiting
|
||||
data = _yf_retry(lambda: ticker.history(start=start_date, end=end_date))
|
||||
|
||||
# Check if data is empty
|
||||
if data.empty:
|
||||
|
|
|
|||
Loading…
Reference in New Issue