ZhuLinsen/daily_stock_analysis · warning · DataFetchError
[AlphaVantage] Rate limited: {data['Note']}
Error message
[AlphaVantage] Rate limited: {data['Note']} What it means
A DataFetchError raised by AlphaVantageFetcher._fetch_raw_data when the successful JSON response contains a top-level 'Note' key. AlphaVantage signals rate limiting this way — HTTP 200 with an explanatory Note instead of time-series data — so the fetcher converts it into an explicit 'Rate limited' error carrying the API's own message.
Source
Thrown at data_provider/alphavantage_fetcher.py:64
symbol = stock_code.strip().upper()
params = {
'function': 'TIME_SERIES_DAILY',
'symbol': symbol,
'outputsize': 'compact',
'apikey': self._api_key,
}
try:
self.random_sleep(0.5, 1.5)
resp = requests.get(_AV_BASE_URL, params=params, timeout=30)
resp.raise_for_status()
data = resp.json()
except Exception as e:
raise DataFetchError(f"[AlphaVantage] HTTP request failed for {symbol}: {e}") from e
if 'Note' in data:
raise DataFetchError(f"[AlphaVantage] Rate limited: {data['Note']}")
if 'Error Message' in data:
raise DataFetchError(f"[AlphaVantage] API error for {symbol}: {data['Error Message']}")
ts_key = 'Time Series (Daily)'
if ts_key not in data or not data[ts_key]:
raise DataFetchError(f"[AlphaVantage] No time series data for {symbol}")
rows = []
start = datetime.strptime(start_date, '%Y-%m-%d').date()
end = datetime.strptime(end_date, '%Y-%m-%d').date()
for date_str, values in data[ts_key].items():
row_date = datetime.strptime(date_str, '%Y-%m-%d').date()
if start <= row_date <= end:
rows.append({
'date': date_str,
'1. open': float(values.get('1. open', 0)),
'2. high': float(values.get('2. high', 0)),
'3. low': float(values.get('3. low', 0)),View on GitHub (pinned to 5159bd72e8)
Solutions
- Check the Note text: 'per minute' limits clear in ~60s and are worth a retry; daily quota requires waiting or a paid key.
- Add caching (AV data only changes daily) and a per-minute request counter to stay under 5/min.
- Upgrade to a premium key or spread batch fetches across the day.
- Fall back to YfinanceFetcher/Akshare for US symbols while the AV quota resets.
Example fix
# before
for sym in us_syms:
df = av_fetcher.fetch(sym, start, end) # burns daily quota
# after
for i, sym in enumerate(us_syms):
try:
df = av_fetcher.fetch(sym, start, end)
except DataFetchError as e:
if 'Rate limited' in str(e):
time.sleep(60)
df = yfinance_fetcher.fetch(sym, start, end)
else:
raise Defensive patterns
Strategy: retry
Try / catch
try:
df = av_fetcher.fetch(sym, start, end)
except DataFetchError as e:
if 'Rate limited' in str(e):
if 'per minute' in str(e):
time.sleep(60)
df = av_fetcher.fetch(sym, start, end)
else: # daily quota exhausted
df = yfinance_fetcher.fetch(sym, start, end)
else:
raise Prevention
- Cache AV responses — daily data does not change intraday, so fetch each symbol at most once per day.
- Track your key's request count in-process and stop before hitting the tier limit.
- Remember this is a plain DataFetchError, not RateLimitError — rate-limit handling keyed on the subclass will miss it.
When it happens
Trigger: Exceeding the AlphaVantage quota for your key tier (classic free tier: 25 requests/day; historically 5/minute): the 26th call in a day, or a burst of calls within a minute, returns {'Note': '...rate limit...'}. Note the built-in random_sleep(0.5, 1.5) is far below the historical 5-req/min pace, so bursts can trigger it.
Common situations: Free-tier key used in batch backfills over hundreds of symbols; multiple processes sharing one key; tests hitting the live API without caching. Also note: this error is NOT a RateLimitError subclass here — it is a plain DataFetchError, so generic rate-limit handling keyed on RateLimitError will miss it.
Related errors
- Tushare 配额超限: {e}
- Akshare 所有渠道获取失败: {last_error}
- Akshare(EM) 可能被限流: {e}
- Akshare 可能被限流: {e}
- [AlphaVantage] API key not configured
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/549abc33f3e2476c.
Report an issue: GitHub.