ZhuLinsen/daily_stock_analysis · error · DataFetchError
无法识别 ETF 代码 {stock_code}
Error message
无法识别 ETF 代码 {stock_code} What it means
Raised by _build_eastmoney_etf_secid in EfinanceFetcher: after normalize_stock_code, the code does not satisfy _is_a_share_etf_code, so no Eastmoney ETF secid can be built. It is a routing/classification error — a non-A-share-ETF code reached the A-share ETF K-line path.
Source
Thrown at data_provider/efinance_fetcher.py:173
ETF 代码规则:
- 上交所 ETF: 51xxxx, 52xxxx, 56xxxx, 58xxxx
- 深交所 ETF: 15xxxx, 16xxxx, 18xxxx
Args:
stock_code: 股票/基金代码
Returns:
True 表示是 ETF 代码,False 表示是普通股票代码
"""
return _is_a_share_etf_code(stock_code)
def _build_eastmoney_etf_secid(stock_code: str) -> str:
"""Build Eastmoney secid for A-share ETF historical K-line queries."""
code = normalize_stock_code(stock_code)
if not _is_etf_code(code):
raise DataFetchError(f"无法识别 ETF 代码 {stock_code}")
if code.startswith(_ETF_SH_PREFIXES):
return f"1.{code}"
if code.startswith(_ETF_SZ_PREFIXES):
return f"0.{code}"
raise DataFetchError(f"无法确定 ETF {stock_code} 的 Eastmoney 市场前缀")
def _is_us_code(stock_code: str) -> bool:
"""
判断代码是否为美股
美股代码规则:
- 1-5个大写字母,如 'AAPL', 'TSLA'
- 可能包含 '.',如 'BRK.B'
"""
code = stock_code.strip().upper()
return bool(re.match(r'^[A-Z]{1,5}(\.[A-Z])?$', code))
View on GitHub (pinned to 5159bd72e8)
Solutions
- Verify the code is a genuine A-share ETF (SH 51/56/58/60 prefixes, SZ 15/16/18 prefixes per _ETF_SH_PREFIXES/_ETF_SZ_PREFIXES).
- Check what normalize_stock_code does to the input — ensure you pass the bare 6-digit code without exchange suffix.
- If you support new ETF prefixes, extend _ETF_SH_PREFIXES/_ETF_SZ_PREFIXES rather than bypassing the check.
Example fix
# before
fetcher.get_daily_data('510300.SH', ...) # suffix may break classification
# after
fetcher.get_daily_data('510300', ...) Defensive patterns
Strategy: validation
Validate before calling
from data_provider.efinance_fetcher import _is_etf_code
code = normalize_stock_code(user_input)
if not _is_etf_code(code):
raise ValueError(f'{user_input} is not an A-share ETF; route to stock path') Type guard
def is_a_share_etf(code: str) -> bool:
c = normalize_stock_code(code)
return _is_etf_code(c) Try / catch
try:
df = fetcher.get_daily_data(code, ...)
except DataFetchError as e:
if '无法识别 ETF' in str(e):
df = fetcher._fetch_stock_data(code, ...) # or route via manager Prevention
- Normalize codes (strip exchange suffixes) before passing to fetchers.
- Maintain the ETF prefix whitelist against exchange fund lists.
- Add unit tests covering LOF/odd-prefix codes for the classifier.
When it happens
Trigger: Calling EfinanceFetcher._fetch_etf_data (or get_daily_data routed to the ETF branch because _is_etf_code matched) with a code that normalize_stock_code mangles or that matches the outer ETF heuristic but not _is_a_share_etf_code — e.g. LOF/funds with unexpected prefixes, codes with typos, or non-CN fund identifiers.
Common situations: User passes a mutual-fund or bond code (e.g. 5-digit odd prefix) that the generic ETF heuristic accepts but the A-share ETF prefix list rejects; code normalization strips or keeps a suffix inconsistently.
Related errors
- 无法确定 ETF {stock_code} 的 Eastmoney 市场前缀
- efinance 获取 ETF 数据失败: {failure_message}
- Backend executable not found: ${backendPath}
- Invalid share image record ID
- Desktop backend URL is unavailable
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/4f97ab32c7171884.
Report an issue: GitHub.