ZhuLinsen/daily_stock_analysis · error · DataFetchError

Tushare 获取数据失败: {e}

Error message

Tushare 获取数据失败: {e}

What it means

The catch-all DataFetchError for TushareFetcher: any exception from the pro API call that does NOT match the quota keywords ('quota'/'配额'/'limit'/'权限') is wrapped here. Typical roots are network failures to api.tushare.pro, invalid/expired token rejected at call time, unsupported ts_code after conversion, or interface-argument errors (bad start/end date).

Source

Thrown at data_provider/tushare_fetcher.py:546

            else:
                # Regular A-share stocks use daily interface
                df = self._api.daily(
                    ts_code=ts_code,
                    start_date=ts_start,
                    end_date=ts_end,
                )
            
            return df
            
        except Exception as e:
            error_msg = str(e).lower()
            
            # 检测配额超限
            if any(keyword in error_msg for keyword in ['quota', '配额', 'limit', '权限']):
                logger.warning(f"Tushare 配额可能超限: {e}")
                raise RateLimitError(f"Tushare 配额超限: {e}") from e
            
            raise DataFetchError(f"Tushare 获取数据失败: {e}") from e
    
    def _normalize_data(self, df: pd.DataFrame, stock_code: str) -> pd.DataFrame:
        """
        标准化 Tushare 数据
        
        Tushare daily / fund_daily 返回的列名:
        ts_code, trade_date, open, high, low, close, pre_close, change, pct_chg, vol, amount
        
        需要映射到标准列名:
        date, open, high, low, close, volume, amount, pct_chg

        单位缩放仅适用于 A 股(及 ETF 等使用同一套单位的接口):
        - vol 按「手」计,乘以 100 转为「股」
        - amount 按「千元」计,乘以 1000 转为「元」

        港股 hk_daily 返回的 vol / amount 已是可直接使用的量级,不做上述缩放。
        """
        df = df.copy()

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Read the chained cause (raise ... from e) — the original exception text in {e} identifies network vs auth vs argument errors.
  2. Verify the converted ts_code: python -c on _convert_stock_code for the failing symbol and test it on tushare.pro's online console.
  3. Check connectivity/egress to api.tushare.pro and retry transient network failures.
  4. If persistent, let the fallback chain serve the symbol from Akshare/Yfinance and file the ts_code issue with the converter.
Defensive patterns

Strategy: fallback

Validate before calling

import socket

# cheap reachability check before a batch run
try:
    socket.create_connection(("api.tushare.pro", 443), timeout=5).close()
    reachable = True
except OSError:
    reachable = False

Try / catch

try:
    df = tushare_fetcher.fetch_stock_data(code)
except DataFetchError as e:
    logger.warning("Tushare failed for %s: %s; falling back", code, e)
    df = akshare_fetcher.fetch_stock_data(code)  # or yfinance, per market

Prevention

When it happens

Trigger: POST to api.tushare.pro timing out or DNS-failing; token invalidated after construction; _convert_stock_code producing a ts_code Tushare rejects; passing dates where ts_start > ts_end or in wrong format; HK code routed to hk_daily without permission (message lacking quota keywords).

Common situations: Running in CI/scheduled Actions with restricted egress; token rotated but process holds old config; watchlist containing codes (e.g. odd ETF prefixes) the converter mishandles; weekends/holidays yielding empty ranges that some interfaces reject.

Related errors


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