Files
daily_stock_analysis/tests/test_hk_realtime_routing.py
mumu 56772ec38e fix: 修复港股代码全链路支持 (Fixes #629, Fixes #691) (#694)
* fix: 修复港股代码全链路支持,避免误走 A 股路径 (Fixes #629, Fixes #691)

- validation.ts: 新增 /^HK\d{5}$/ 港股前缀格式校验,修复 Web 端 HK01810 被拒问题
- base.py: normalize_stock_code 支持 1810.HK / hk1810 归一为 HK01810;
         _is_hk_market 精确匹配 HK+纯数字,防止误匹配;
         DataFetcherManager.get_realtime_quote 新增港股专用快速路径,
         直接调用 akshare_hk,不再按 A 股 source_priority 多次尝试
- tushare_fetcher.py: 四处方法(_convert_stock_code / _fetch_raw_data /
  get_realtime_quote / get_stock_name)增加 HK 早退,避免港股误走深市
- baostock_fetcher.py: 两处方法增加 HK 早退,防止生成 sz.HK01810 等无效请求
- pytdx_fetcher.py: 两处方法增加 HK 早退,规避 36 秒连接超时
- akshare_fetcher.py: get_chip_distribution 增加 HK 早退(stock_cyq_em 仅支持 A 股)
- data_tools.py: DataFetcherManager 改为 singleton,避免每次工具调用重置熔断器;
                 get_realtime_quote 失败时返回 retriable=false,阻止 LLM 重试
- runner.py: 新增工具调用非兼容缓存(non_retriable_tool_results),
             HK 代码不同写法(HK01810 / 1810.HK)共享同一缓存 key
- tests: 新增 test_hk_realtime_routing.py;补充 test_stock_code_bse / test_agent_executor

* fix: reset agent fetcher singleton on config reload

* fix: align web hk validation with backend formats
2026-03-16 00:24:54 +08:00

56 lines
1.7 KiB
Python

# -*- coding: utf-8 -*-
"""
Regression tests for Hong Kong realtime quote routing.
"""
import sys
import unittest
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
if "litellm" not in sys.modules:
sys.modules["litellm"] = MagicMock()
if "json_repair" not in sys.modules:
sys.modules["json_repair"] = MagicMock()
from data_provider.base import DataFetcherManager
class _DummyFetcher:
def __init__(self, name: str, priority: int, result=None):
self.name = name
self.priority = priority
self.result = result
self.calls = []
def get_realtime_quote(self, *args, **kwargs):
self.calls.append((args, kwargs))
return self.result
class TestHKRealtimeRouting(unittest.TestCase):
"""Ensure HK realtime lookup does not fan out into A-share sources."""
@patch("src.config.get_config")
def test_manager_routes_hk_suffix_only_to_akshare_once(self, mock_get_config):
mock_get_config.return_value = SimpleNamespace(
enable_realtime_quote=True,
realtime_source_priority="tencent,akshare_sina,efinance,akshare_em,tushare",
)
efinance = _DummyFetcher("EfinanceFetcher", 0, result={"should": "not be called"})
akshare = _DummyFetcher("AkshareFetcher", 1, result=None)
tushare = _DummyFetcher("TushareFetcher", 2, result={"should": "not be called"})
manager = DataFetcherManager(fetchers=[efinance, akshare, tushare])
quote = manager.get_realtime_quote("1810.HK")
self.assertIsNone(quote)
self.assertEqual(akshare.calls, [(("HK01810",), {"source": "hk"})])
self.assertEqual(efinance.calls, [])
self.assertEqual(tushare.calls, [])
if __name__ == "__main__":
unittest.main()