ZhuLinsen/daily_stock_analysis · error · DataFetchError
efinance 获取数据失败: {failure_message}
Error message
efinance 获取数据失败: {failure_message} What it means
Generic terminal failure of EfinanceFetcher._fetch_stock_data: _build_history_failure_message classified the exception as something other than rate-limit/anti-bot (parse error, schema change, KeyError, network fault), and it is re-raised as DataFetchError with the categorized failure message attached.
Source
Thrown at data_provider/efinance_fetcher.py:474
return df
except Exception as e:
api_elapsed = time.time() - api_start
category, failure_message = self._build_history_failure_message(
stock_code=stock_code,
beg_date=beg_date,
end_date=end_date_fmt,
exc=e,
elapsed=api_elapsed,
)
if category == "rate_limit_or_anti_bot":
logger.warning(failure_message)
raise RateLimitError(f"efinance 可能被限流: {failure_message}") from e
logger.error(failure_message)
raise DataFetchError(f"efinance 获取数据失败: {failure_message}") from e
def _fetch_etf_data(self, stock_code: str, start_date: str, end_date: str) -> pd.DataFrame:
"""
获取 ETF 基金历史数据
Exchange-traded ETFs have OHLCV data just like regular stocks, so we use
ef.stock.get_quote_history (the stock K-line API) which returns full
open/high/low/close/volume data.
Previously this method used ef.fund.get_quote_history which only returns
NAV data (单位净值/累计净值) without volume or OHLC, causing:
- Issue #541: 'got an unexpected keyword argument beg'
- Issue #527: ETF volume/turnover always showing 0
Args:
stock_code: ETF code, e.g. '512400', '159883', '515120'
start_date: Start date, format 'YYYY-MM-DD'
end_date: End date, format 'YYYY-MM-DD'View on GitHub (pinned to 5159bd72e8)
Solutions
- Read failure_message — it embeds the original exception and elapsed time, pinpointing parse vs network.
- Pin or upgrade efinance to a version known to match the parsing code (check requirements.txt consistency).
- If persistent, fail over via the manager to akshare/tushare and file/adjust the efinance normalizer.
Defensive patterns
Strategy: fallback
Validate before calling
# smoke-test the parsing path before batch runs
raw = efinance_fetcher._fetch_raw_data('600519', start, end)
normalized = efinance_fetcher._normalize_data(raw, '600519')
assert not normalized.empty Try / catch
try:
df = efinance_fetcher.get_daily_data(code, ...)
except DataFetchError as e:
logger.warning('efinance parse failed for %s: %s', code, e.__cause__)
df = manager.get_daily_data(code, ...) # akshare/tushare fallback Prevention
- Pin the efinance version in requirements.txt and retest parsing on upgrades.
- Add schema contract tests for Eastmoney response columns.
- Include e.__cause__ in logs — the wrapper message hides the concrete exception type.
When it happens
Trigger: ef.stock.get_quote_history succeeding HTTP-wise but returning an unexpected shape; efraction/efinance library version changes renaming columns; KeyError/AttributeError inside response processing; non-throttle network errors.
Common situations: efinance package upgraded and response schema drifted; Eastmoney changed field names; stock suspended long-term returning a degenerate payload.
Related errors
- efinance 获取 ETF 数据失败: {failure_message}
- 大盘复盘未返回可持久化报告
- {call_name} 调用超过 {wait_seconds:g}s,已放弃等待
- {call_name} 调用进程未返回结果
- AkshareFetcher 不支持美股 {stock_code},请使用 YfinanceFetcher 获取正确的复
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/2039c8f8df20e38c.
Report an issue: GitHub.