124 lines
4.8 KiB
Python
124 lines
4.8 KiB
Python
"""真实数据源集成测试。"""
|
||
|
||
import os
|
||
import random
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
|
||
from sidecar.config import SidecarConfig
|
||
from sidecar.service import UnifiedDataService
|
||
from sidecar.sources.mootdx_source import MootdxSource
|
||
from sidecar.sources.tencent import TencentFinanceSource
|
||
from sidecar.storage import DuckDBStore
|
||
|
||
pytestmark = pytest.mark.skipif(
|
||
os.getenv("RUN_REAL_MARKET_TESTS") != "1",
|
||
reason="真实网络测试需设置 RUN_REAL_MARKET_TESTS=1",
|
||
)
|
||
|
||
|
||
def test_3_1_real_tencent_snapshot() -> None:
|
||
"""
|
||
功能说明:验证腾讯财经真实快照接口可用。
|
||
参数说明:无。
|
||
返回值说明:无返回值。
|
||
注意事项:用例编号 3-1,需要可访问 qt.gtimg.cn。
|
||
"""
|
||
snapshot = TencentFinanceSource(timeout_seconds=10).fetch_snapshot("600000")
|
||
|
||
assert snapshot.symbol == "sh600000"
|
||
assert snapshot.name
|
||
assert snapshot.price is not None
|
||
assert snapshot.source == "tencent"
|
||
|
||
|
||
def test_3_2_real_mootdx_kline() -> None:
|
||
"""
|
||
功能说明:验证 mootdx 真实 K 线接口可用。
|
||
参数说明:无。
|
||
返回值说明:无返回值。
|
||
注意事项:用例编号 3-2,需要可连接通达信行情服务器。
|
||
"""
|
||
bars = MootdxSource().fetch_kline("600000", "day", 5)
|
||
|
||
assert len(bars) > 0
|
||
assert bars[-1].symbol == "sh600000"
|
||
assert bars[-1].close is not None
|
||
assert bars[-1].source == "mootdx"
|
||
|
||
|
||
def test_3_3_real_unified_service_cache(tmp_path: Path) -> None:
|
||
"""
|
||
功能说明:验证统一服务可使用真实数据源写入 DuckDB 缓存。
|
||
参数说明:tmp_path 为 pytest 临时目录。
|
||
返回值说明:无返回值。
|
||
注意事项:用例编号 3-3,同时覆盖腾讯快照、mootdx K 线和 DuckDB 往返。
|
||
"""
|
||
config = SidecarConfig(db_path=str(tmp_path / "real.duckdb"), snapshot_ttl_seconds=60)
|
||
store = DuckDBStore(config.db_path)
|
||
mootdx = MootdxSource()
|
||
service = UnifiedDataService(store, config, mootdx, [TencentFinanceSource(10), mootdx])
|
||
|
||
bars = service.get_kline("600000", limit=5, refresh=True)
|
||
snapshot = service.get_snapshot("600000", refresh=True)
|
||
|
||
assert len(bars) > 0
|
||
assert store.load_kline("sh600000", "day", 5)
|
||
assert snapshot.price is not None
|
||
assert store.load_snapshot("sh600000") is not None
|
||
|
||
|
||
def assert_random_kline_prices_match(symbols, sample_size: int, seed: int) -> None:
|
||
"""
|
||
功能说明:随机抽取多个代码的 K 线价格并比较 mootdx 与腾讯财经是否基本一致。
|
||
参数说明:symbols 为待比较代码列表,sample_size 为抽样值数量,seed 为固定随机种子。
|
||
返回值说明:无返回值。
|
||
注意事项:仅比较 OHLC 价格,成交量和成交额因接口口径差异不参与比较。
|
||
"""
|
||
fields = ["open", "high", "low", "close"]
|
||
mootdx = MootdxSource()
|
||
tencent = TencentFinanceSource(timeout_seconds=10)
|
||
candidates = []
|
||
|
||
for symbol in symbols:
|
||
mootdx_bars = {bar.trade_date: bar for bar in mootdx.fetch_kline(symbol, "day", 60)}
|
||
tencent_bars = {bar.trade_date: bar for bar in tencent.fetch_kline(symbol, "day", 60)}
|
||
for trade_date in sorted(set(mootdx_bars) & set(tencent_bars)):
|
||
for field in fields:
|
||
mootdx_value = getattr(mootdx_bars[trade_date], field)
|
||
tencent_value = getattr(tencent_bars[trade_date], field)
|
||
if mootdx_value is not None and tencent_value is not None:
|
||
candidates.append((symbol, trade_date, field, mootdx_value, tencent_value))
|
||
|
||
assert len(candidates) >= sample_size
|
||
|
||
samples = random.Random(seed).sample(candidates, sample_size)
|
||
mismatches = [
|
||
(symbol, trade_date, field, mootdx_value, tencent_value)
|
||
for symbol, trade_date, field, mootdx_value, tencent_value in samples
|
||
if abs(mootdx_value - tencent_value) > 0.05
|
||
]
|
||
|
||
assert mismatches == []
|
||
|
||
|
||
def test_3_4_real_mootdx_index_kline_matches_tencent() -> None:
|
||
"""
|
||
功能说明:验证 mootdx 指数 K 线与腾讯财经 K 线价格基本一致。
|
||
参数说明:无。
|
||
返回值说明:无返回值。
|
||
注意事项:用例编号 3-4,随机抽取上证指数、深证成指、创业板指共 100 个 OHLC 值对比。
|
||
"""
|
||
assert_random_kline_prices_match(["sh000001", "sz399001", "sz399006"], 100, 20260623)
|
||
|
||
|
||
def test_3_5_real_mootdx_component_kline_matches_tencent() -> None:
|
||
"""
|
||
功能说明:验证三大指数代表成分股的 mootdx K 线与腾讯财经 K 线价格基本一致。
|
||
参数说明:无。
|
||
返回值说明:无返回值。
|
||
注意事项:用例编号 3-5,分别选取贵州茅台、平安银行、宁德时代并随机抽取 100 个 OHLC 值对比。
|
||
"""
|
||
assert_random_kline_prices_match(["sh600519", "sz000001", "sz300750"], 100, 20260624)
|