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

  1. Check the Note text: 'per minute' limits clear in ~60s and are worth a retry; daily quota requires waiting or a paid key.
  2. Add caching (AV data only changes daily) and a per-minute request counter to stay under 5/min.
  3. Upgrade to a premium key or spread batch fetches across the day.
  4. 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

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


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/549abc33f3e2476c. Report an issue: GitHub.