{"record":{"id":"f0138b93bb8fc244","repo":"ZhuLinsen/daily_stock_analysis","slug":"pytdxfetcher-stock-code","errorCode":null,"errorMessage":"PytdxFetcher 不支持北交所 {stock_code}，将自动切换其他数据源","messagePattern":"PytdxFetcher 不支持北交所 (.+?)，将自动切换其他数据源","errorType":"exception","errorClass":"DataFetchError","httpStatus":null,"severity":"error","filePath":"data_provider/pytdx_fetcher.py","lineNumber":332,"sourceCode":"        使用 get_security_bars() 获取日线数据\n        \n        流程：\n        1. 检查是否为美股（不支持）\n        2. 使用上下文管理器管理连接\n        3. 判断市场代码\n        4. 调用 API 获取 K 线数据\n        \"\"\"\n        # 美股不支持，抛出异常让 DataFetcherManager 切换到其他数据源\n        if _is_us_code(stock_code):\n            raise DataFetchError(f\"PytdxFetcher 不支持美股 {stock_code}，请使用 AkshareFetcher 或 YfinanceFetcher\")\n\n        # 港股不支持，抛出异常让 DataFetcherManager 切换到其他数据源\n        if _is_hk_market(stock_code):\n            raise DataFetchError(f\"PytdxFetcher 不支持港股 {stock_code}，请使用 AkshareFetcher\")\n\n        # 北交所不支持，抛出异常让 DataFetcherManager 切换到其他数据源\n        if is_bse_code(stock_code):\n            raise DataFetchError(\n                f\"PytdxFetcher 不支持北交所 {stock_code}，将自动切换其他数据源\"\n            )\n        \n        market, code = self._get_market_code(stock_code)\n        \n        # 计算需要获取的交易日数量（估算）\n        from datetime import datetime as dt\n        start_dt = dt.strptime(start_date, '%Y-%m-%d')\n        end_dt = dt.strptime(end_date, '%Y-%m-%d')\n        days = (end_dt - start_dt).days\n        count = min(max(days * 5 // 7 + 10, 30), 800)  # 估算交易日，最大 800 条\n        \n        logger.debug(f\"调用 Pytdx get_security_bars(market={market}, code={code}, count={count})\")\n        \n        with self._pytdx_session() as api:\n            try:\n                # 获取日 K 线数据\n                # category: 9-日线, 0-5分钟, 1-15分钟, 2-30分钟, 3-1小时","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/data_provider/pytdx_fetcher.py#L314-L350","documentation":"DataFetchError raised in PytdxFetcher._fetch_raw_data when is_bse_code(stock_code) is true (Beijing Stock Exchange, 8xxxxx/4xxxxx codes). The free TDX endpoints used here lack BSE coverage, so the fetcher declines and relies on the manager to switch data sources.","triggerScenarios":"Requesting daily K-line history for a BSE-listed code (e.g. 83xxxx, 43xxxx, 92xxxx patterns matched by is_bse_code) from PytdxFetcher.","commonSituations":"Watchlists extended with 北交所 stocks while the provider chain still has pytdx as first A-share source; BSE IPOs added to scheduled analysis without provider coverage review.","solutions":["Put a BSE-capable provider (e.g. Akshare/Tushare) ahead of pytdx for BSE codes, or exclude pytdx from BSE routing.","Pre-filter with is_bse_code at the dispatch layer.","Confirm the replacement provider actually covers BSE daily bars before switching."],"exampleFix":"# before\ndf = pytdx_fetcher.get_stock_data(\"832566\", start, end)  # DataFetchError\n\n# after\nfrom src.utils.stock_utils import is_bse_code\nprovider = akshare_fetcher if is_bse_code(code) else pytdx_fetcher\ndf = provider.get_stock_data(code, start, end)","handlingStrategy":"type-guard","validationCode":"from src.utils.stock_utils import is_bse_code\n\nfetcher = akshare_fetcher if is_bse_code(stock_code) else pytdx_fetcher","typeGuard":"from src.utils.stock_utils import is_bse_code\n\ndef is_bse_symbol(code: str) -> bool:\n    \"\"\"True when the code is a Beijing Stock Exchange listing.\"\"\"\n    return is_bse_code(code)","tryCatchPattern":"try:\n    df = pytdx_fetcher.get_stock_data(code, start, end)\nexcept DataFetchError as e:\n    if \"北交所\" in str(e):\n        df = akshare_fetcher.get_stock_data(code, start, end)\n    else:\n        raise","preventionTips":["Keep a market classifier (SH/SZ/BJ/HK/US) as a single shared utility and use it for all routing.","When adding BSE names to watchlists, verify provider coverage first."],"tags":["pytdx","market-coverage","bse","routing"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}