Files
sanguo_vnpy_v2/docs/research/joinquant_strategies/SUMMARY.md
T
claude_dev de04a8904b feat(portfolio): 移植3聚宽策略到BulletTrade + 8bug修正 + 数据缺口文档
三策略(聚宽py2→BulletTrade 0.9.2,BrokerFacade注入跨版本兼容):
- momentum_timing 动量择时(牛熊分界+行业RPS+均线,切回10中证行业指数)
- value_selection 价值精选(6条基本面过滤,切回沪深300)
- small_cap 小市值(去IC对冲,切回000985中证全指)

框架:
- runner_backtest 加 --strategy 分发(原硬编码all_weather)
- provider 加 get_value_metrics(价值精选6条基本面,NOTICE_DATE治前视偏差)
- 72单测全过(21+27+24)

修8个回测实测发现的真bug:
- 01第⑥条EPS绝对值0.08~0.5与①大盘矛盾→6条交集恒空致全程空仓,按注释本意改净利润同比8~50%
- 03原帖calRPS取数区间错(get_price start=end只取1天)→涨跌幅恒0 RPS失效;date.today()取真实今天非回测日
- 02 universe 000985不在constituent_unified→候选池空

VPS实测(短区间验证逻辑,非长期表现): 01价值+23%/03行业轮动+48%/02选出20只小盘

数据缺口(详见docs/research/joinquant_strategies/SUMMARY.md + data_gaps_fix_plan.md):
- 三表"1/3损坏"误报已撤回(全扫5530文件/表0损坏,沪深95%+健康,仅北交所920xxx空,不做北交所)
- 真实缺口: 行业成份股(G1已补)/000985(G2已补)/IC期货(02对冲去掉)/provider批量接口(G5待做,解锁长回测)
2026-07-28 22:20:49 +08:00

86 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 聚宽三策略移植回测总结(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`(中证20002684只小盘) |
| 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 <name> --provider unified --start 2024-01-01 --end 2024-06-30 --cash 1000000"
# <name> ∈ {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 批量优化跟进。