ZhuLinsen/daily_stock_analysis · warning · DataFetchError

AkshareFetcher 不支持美股 {stock_code},请使用 YfinanceFetcher 获取正确的复

Error message

AkshareFetcher 不支持美股 {stock_code},请使用 YfinanceFetcher 获取正确的复权价格

What it means

DataFetchError raised deliberately by AkshareFetcher when asked for a US stock: akshare's stock_us_daily has a known adjusted-price defect (akshare Issue #311), so the fetcher refuses US codes and instructs the caller to use YfinanceFetcher instead. This is a routing guard, not an incidental failure.

Source

Thrown at data_provider/akshare_fetcher.py:486

        
        根据代码类型自动选择 API:
        - 美股:不支持,抛出异常由 YfinanceFetcher 处理(Issue #311)
        - 港股:使用 ak.stock_hk_hist()
        - ETF 基金:使用 ak.fund_etf_hist_em()
        - 普通 A 股:使用 ak.stock_zh_a_hist()
        
        流程:
        1. 判断代码类型(美股/港股/ETF/A股)
        2. 设置随机 User-Agent
        3. 执行速率限制(随机休眠)
        4. 调用对应的 akshare API
        5. 处理返回数据
        """
        # 根据代码类型选择不同的获取方法
        if _is_us_code(stock_code):
            # 美股:akshare 的 stock_us_daily 接口复权存在已知问题(参见 Issue #311)
            # 交由 YfinanceFetcher 处理,确保复权价格一致
            raise DataFetchError(
                f"AkshareFetcher 不支持美股 {stock_code},请使用 YfinanceFetcher 获取正确的复权价格"
            )
        elif _is_hk_code(stock_code):
            return self._fetch_hk_data(stock_code, start_date, end_date)
        elif _is_etf_code(stock_code):
            return self._fetch_etf_data(stock_code, start_date, end_date)
        else:
            return self._fetch_stock_data(stock_code, start_date, end_date)
    
    def _fetch_stock_data(self, stock_code: str, start_date: str, end_date: str) -> pd.DataFrame:
        """
        获取普通 A 股历史数据

        策略:
        1. 优先尝试东方财富接口 (ak.stock_zh_a_hist)
        2. 失败后尝试新浪财经接口 (ak.stock_zh_a_daily)
        3. 最后尝试腾讯财经接口 (ak.stock_zh_a_hist_tx)
        """

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Use YfinanceFetcher for US stocks — it returns correctly adjusted prices.
  2. If you use the repo's data provider facade, ensure codes are routed by market (A/HK/ETF -> akshare, US -> yfinance).
  3. Catch DataFetchError with this message as a signal to reroute rather than retry.
  4. Do not attempt to bypass by stripping the US check — the underlying akshare data is known-bad for this case.

Example fix

# before
fetcher = AkshareFetcher()
df = fetcher.fetch_stock_data('AAPL', '2024-01-01', '2024-12-31')  # raises

# after
from data_provider.yfinance_fetcher import YfinanceFetcher
df = YfinanceFetcher().fetch_stock_data('AAPL', '2024-01-01', '2024-12-31')
Defensive patterns

Strategy: validation

Validate before calling

def pick_fetcher(stock_code: str):
    import re
    if re.fullmatch(r'[A-Z]{1,5}', stock_code.strip().upper()):
        return YfinanceFetcher()   # US codes -> yfinance
    return AkshareFetcher()        # A-share/HK/ETF -> akshare

fetcher = pick_fetcher('AAPL')

Type guard

from data_provider.exceptions import DataFetchError

def is_us_unsupported_by_akshare(exc: Exception) -> bool:
    return isinstance(exc, DataFetchError) and '请使用 YfinanceFetcher' in str(exc)

Try / catch

try:
    df = akshare_fetcher.fetch_stock_data(code, start, end)
except DataFetchError as e:
    if '请使用 YfinanceFetcher' in str(e):
        df = yfinance_fetcher.fetch_stock_data(code, start, end)  # reroute, don't retry akshare
    else:
        raise

Prevention

When it happens

Trigger: Calling AkshareFetcher.fetch_stock_data (directly or via a data provider that doesn't route by market) with a US code such as 'AAPL', 'AMD', 'TSLA' — detected by _is_us_code(stock_code).

Common situations: Custom scripts or provider configurations that hardcode AkshareFetcher as the single source for all markets; new multi-market support added without per-market fetcher routing; accidentally passing a US ticker to an A-share pipeline.

Related errors


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