ZhuLinsen/daily_stock_analysis · error · DataFetchError

efinance 获取 ETF 数据失败: {failure_message}

Error message

efinance 获取 ETF 数据失败: {failure_message}

What it means

Generic terminal failure of EfinanceFetcher._fetch_etf_data: the exception from the ETF history call was classified as non-rate-limit (parse/schema/network), re-raised as DataFetchError with the built failure message. ETF twin of error 151.

Source

Thrown at data_provider/efinance_fetcher.py:568

            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,
                is_etf=True,
            )

            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 获取 ETF 数据失败: {failure_message}") from e
    
    def _normalize_data(self, df: pd.DataFrame, stock_code: str) -> pd.DataFrame:
        """
        标准化 efinance 数据
        
        efinance 返回的列名(中文):
        股票名称, 股票代码, 日期, 开盘, 收盘, 最高, 最低, 成交量, 成交额, 振幅, 涨跌幅, 涨跌额, 换手率
        
        需要映射到标准列名:
        date, open, high, low, close, volume, amount, pct_chg
        """
        df = df.copy()
        
        # Column mapping (efinance Chinese column names -> standard English column names)
        column_mapping = {
            '日期': 'date',
            '开盘': 'open',
            '收盘': 'close',

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Read failure_message for the underlying exception and elapsed time to classify parse vs network.
  2. Verify the efinance version supports the stock-K-line call signature used in _fetch_etf_data (beg/end kwargs — see Issue #541 note).
  3. Fail over to akshare/tushare ETF daily data via the manager.
Defensive patterns

Strategy: fallback

Validate before calling

# verify efinance supports the stock-K-line kwargs used for ETFs
import efinance as ef, inspect
sig = inspect.signature(ef.stock.get_quote_history)
assert {'beg', 'end'} <= set(sig.parameters), 'efinance version incompatible with ETF path'

Try / catch

try:
    df = efinance_fetcher.get_daily_data(etf_code, ...)
except DataFetchError as e:
    df = manager.get_daily_data(etf_code, ...)  # akshare ETF fallback

Prevention

When it happens

Trigger: ETF history response shape unexpected (column rename, missing 单位净值-era fields); efinance version regression on the stock-K-line-for-ETF path (the code historically had Issue #541 with ef.fund.get_quote_history kwargs); non-throttle network faults.

Common situations: Upgrading efinance after the ETF path switched from fund API to stock API; ETF with tiny history returning degenerate frames.

Related errors


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