Files
sanguo_vnpy_v2/scripts/data_platform/verify_unified_e2e.py
T
claude_dev 41cc6d13bf feat(portfolio): LocalUnifiedProvider spec §6 使用层落地 + VPS E2E(Task6)
spec §6 使用层 provider — 读方案A 权威数据层, 零 online, 治幸存者偏差:
- get_price: dbbardata('d') raw + bs_adjust_factor 前复权(asof, qfq[t]=raw[t]*factor[t])
- get_index_stocks/get_constituent: constituent_unified 并集治偏差(300=940含被踢, 无date时点)
- get_fundamentals_df: baostock pe/pb/ps/pcf + akshare 市值 + 三表委托 LocalParquetProvider
- 辅助: trade_days/security_info/current_tick/split_dividend/all_securities

VPS E2E 实证修复(Mac fixture 盲区):
- dbbardata datetime 混合格式("2024-09-26" vs "2024-09-26 00:00:00")
  → pd.to_datetime format='mixed' + SQL substr(datetime,1,10) 比日期(字符串比漏边界)
- 补 TestMixedDatetimeFormat 单测覆盖

验证: VPS 真数据 E2E 全通过(600519在市raw/qfq复权/000005退市治偏差/510300ETF/
fundamentals市值+pe+eps全字段/辅助方法); Mac 37单测+149回归绿

交付: 使用说明 docs/portfolio_local_unified_provider.md(其他 session 直用)+
plan+probe+E2E 脚本
2026-07-23 08:25:44 +08:00

58 lines
3.0 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""verify_unified_e2e.py — LocalUnifiedProvider VPS 真数据 E2E(spec §6 Task6)。
直接实例化 provider 测三大接口(不跑 bullet_trade 全回测,精确验证):
- get_price 读 dbbardata('d'): 在市(600519)/退市(000005 治偏差)/ETF(510300) + raw vs qfq 复权
- get_index_stocks 并集(constituent_unified,含被踢)
- get_fundamentals_df 市值(akshare)+ pe/pb(baostock)+ 三表
每步 flush(ssh 非交互 stdout block-buffered)。避开 get_all_securities(全表 distinct 28GB 慢)。
"""
import sys
sys.path.insert(0, r"C:\sanguo_vnpy_v2")
try:
sys.stdout.reconfigure(line_buffering=True) # 每行 flush
except Exception:
pass
from sanguo_portfolio.providers import LocalUnifiedProvider
p = LocalUnifiedProvider()
def step(title):
print(f"\n===== {title} =====", flush=True)
step("1. get_price 读 dbbardata('d') 混合 datetime 格式")
df = p.get_price("600519.XSHG", start_date="2024-09-25", end_date="2024-09-30", fq="raw")
print(f"600519 raw: {len(df)}", df.tail(1).to_dict("records") if len(df) else "EMPTY", flush=True)
df_q = p.get_price("600519.XSHG", start_date="2024-09-25", end_date="2024-09-30", fq="qfq")
print(f"600519 qfq(前复权): {len(df_q)}", df_q.tail(1).to_dict("records") if len(df_q) else "EMPTY", flush=True)
df_d = p.get_price("000005.XSHE", start_date="2024-04-20", end_date="2024-04-30")
print(f"000005 退市(治偏差): {len(df_d)}", "✅有数据" if len(df_d) else "❌空!偏差未治", flush=True)
df_e = p.get_price("510300.SH", start_date="2024-09-25", end_date="2024-09-30")
print(f"510300 ETF(xtata源): {len(df_e)}", flush=True)
df_p = p.get_price(["600519.XSHG", "000001.XSHE"], end_date="2024-09-30", count=2, panel=False, fields=["close"])
print(f"panel=False 长表: {len(df_p)} 行, 列={list(df_p.columns) if len(df_p) else 'EMPTY'}", flush=True)
step("2. get_index_stocks 并集(constituent_unified 治偏差)")
for idx in ["000300.XSHG", "000905.XSHG", "000016.XSHG"]:
s = p.get_index_stocks(idx)
print(f" {idx}: {len(s)} 只(含被踢) e.g. {s[:2]}", flush=True)
print(f" get_constituent 别名 300: {len(p.get_constituent('000300'))}", flush=True)
step("3. get_fundamentals_df(市值 akshare + pe/pb baostock + 三表)")
fund = p.get_fundamentals_df(["600519.XSHG", "000001.XSHE"], date="2024-09-30")
cols = ["code", "market_cap", "circulating_market_cap", "pe_ratio", "pb_ratio", "ps_ratio", "eps"]
print(fund[cols].to_string(), flush=True)
step("4. 辅助方法(轻量,避全表扫)")
print("get_trade_days(count=3):", [d.strftime("%Y-%m-%d") for d in p.get_trade_days(count=3)], flush=True)
print("get_security_info 600519:", p.get_security_info("600519.XSHG"), flush=True)
tick = p.get_current_tick("600519.XSHG")
print("get_current_tick:", {k: tick[k] for k in ("close", "high_limit", "low_limit")} if tick else None, flush=True)
print("get_split_dividend 600519(2024):", len(p.get_split_dividend("600519.XSHG", "2024-01-01", "2024-12-31")), "事件", flush=True)
print("\nE2E DONE — LocalUnifiedProvider VPS 真数据验证通过", flush=True)