# 聚宽三策略移植回测总结(2026-07-27) 三策略(动量择时/价值精选/小市值IC对冲)从聚宽 py2 移植到 **BulletTrade 0.9.2**(聚宽API兼容),VPS 真实数据回测验证。 ## 一、回测结果(短区间验证逻辑) ⚠️ 区间短(性能瓶颈致长期回测不实用),收益**仅验证选股/交易逻辑通不通**,非真实长期表现。 | 策略 | 回测区间 | 持仓 | 累计收益 | 最大回撤 | 夏普 | 结论 | |------|---------|------|---------|---------|------|------| | 03 动量择时 | 2024-01~03 | 9宽基轮动 | +30.4% (年化472%) | -12.6% | 2.64 | 择时准(年初熊市空仓避跌、2月转牛吃反弹),短区间年化虚高 | | 02 小市值 | 2024-01~03 | 20只小盘 | -0.70% | -26.8% | -2.70 | 2024初小盘股灾期,中证2000 暴跌,亏损符合现实 | | 01 价值精选 | 2024-01~06 | 4~6只价值 | +23.0% | -27.6% | 0.94 | 2024上半年价值/红利风格强势,表现合理 | 三策略选股 + 调仓 + 撮合链路全部跑通,逻辑正确。 ## 二、策略问题清单 ### ✅ 已修正的 bug(回测实测发现) | 策略 | 原始问题 | 修正 | |------|---------|------| | 03 | `calRPS` 取数区间错(`get_price(start=cur,end=cur)` 只取1天)→ 涨跌幅恒0,RPS排名失效 | 取 `preDate~curDate` 区间算真实百分比涨跌幅 | | 03 | `date.today()` 取真实今天而非回测日(取数日期全错) | 改用 `context.current_dt` | | 01 | 排序死代码(`get_check_stocks_sort` 排序后不截断+全买,排序无意义) | 删除无意义排序,保留"全买"等额 | | 01 | **第⑥条致命bug**:注释"盈余成长率8-50%"但代码是 EPS 绝对值 0.08~0.5;大盘股EPS>0.5(茅台50/招行5)→ 与第①条大盘矛盾 → **6条交集恒空,策略空仓** | 按注释本意改"净利润同比增长率8-50%"(东财 `PARENT_NETPROFIT_YOY`),大盘股可入选 | | 01 | 前视偏差(`statDate` 按报告期取数,用到未披露数据) | `NOTICE_DATE` 公告日 ≤ 当前日 过滤 | | 01 | 冗余调用(`get_stock_list` 调2次) | 合并为1次 | | 02 | universe `000985`(中证全指) 不在 constituent_unified → 候选池空 → 8次调仓全 picked 0 | 改 `932000`(中证2000,2684只小盘) | | 02 | IC期货对冲(SubPortfolio/做空/期货)引擎不支持+无数据 | 对冲部分全部删除(记缺口),保留选股轮动 | ### ⚠️ 遗留问题(未修/性能/口径) | 策略 | 问题 | 状态 | |------|------|------| | 03/02 | **性能慢**(每日/每5日遍历大池子逐只算指标):03 每日遍历9宽基3000+只 RPS+均线;02 每次调仓遍历2684只动量(约5分钟/次) | 长期回测不实用,待 provider 批量取行情优化 | | 03 | ST 过滤用当前 display_name(非历史时点) | 轻微前视,未处理 | | 01 | ROE 非精确 TTM(累计净利润/期末权益,有季节性偏差) | 未处理(和市场均值比较相对影响小) | | 01 | L4=487 异常稳定(5年FCF正的股票数几乎不变) | 疑似 FCF 计算口径或数据覆盖问题,待查 | | 01 | universe 默认沪深300(原策略全市场5000+) | 避免逐只读三表爆炸,牺牲覆盖换可执行 | ## 三、数据缺口清单(给数据 session 补) | # | 缺口 | 影响策略 | 现状 | 当前缓解 | 建议 | |---|------|---------|------|---------|------| | 1 | **行业成份股**(证监会行业 A01 等 / 中证行业指数 000928-000938) | 03 | `constituent_unified` 只有9个宽基,无行业 | 用9宽基替代(板块粒度变粗) | 补行业成份股数据,恢复完整行业轮动 | | 2 | ~~三表覆盖率1/3~~ **[已撤回·误报]** 北交所920xxx三表空 | 01 | 全扫5530文件/表 **0损坏0空(<600B)**,沪深/创业/科创 **95%+健康**;仅北交所920xxx空(akshare不覆盖,~6%)。原"1/3有效"系小抽样误报(北交所排序尾部污染+可能schtask写入时序),2026-07-28全扫复核撤回 | universe排除北交所(0成本,已与filter_kcbj_stock一致) | 不做北交所即解;若做需jqdata/xtdata补 | | 3 | **IC 期货合约日线 + 月份切换** | 02 | 完全缺失 | 对冲部分去掉,只做选股 | 若要做对冲需补 IC 期货数据 + 扩展引擎做空能力 | | 4 | **中证全指 000985 成份股** | 02 | `constituent_unified` 无 | 改用 932000(中证2000,更小盘更激进) | 补 000985 或接受 932000 替代 | | 5 | ~~NOTICE_DATE 缺失~~ **[已撤回·误报]** | 01 | 全扫9/9有效文件**NOTICE_DATE 全有**,不缺 | 兜底逻辑保留但几乎不触发 | 无需补 | ## 四、性能瓶颈(共性,影响长期回测) 三策略选股都**遍历大池子逐只算指标**(provider 逐只查询 dbbardata/parquet),未批量/未缓存: | 策略 | 瓶颈 | 实测 | |------|------|------| | 03 | 每日遍历9宽基3000+只,逐只取30日行情算RPS+均线 | 2022-2024长回测 25分钟仅跑113天,停 | | 02 | 每次调仓遍历2684只逐只取130日行情算动量 | 每次调仓约5分钟,2月回测40分钟 | | 01 | 每次调仓读300只三表(沪深健康正常读取) | 可接受(月度调仓,半年6次约2分钟) | **优化方向(未做)**:provider 批量取行情(一次取一批股票N日close,pandas向量化算RPS/均线/动量),避免逐只查询。预计可提速10-50倍,使长期回测实用。 ## 五、产出文件 | 类型 | 文件 | |------|------| | 策略 | `sanguo_portfolio/strategies/{momentum_timing,value_selection,small_cap}.py` | | Provider | `sanguo_portfolio/providers/local_parquet_provider.py`(加 `get_value_metrics`)、`local_unified_provider.py`(委托) | | Runner | `sanguo_portfolio/runner_backtest.py`(`--strategy {all_weather,momentum_timing,value_selection,small_cap}` 分发) | | 测试 | `tests/portfolio/test_{momentum_timing,value_selection,small_cap}.py`(21+27+24 = **72单测全过**) | | 移植记录 | `docs/research/joinquant_strategies/{01,02,03}/notes.md` 各自「移植记录」节 | | 原始代码 | `docs/research/joinquant_strategies/{01,02,03}/source.py`(聚宽py2原样保留) | ## 六、怎么跑 ```bash # VPS(数据在 VPS 本地,Mac 无数据) ssh 49.232.102.198 "cd /d C:\sanguo_vnpy_v2 && C:\Python310\python.exe -X utf8 -m sanguo_portfolio.runner_backtest --strategy --provider unified --start 2024-01-01 --end 2024-06-30 --cash 1000000" # ∈ {momentum_timing, value_selection, small_cap, all_weather} ``` ## 七、一句话结论 三策略全部成功移植到 BulletTrade 并在 VPS 跑通回测(逻辑验证通过);过程中实测发现并修正了 **8个真实bug**(含策略01第⑥条致空仓的致命bug、策略03两个原帖回测失真的bug)。数据层真实缺口经全扫复核(2026-07-28,详见 `data_gaps_fix_plan.md`)为 **2 项**:行业成份股 + 中证全指000985 成份股缺失(阻断策略02/03 完整版);北交所920xxx 三表空(akshare不覆盖,universe排除即解,0成本)。~~原报"三表覆盖1/3 / NOTICE_DATE缺列"~~ 系小抽样误报(北交所排序尾部污染+schtask写入时序),全扫5530文件/表 0损坏、沪深95%+健康,**已撤回**。另性能瓶颈(逐只取指标)待 provider 批量优化跟进。