Doubles 策略总览
来源: Obsidian Vault
Doubles 策略总览
A 股翻倍股 (Doubled Stocks) 选股 + 因子挖掘策略 — 模型端 FINAL(2026-06-14) 代码:
/opt/claude/doubles主仓库 +/opt/claude/RD-Agent实验层 生产配置:v5 + K=20 + N=10 + soft sector cap=4
一、原理
核心假设
A 股散户主导,历史已翻倍的股票(近 3 个月股价涨幅 ≥ 100%)具有可识别的共性特征。在这些"翻倍股"universe 内部,通过 LightGBM 学截面 ranking,能预测下一批继续上涨的票。
与 B-Line 的对比
| 维度 | B-Line | Doubles |
|---|---|---|
| Alpha 本源 | 60 日反转(输家反弹) | 90 日动量延续(赢家继续涨) |
| Universe | universe100(100 只全市场抽样) | 660 只历史翻倍股(生存者) |
| 信号 | 单因子 RET_60D |
29 因子 LightGBM binary |
| 持仓 | top-5 最低 RET_60D | top-10 by pred |
| Horizon | T+30(月度) | T+20(K=20 holding) |
| 已知风险 | 大盘 beta 压制 | 生存者偏差(660 都是已经翻倍的) |
项目双层结构(doubles vs factor_mining)
/opt/claude/doubles/
├── screening/ ← 数据采集层 (上游)
│ ├── find_doubled_stocks.py # 全市场扫描近 3 月翻倍股
│ ├── collect_valuation.py # ELTDX F10 → MySQL 日度估值
│ ├── fundamentals.csv # 660 只翻倍股快照
│ └── washout_candidates*.csv # 暴跌候选(实盘监控)
│
└── factor_mining/ ← 因子挖掘层 (下游, 核心)
├── mysql_to_qlib.py # MySQL → Qlib .bin 特征
├── factor_mining_v{1..7}.py # 7 个版本迭代
├── v5_lightgbm_oos.py # v5 LightGBM OOS 验证 (FINAL)
├── backtest_kday_compare.py # K-day holding 突破 (诊断 horizon)
├── backtest_production.py # 生产约束 (sector neutral + halt)
├── production_signal_generator.py # 实盘信号生成 (输出 weights, ST/*ST 剔除已接入)
├── backtest_production_constrained.py # P0 三项落地 (ST + ADV cap + ADV filter)
├── walk_forward_v5.py # Walk-forward 稳定性验证
├── factor_output_v{1..7}/ # 各版本输出
├── production_signals_v5/ # 实盘信号 (原版, 无 ST 剔除)
├── production_signals_v5_st/ # 实盘信号 (P0-1 落地: ST/*ST 剔除, 当前生产版)
└── factor_output_walkforward/ # WF 验证结果
关系总结:
- doubles = 研究主题(A 股翻倍股)
- screening = 数据来源(ELTDX → MySQL → 660 只候选股)
- factor_mining = 算法核心(在 660 股上学预测因子 → 输出投资信号)
- 单向数据流:screening → factor_mining → 实盘 OMS
- 反哺闭环(P5 待办):表现最好的因子写回 screening,优化选股阈值
二、策略规格(FROZEN)
| 参数 | 值 | 来源 |
|---|---|---|
| Universe | 660 只历史翻倍股 (2024-06 ~ 2026-01) | eltdx F10 全市场扫描 |
| 模型 | LightGBM binary (label_doubled, pos_rate 2.5%) |
v5 Treatment, best_round=107 |
| 特征 | 29 个(27 base + r_spread_60d + d_tradable_mv × r_spread_60d) |
v5 quantlab §七 三条建议 |
| 训练窗 | 2024-01-01 ~ 2025-04-30 (expanding) | v5 排除 2025-05 反转 regime |
| 持仓数 | top-10 by pred |
K-day backtest Pareto 最优 |
| 持仓周期 | K=20 个交易日(月度) | K-day 扫描 [1, 5, 10, 20] 突破 |
| Sector cap | soft cap=4 (max 40% per prefix group) | 6 配置对比,soft 仅损 -0.22 Sharpe |
| Halt handling | fillna(0) (停牌股占位 0% return) |
与 dropna 完全等价(验证) |
| Position cap | 15% (N=10 时基础权重 10%, 不绑定) | 默认风控 |
| 交易成本 | 0.10% 买 + 0.15% 卖(含 0.05% 印花税) | 真实 A 股成本 |
| 调仓 | 每日 T 收盘后选股, T+1 开盘执行 | 月度 sub-portfolio 滚动 |
三、使用方法
月度执行流程
-
T-1(月末最后交易日收盘后) - 拉 MySQL 日度估值(PE/PB/PS/MV)→ Qlib
.bin- 计算 28 个 base 因子 +r_spread_60dregime indicator - 构造d_tradable_mv × r_spread_60d交互项 -
T(月首交易日) - 重训模型(expanding window,所有历史 + 上月新数据) - 对 660 只股票跑 LightGBM predict → 得
pred概率 - 升序排列无意义,取 top-10 bypred(最大概率继续翻倍) - 应用 soft sector cap=4:4 个 prefix 组(SH60/SH68/SZ00/SZ30)每组最多 4 只 -
持仓期 K=20 天(sub-portfolio 滚动) - 每天 T:与过去 19 日的 top-10 sub-portfolios 同时活跃 - 共 20 个 sub-portfolios × 10 只 = 100 个 slot(重叠后实际 ~28 只) - 每 sub-portfolio 等权 1/20 = 5%,内部等权 - 当日 portfolio return = mean(20 个 sub-portfolios 的当日 mean return)
-
风控 - 单股最大权重 ≤ 15%(halt 后 redistribute) - 单 prefix 组最大 40%(防板块集中) - 单日 turnover ≤ 5%(K=20 自然约束)
实盘工程兜底(不改模型)
- 停牌处理:halt 股占位 0% return(已验证,与 dropna 等价)
- 跌停强平:止损触发但封死跌停 → T+1 集合竞价无条件强平
- 容量管理:单股仓位 ≤ 该股 20 日 ADV 的 20%
- ST/*ST 排除:选股阶段强制剔除(需接入标记数据源)
- 重训节奏:每月 expanding window retrain(walk-forward 已验证稳定)
四、绩效结论(660 翻倍股 OOS, 2025-05 ~ 2026-01, NET 成本后)
Single-train vs Walk-Forward 对比
| 指标 | Single-train (2024-04 截止) | Walk-Forward (4 窗口重训) | Δ |
|---|---|---|---|
| Alpha Sharpe | +1.94 | +2.69 | +0.75 |
| Top-10 long Sharpe | +4.03 | — | — |
| LS Sharpe | +1.68 | — | — |
| Alpha Total Return | +20.85% | +26.11% | +5.26pp |
| Max Drawdown | -7.94% | -5.75% | +2.19pp |
| 基准(等权 660 股)Sharpe | +4.60 | +4.60 | — |
⚠️ 生存者偏差警示:基准 660 等权 Sharpe +4.60 是因为这些都是已翻倍股。Alpha = Top - Bench 才是真实信号。
K-day holding 扫描(v5 N=10)
| K | Alpha Sharpe | LS Sharpe | 评注 |
|---|---|---|---|
| 1 | -1.08 | +0.92 | Daily rebalance 摧毁 alpha |
| 5 | +1.66 | +2.01 | 周 horizon 接近 label T+90 |
| 10 | +1.74 | +1.79 | 良好 |
| 20 | +2.16 | +1.96 | 最优(与 label T+90 最匹配) |
关键洞察:v5 模型在 K=1 表现差不是模型问题,是 horizon mismatch — label 是 T+90 学到的,需要月度调仓释放 alpha。
Walk-Forward 4 窗口稳定性
| Window | 训练截止 | 测试期 | Alpha Sharpe | Alpha Total |
|---|---|---|---|---|
| W1 | 2025-04-30 | May-Jun 2025 | +0.76 | +2.07% |
| W2 | 2025-06-30 | Jul-Aug 2025 | +4.11 | +16.06% |
| W3 | 2025-08-31 | Sep-Oct 2025 | +3.38 | +11.30% |
| W4 | 2025-10-31 | Nov 2025 - Jan 2026 | +2.81 | +8.37% |
Min +0.76, Max +4.11, Std 1.24。4 个窗口全部正收益,证明 v5 没有过拟合到特定训练期。
Enhanced Metrics(Calmar / 月度胜率 / 换手率 / Regime 分解)
2026-06-14 补充。脚本:
backtest_enhanced_metrics.py,输出:factor_output_enhanced/enhanced_metrics.json
| 指标 | Alpha (Top-Bench) | Top-10 Long | Bench (660 等权) |
|---|---|---|---|
| Sharpe | +1.94 | +4.03 | +3.98 |
| Calmar | +3.71 | +15.02 | — |
| 月度胜率 | 80.0% (8/10 月) | 80.0% | — |
| Total Return | +20.85% | — | — |
| Annualized Return | +29.43% | — | — |
| Max Drawdown | -7.94% | — | — |
实际换手率(K=20 blended weights):avg 4.03%/day 双边,max 100%(首日建仓),avg 28.5 只活跃股。
Regime 分解(按 r_spread_60d 中位数 -0.099): - High regime (92 days): Sharpe +2.22, Total +11.08% - Low regime (93 days): Sharpe +1.67, Total +8.80% - Δ (High-Low) = +0.55 → alpha 在 spread 高时更强(与 v5 设计假设一致,非纯 beta 暴露)
Top-10 Feature Importance(v5 Treatment, gain-based)
| Rank | Feature | Gain % | 备注 |
|---|---|---|---|
| 1 | d_pe |
18.1% | 市盈率因子 |
| 2 | d_peg |
17.1% | PEG 因子 |
| 3 | d_tradable_mv |
11.7% | 流通市值 |
| 4 | d_pb |
8.5% | 市净率 |
| 5 | d_pcf |
8.4% | 现金流市盈率 |
| 6 | d_total_mv |
6.9% | 总市值 |
| 7 | d_ps |
6.2% | 市销率 |
| 8 | r_spread_60d |
4.1% | regime indicator ← |
| 9 | f13_price_position_60d |
3.8% | 60 日价格分位 |
| 10 | x_mv_x_spread |
3.2% | 交互项 ← |
观察:估值因子(PE/PEG/PB/PCF/PS)合计占 60%+ gain,符合"翻倍股内部分化靠估值"假设。Regime 相关项(r_spread_60d + 交互项)合计 7.3% gain,证明 v5 引入这两项的真实价值。
PSI 特征漂移监控(4 窗口 × Top-10 features)
2026-06-14 补充。脚本:
psi_monitoring.py,输出:factor_output_psi/psi_monitoring.json。每月 retrain 前应跑此脚本预警漂移。
| 特征类型 | avg PSI | max PSI | 判定 |
|---|---|---|---|
| 估值因子 (d_pe/d_peg/d_pb/d_pcf/d_ps/d_mv/d_total_mv/f13_price_pos) | 0.076 | 0.444 | ✅ 整体稳定(25/32 stable, 6/32 drift, 1/32 significant) |
| Regime 因子 (r_spread_60d + x_mv_x_spread) | 7.42 | 12.52 | ⚠️ by design 漂移(regime 切换是 feature 设计目标) |
关键发现:
- W2 (Jul-Aug 2025) 估值因子最漂移:f13_price_position_60d PSI 0.44 显著漂移,但 W2 Alpha Sharpe 最高 (+4.11) — regime shift 反而创造 alpha 机会
- Regime indicator PSI 漂移大是 by design:r_spread_60d 设计上就捕捉市场状态切换,分布变化是预期内的;PSI 不适合直接判定这类特征
- 实盘监控建议:每月 retrain 前跑 PSI;任一估值因子 PSI ≥ 0.25 触发预警;regime indicator PSI 突破历史 max 12.52 视为进入训练集未见过的 regime
真实 Alpha 定位(2026-06-14 关键修正)
2026-06-14 跑真实 benchmark 对比 + 白噪测试,修正策略定位。脚本:
backtest_real_benchmark.py+backtest_falsification.py。
⚠️ Alpha Sharpe +1.94 是相对生存者偏差 bench,不是真实 alpha。
| Benchmark | Alpha Sharpe | 判定 |
|---|---|---|
| 660等权(生存者偏差) | +1.94 | ❌ 虚假基准 |
| 沪深300 | -0.11 | ❌ 跑输大盘 |
| 中证500(最公平) | -0.25 | ❌ 跑输 |
| 创业板指 | -0.44 | ❌ 跑输 |
| 国证2000(中小盘) | +0.96 | ✅ 真实 stock selection alpha |
白噪测试(100 次随机 pred):v5 Alpha vs 国证2000 p=0.0% — 框架无 bug,stock selection alpha 真实存在。
真实定位:v5 策略是 两阶段 stock picker: 1. Universe 选择:从全市场筛 660 只翻倍股(universe alpha vs 大盘) 2. Universe 内 selection:v5 LightGBM 选 top-10(stock selection alpha vs 国证2000 ≈ +0.96 Sharpe,加 ST 剔除后 +1.11 Sharpe)
A1 国证2000 overlay 结果(2026-06-15,假设证伪):在 660 ∩ 国证2000 = 271 只子集上重训 v5,Alpha −0.60 ❌。揭示 alpha 真正来源 = 660∖国证2000 的 389 只小盘翻倍股(未进指数)。详见评估报告 §八。
实盘含义:
- 不要用 v5 替代大盘配置——直接买 CSI500 在 2025-05~2026-01 期间 Sharpe +1.91
- 当前 production_signals_v5_st/daily_target_weights.h5(生产版,含 ST 剔除)是"660 universe 内的相对权重",不能直接对接大盘 OMS
- 真实可期待 alpha ≈ +1.11 Sharpe(vs 国证2000,ST 剔除后)
- 实盘 AUM 上限 3000 万元(详见评估报告 §九 P0-2 ADV 容量评估)
五、迭代历程(v1 → v7 + Walk-Forward)
| 阶段 | 关键改动 | 结论 |
|---|---|---|
| v1 | OHLCV-only 22 因子 baseline | IC ≈ 0.025(噪声水平) |
| v2 | + PB/PE/PS 估值因子(static),双 bias | TRAIN IC +0.26 但 OOS 不显著 |
| v3 | 修复双 bias(无偏动态 PB),对齐 quantlab 审计 | TRAIN IC -0.047(与审计 -0.033 吻合),bias 闭环 |
| v4 | 27 因子(d_pb 无偏 + 26 base),Filter Nan 处理 | 信号变纯,OOS IC +0.05 |
| v5 | + r_spread_60d regime indicator + TRAIN 截止 2025-04-30 |
OOS AUC 0.55, ICIR +1.09, Top-50 LS Sharpe +1.68 |
| v5_backtest | K=1 daily rebalance | Top-N alpha Sharpe -0.5 ~ +0.5(弱) |
| K-day 突破 | K=20 holding | Alpha Sharpe +2.16(v5 + K=20 + N=10) |
| v6 | scale_pos_weight + 5-fold CV + 特征过滤 | 失败:fold 1 数据不足,gap 0.45(更差) |
| v7 | label_doubled → label_top20pct(4% → 20% 正样本) | 失败:horizon mismatch 是真问题,不是 label |
| 生产约束 | soft sector cap=4 + halt handling | Alpha Sharpe +1.94(损 -0.22,可接受) |
| Walk-Forward | 4 窗口 expanding retrain | Alpha Sharpe +2.69(反超 single-train +0.75) ✅ |
六、不采用清单(当前版本)
当前 v5_production_release 不采用以下路线;其中 v6/v7 标注"待重审"——数据积累或方法改进后可在
doubles_v8_regression分支重试,并非永久关闭。
不采用:
- ⏸ v6 路线(scale_pos_weight + 5-fold CV + 特征过滤):fold 1 数据不足,gap 0.45(比 v5 还差)。待重审:可改 TimeSeriesSplit 或减 fold 数,作为 v8 候选
- ⏸ v7 label 改动(label_doubled → label_top20pct):OOS AUC 反降,alpha 全负。待重审:若 horizon mismatch 假设被推翻,可重新评估
- ❌ Strict sector neutral(4 组均分 N/4):Alpha Sharpe -1.01(v5 已学会避开 SH68,强行均分塞差票)
- ❌ K=1 daily rebalance:horizon mismatch,alpha 释放不出来
- ❌ 重写为 Alpha158 表达式接入 quantlab:会丢失 r_spread_60d 和 d_tradable_mv × r_spread_60d 交互项
- ❌ Position cap < 15%:N=10 基础权重 10%,cap=15% 不绑定,过严反而损 alpha
- ❌ Hard halt drop(dropna()):与 fillna(0) 数值完全一致,无意义改动
七、方法论沉淀
- Horizon 匹配优先于模型调优 — label T+90 必须配 K≥20 holding,K=1 的差表现不是模型问题
- 生存者偏差要识别但不必消除 — 660 翻倍股 universe 本身是生存者,Alpha = Top - Bench 才有意义
- Walk-Forward 是过拟合照妖镜 — 单 train Sharpe 1.94 不够,必须 4 窗口都正才算稳定
- Soft cap > Strict cap — 板块约束用 max_per_group(允许倾斜),不用 strict equality(强制均分)
- Production 约束要早测 — sector neutral / position cap 在 backtest 阶段就要验证,不要留到实盘
- RD-Agent 协作要分仓库 — doubles 仓库负责数据和模型,RD-Agent 仓库负责 prompt 和实验,HDF5 状态分离
八、关键文件索引
生产信号 (实盘消费)
| 文件 | 用途 |
|---|---|
production_signals_v5_st/daily_target_weights.h5 |
生产版:每日 K=20 blended 权重 [datetime, instrument, weight],含 ST 剔除 |
production_signals_v5_st/daily_selections.h5 |
生产版每日 top-10 新选股 [datetime, instrument, rank, pred] |
production_signals_v5_st/signal_metadata.json |
生产版配置 + Alpha Sharpe 校验 |
production_signals_v5/daily_target_weights.h5 |
原版(无 ST 剔除),保留做对比 |
模型 & 验证
| 文件 | 用途 |
|---|---|
factor_mining/v5_lightgbm_oos.py |
v5 LightGBM 训练 (Treatment) |
factor_mining/v5_treatment_only.py |
v5 极简版(生成 oos_pred_v5.h5) |
factor_mining/factor_output_v5/oos_pred_v5.h5 |
v5 OOS 预测(118486 rows) |
factor_mining/backtest_kday_compare.py |
K-day holding backtest |
factor_mining/backtest_production.py |
6 配置生产约束对比(soft cap / halt / poscap) |
factor_mining/backtest_real_benchmark.py |
真实 benchmark 对比(CSI300/500/创业板/国证2000) |
factor_mining/backtest_falsification.py |
白噪测试(100 次随机 pred, p-value 检验) |
factor_mining/backtest_enhanced_metrics.py |
Calmar/月度胜率/换手率/Regime 分解/Top-10 feat imp |
factor_mining/backtest_production_constrained.py |
P0 三项落地(ST + ADV cap + ADV filter, 6 配置对比) |
factor_mining/v5_gzh2000_overlay.py |
A1 国证2000 重训 overlay(假设证伪) |
factor_mining/paper_trading_tracker.py |
模拟盘跟踪(warmup / update / report 三模式) |
factor_mining/factor_output_enhanced/enhanced_metrics.json |
5 个增强指标 + 全 feature importance |
factor_mining/psi_monitoring.py |
PSI 特征漂移监控(4 窗口 × Top-10) |
factor_mining/factor_output_psi/psi_monitoring.json |
PSI 结果 + 分组判定 |
factor_mining/walk_forward_v5.py |
4 窗口 walk-forward 训练 |
factor_mining/factor_output_walkforward/walkforward_summary.json |
WF 稳定性结果 |
数据管道
| 文件 | 用途 |
|---|---|
screening/find_doubled_stocks.py |
ELTDX 全市场扫描翻倍股 |
screening/collect_valuation.py |
ELTDX F10 → MySQL 日度估值 |
factor_mining/mysql_to_qlib.py |
MySQL → Qlib .bin |
screening/fundamentals.csv |
660 翻倍股快照 |
MySQL mystocks.stock_valuation_daily |
779,333 行日度估值(660 股 × ~1200 天) |
文档
| 文件 | 用途 |
|---|---|
/opt/claude/doubles/PROJECT_SUMMARY.md |
项目总结(数据 + RD-Agent 集成) |
/opt/claude/doubles/HANDOFF.md |
Handoff 状态(资产位置 + MySQL schema) |
/opt/claude/doubles/factor_mining/v5_lightgbm_oos_report.md |
v5 详细实验报告 |
/opt/claude/doubles/factor_mining/v5_factor_evaluation.md |
v5 因子 IC 评估 |
/opt/claude/doubles/factor_mining/v3_vs_v2_comparison.md |
bias 修复闭环报告 |
九、上线路径
- ✅ 数据管道:ELTDX → MySQL → Qlib 已稳定运行
- ✅ 模型训练:v5 LightGBM Treatment 已固化(best_round=107)
- ✅ 生产约束:soft sector cap=4 + halt handling 已验证
- ✅ Walk-Forward:4 窗口稳定性已验证(Sharpe +2.69)
- ✅ 信号生成:
production_signals_v5_st/daily_target_weights.h5(生产版, ST 剔除已接入),schema 已定义,可直接对接 OMS - ⏳ 实盘工程三项(P0):
- ✅ P0-1 ST/*ST 剔除:已接入
production_signal_generator.py,Alpha +1.94 → +2.13 - ⚠️ P0-2 ADV 容量约束:评估完成,AUM 上限 3000 万(1 亿时 alpha 翻负 -1.77) - ⏳ P0-3 跌停强平:完整 spec 已交付(评估报告 §十),待 OMS 团队实施(~3 周) - ✅ 模拟盘框架:
paper_trading_tracker.py三模式(warmup/update/report),warmup 通过(Alpha +1.07 ≈ 预期 +1.11) - ⏳ Forward paper trading:需先建 v5 每日增量预测 pipeline(新会话优先项)
- ⏳ 每月重训:expanding window,月初执行
生产上线 SOP:见 Doubles 生产上线 SOP.md(数据流 / OMS 对接 / 监控指标 / 上线 Checklist / 回滚预案)
十、与 RD-Agent 的协作
| 维度 | Doubles 仓库 | RD-Agent 仓库 |
|---|---|---|
| 职责 | 数据 + 模型 + 信号 | LLM 实验循环 + 因子生成 |
| 数据 | MySQL/Qlib .bin (权威源) |
HDF5 factor_implementation_source_data |
| 输出 | production_signals_v5/ | RD-Agent_workspace/ |
| Prompt | 不涉及 | rdagent/scenarios/qlib/experiment/factor_data_template/ |
| 状态文档 | doubles/HANDOFF.md |
RD-Agent/EXPERIMENT_NOTES.md |
协作流程:
1. Doubles 提供 PB/PE/PS 因子 → RD-Agent LLM prompt 注入
2. RD-Agent LLM 生成新因子 → 跑 Qlib backtest → 提取 IC
3. 若 IC > 0.05,因子反哺到 factor_output_v3/ 进 doubles pipeline
4. Doubles 验证 → 若通过,进 factor_mining_v5.py 加入特征集
版本:v5_production_st(基于 v5 Treatment + soft cap=4 + walk-forward + ST/ST 剔除,2026-06-15)
配套文档*:
- Doubles 生产上线 SOP.md — 生产上线流程 / OMS 对接 / 监控 / 回滚
- 策略评估报告:Doubles.md — 评估 + 项目方核实 + Alpha 真实性 + A1/P0 实证(§七-§十)
维护规则:
- ✅ 允许:重训机制(expanding window)、数据源扩展、风控开关、执行逻辑
- ❌ 禁止:改 label、改 sector neutral 为 strict、改 horizon、删 r_spread_60d 交互项
- 如要重审:fork 新分支(如 doubles_v8_regression),不污染 main
十一、A1 重定位计划(待办)
2026-06-14 真实 benchmark 揭示:v5 Alpha Sharpe +1.94 是相对生存者偏差 bench,真实 stock selection alpha ≈ +0.96(vs 国证2000)。A1 目标:在国证2000 universe 上重训 v5,验证 stock selection alpha 能否脱离 660 翻倍股池直接复现。
数据源(NAS MySQL mystocks 库,3 张表)
| 表名 | 用途 | 关键字段 | 行数 |
|---|---|---|---|
cnindex_399303_cons |
国证2000 成分股+权重 | constitute_date, stock_code, weight_pct, market_cap_yi, industry |
4000 (2 期快照) |
cnindex_399303_daily |
国证2000 指数日线 | trade_date, open/close/high/low, pct_change, volume, turnover |
3992 |
cnindex_industry_202606 |
国证行业分类(4 级) | stock_code, level1_code/name, level2/3/4... |
6263 |
成分股快照:2026-05-29(完整 2000 只)+ 2026-06-12(仅 top10 有权重)。
执行清单(5 步)
cd /opt/claude/doubles/factor_mining
# Step 1: 从 MySQL 拉国证2000成分股
# SELECT stock_code, weight_pct, market_cap_yi, industry
# FROM cnindex_399303_cons
# WHERE constitute_date = '2026-05-29' AND weight_pct IS NOT NULL
# ORDER BY weight_pct DESC;
# → 拿 2000 只 stock_code → 转 qlib 格式 (e.g. '000001' → 'SZ000001')
# Step 2: 过滤 v5 factors 到国证2000 universe (2000 只)
# 推荐选项 A: 全部 2000 只 (脱离 660 universe, 真验证 stock selection alpha)
# Step 3: 重新训练 v5 LightGBM
# - 复用 29 特征 (27 base + r_spread_60d + x_mv_x_spread)
# - 训练窗口: 2024-01-01 ~ 2025-04-30 (与原 v5 一致)
# - label: label_doubled (复用, 但查 pos_rate, 可能 < 2.5%, 调 scale_pos_weight)
# Step 4: 跑 overlay backtest
# - 持仓: top-10 from 国证2000 (K=20 + soft cap, 可改 industry 一级 cap)
# - benchmark: cnindex_399303_daily 真指数 (含真实权重)
# - alpha = Top - Bench
# Step 5: 对比
# - v5 原版 (660 universe) Alpha vs 国证2000 = +0.96
# - v5 国证2000版 (2000 universe) Alpha vs 国证2000 = ?
# - 期待: > 0.5 → stock selection alpha 可脱离 660 直接复现
3 个待决策点
| 决策 | 选项 A | 选项 B | 推荐 |
|---|---|---|---|
| Universe | 全 2000 只 | 660 ∩ 国证2000 (~200 只) | A(真脱离 660) |
| Benchmark | 等权 2000 | cnindex_399303_daily 真指数 | B(含真实权重,更公允) |
| Sector cap | 复用 SH60/SH68/SZ00/SZ30 prefix | 改用 industry 一级 (11 类) cap | B(更细,max_per_group 调到 ~3) |
预期工作量
| 阶段 | 时间 |
|---|---|
| Step 1 拉 MySQL + 转 qlib 格式 | 30 min |
| Step 2 过滤 + 数据完整性检查 | 15 min |
| Step 3 训练(含 pos_rate 检查 + scale_pos_weight 调参) | 30 min |
| Step 4 backtest | 30 min |
| Step 5 对比 + 报告 | 30 min |
| 调试 buffer | 1 h |
| 合计 | ~3 h |
关键风险
- ⚠️ 静态成分股 look-ahead bias — 用 2026-05-29 快照 backtest 2025-05~2026-01,存在轻微信号 look-ahead。报告时必须标注。完整解需要历史成分股,但 MySQL 仅 2 期快照。
- ⚠️ pos_rate 可能极低(国证2000 内非翻倍股池,"未来 90 天翻倍"概率可能 < 1%)— 可能需要
is_unbalance=True+ 调scale_pos_weight,或改 label 定义(如 label_top20pct) - ⚠️ 因子可能在国证2000 universe 内失效 — d_pe 等估值因子在大盘可能更有效,中小盘需要验证
- ⚠️ 样本量 — 660 universe 之前 v5 best_round=107,国证2000 (2000 只) 数据量增加,可能需要重调
num_leaves/min_child_samples
判定标准
| Alpha Sharpe (vs 国证2000) | 判定 | 行动 |
|---|---|---|
| ≥ 0.8 | ✅ alpha 完全脱离 660 universe 复现 | 进实盘准备 |
| 0.5 ~ 0.8 | — alpha 部分复现,仍依赖 universe selection | 进模拟盘观察 |
| 0.0 ~ 0.5 | ⚠️ alpha 主要靠 universe selection | 重新设计或放弃 |
| < 0.0 | ❌ stock selection alpha 失效 | 回退到原 v5 + 接受 +0.96 alpha |
输出文件(规划)
| 文件 | 用途 |
|---|---|
v5_gzh2000_train.py |
国证2000 universe 上的 v5 训练脚本 |
factor_output_v5_gzh2000/factors_v5_gzh2000.h5 |
国证2000 universe 的 factors |
factor_output_v5_gzh2000/oos_pred_v5_gzh2000.h5 |
OOS 预测 |
backtest_gzh2000_overlay.py |
overlay backtest 脚本 |
factor_output_gzh2000_overlay/overlay_alpha.json |
对比结果(原 v5 vs 国证2000 版) |
执行结果(2026-06-15)
⚠️ 方法学限制:v5 factors 只覆盖 660 翻倍股,无法在完整 2000 只国证2000 上重训。实际测试 = 271 只(660 ∩ 国证2000)子集,不是完整 A1。
结果数据:
| Config | Universe | n_inst | TRAIN AUC | OOS AUC | OOS IC | Alpha vs 399303真指数 |
|---|---|---|---|---|---|---|
| v5 原版 | 660 | 660 | 0.91 | 0.74 | +0.044 | +0.96 ✅ |
| v5 GZH2000 子集 | 271 | 271 | 0.91 | 0.56 | −0.002 | −0.60 ❌ |
关键发现 — alpha 真正来源:
v5 的 +0.96 alpha(vs 国证2000)不来自国证2000 内部选股,而来自 389 只 660∖国证2000 的小盘翻倍股(规模太小或刚翻倍未被指数纳入)。反向推算 389 子集隐含 alpha ≈ +2.0+。
660 universe = 271 大盘翻倍股(已进国证2000) → 内部 ranking alpha ≈ -0.60
+ 389 小盘翻倍股(未进国证2000) → 隐含 alpha ≈ +2.0+ (vs 国证2000)
= +0.96 blended alpha
实盘含义:
- ❌ 不能把 v5 移植到国证2000 — alpha 源头在 index 之外
- ✅ 保留 660 universe — alpha 主要来自 universe selection 步骤(screening 层筛小盘翻倍股)+ 389 子集的 stock selection
- ⚠️ 实盘容量警告 — 389 小盘股流动性差,必须接入 ADV 容量约束(P0 工程项)
- ⚠️ 生存者偏差仍在 — 660 是历史已翻倍股池,未来类似股票可能携带不同特征。每月 expanding retrain + PSI 监控是必需的
A1 任务关闭 — 假设证伪,stock selection alpha 不能脱离 660 universe 直接复现。下一步重点转向实盘工程三项(ST/ADV/跌停)。