{"record":{"id":"7b278d96bb9bf266","repo":"ZhuLinsen/daily_stock_analysis","slug":"alphavantage-no-data-in-date-range-for-symbol","errorCode":null,"errorMessage":"[AlphaVantage] No data in date range for {symbol}","messagePattern":"\\[AlphaVantage\\] No data in date range for (.+?)","errorType":"exception","errorClass":"DataFetchError","httpStatus":null,"severity":"warning","filePath":"data_provider/alphavantage_fetcher.py","lineNumber":88,"sourceCode":"            raise DataFetchError(f\"[AlphaVantage] No time series data for {symbol}\")\n\n        rows = []\n        start = datetime.strptime(start_date, '%Y-%m-%d').date()\n        end = datetime.strptime(end_date, '%Y-%m-%d').date()\n        for date_str, values in data[ts_key].items():\n            row_date = datetime.strptime(date_str, '%Y-%m-%d').date()\n            if start <= row_date <= end:\n                rows.append({\n                    'date': date_str,\n                    '1. open': float(values.get('1. open', 0)),\n                    '2. high': float(values.get('2. high', 0)),\n                    '3. low': float(values.get('3. low', 0)),\n                    '4. close': float(values.get('4. close', 0)),\n                    '5. volume': float(values.get('5. volume', 0)),\n                })\n\n        if not rows:\n            raise DataFetchError(f\"[AlphaVantage] No data in date range for {symbol}\")\n\n        df = pd.DataFrame(rows)\n        df.index = pd.to_datetime(df['date'])\n        df.index.name = None  # 避免与 _normalize_data 重新添加的 'date' 列冲突\n        return df.drop(columns=['date'])\n\n    def _normalize_data(self, df: pd.DataFrame, stock_code: str) -> pd.DataFrame:\n        if df.empty:\n            return df\n\n        df = df.copy()\n        df['date'] = pd.to_datetime(df.index).date\n        df = df.rename(columns={\n            '1. open': 'open', '2. high': 'high', '3. low': 'low',\n            '4. close': 'close', '5. volume': 'volume',\n        })\n        # AlphaVantage returns newest-first; sort ascending before computing pct_chg\n        df = df.sort_values('date', ascending=True).reset_index(drop=True)","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/data_provider/alphavantage_fetcher.py#L70-L106","documentation":"A DataFetchError raised by AlphaVantageFetcher._fetch_raw_data when the time series parsed successfully but zero rows fall inside the requested [start_date, end_date] window. AV's 'compact' outputsize returns only the most recent ~100 trading points, so older date ranges yield no matching rows even though the symbol is valid.","triggerScenarios":"Requesting a date range older than the last ~100 trading days (outputsize is hardcoded to 'compact'); requesting a range entirely in the future; weekends/holidays-only ranges for very recent windows; symbol whose recent data ends before start_date (delisted).","commonSituations":"Backfill jobs asking for years of history with a compact response; end_date accidentally formatted wrong (e.g. '2025-13-01' parsing failure happens earlier, but swapped day/month can silently shift the window); delisted symbols.","solutions":["If you need >100 days of history, request with outputsize='full' (requires editing the params in the fetcher or using a custom call).","Verify start/end are within the last ~100 trading days when using compact mode.","Check the symbol still trades; delisted ones have no recent rows.","Fall back to Yfinance (free full history) for long backfills."],"exampleFix":"# before (in alphavantage_fetcher.py params)\n'outputsize': 'compact',  # only ~100 recent points\n\n# after\n'outputsize': 'full',  # full history; heavier response","handlingStrategy":"fallback","validationCode":"from datetime import date, timedelta\ncompact_horizon = date.today() - timedelta(days=150)  # ~100 trading days\nif date.fromisoformat(start_date) < compact_horizon:\n    logger.info('range older than compact window; prefer a full-history source')","typeGuard":null,"tryCatchPattern":"try:\n    df = av_fetcher.fetch(sym, start, end)\nexcept DataFetchError as e:\n    if 'No data in date range' in str(e):\n        df = yfinance_fetcher.fetch(sym, start, end)  # free full history\n    else:\n        raise","preventionTips":["Remember outputsize is hardcoded 'compact' (~100 recent points); long backfills belong on Yfinance.","Validate start_date <= end_date and both within recent history before calling.","For symbols that may be delisted, fall back instead of failing the batch."],"tags":["alphavantage","date-range","compact-output","backfill"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}