- 当前状态: baostock获取500只股票代码,含已退市股票(600001邯郸钢铁、000003PT金田A等)
- 检查:
_get_major_stocks()生成固定代码范围,不依赖当前成分股列表 - 结论: 无幸存者偏差
- 当前状态: 因子IC用point-in-time计算,每个时间点只用之前数据
- 检查: 走查验证(train 2021-2023, test 2024-2026)通过
- 结论: 无数据挖掘偏差
- 当前状态: 2021-2026(5.4年),覆盖牛熊周期
- 检查: 包含2021-2023熊市和2024-2026牛市
- 结论: 样本足够
- 当前状态: 参数扫描测试了6种ICIR配置 + 4种IC配置 + 3种波动率目标
- 检查: ICIR+MVO在多个lookback(63/126/252)和min_icir(0/0.05/0.1)下都为正Sharpe
- 结论: 无参数孤岛效应
- 当前状态: 因子有经济逻辑(size=小盘溢价, quality=低换手波动, idio_vol=特质波动异象, vol_of_vol=二阶风险)
- 检查: 因子逻辑来自学术文献(Ang et al. 2006, Fama-French),先于数据发现
- 结论: 无讲故事偏差
- 当前状态: 使用winsorize(1%-99%)+ zscore标准化
- 检查:
factors/processing.py横截面缩尾+标准化 - 结论: 已处理
- 当前状态: 月度调仓,换手率约束30%
- 检查: Walk-forward测试期因子IC仍为正(idio_vol: 0.2078, size: 0.1571, quality: 0.1851)
- 结论: 信号未衰减
- 当前状态: Walk-forward验证train/test期因子IC变化
- 检查: 测试期ICIR仍为正,无结构性断裂
- 结论: 因子在不同市场环境下都有效
- 当前状态: 佣金0.03%双边 + 印花税0.1%仅卖出 + 滑点0.05%
- 检查:
backtest/cost_model.py完整A股成本模型 - 结论: 成本模型合理
- 当前状态: 假设任何数量都能成交
- 检查: 未考虑股票流动性
- 风险: 小盘股可能无法按理想价格成交(但max_weight=8%限制了单票暴露)
- 当前状态: 使用收盘价成交,次日shift(-1)执行
- 检查: 月频调仓天然规避日内价格假设
- 结论: 合理
- 当前状态: 因子使用历史价格,fwd_ret = close.pct_change().shift(-1)
- 检查: IC计算使用shift后的前向收益,无未来信息
- 结论: 无偷价
- 当前状态: Walk-forward验证(train 2021-2023, test 2024-2026)
- 检查: 测试集未用于模型选择
- 结论: 有效的样本外测试
- 当前状态: 参数扫描 + Walk-forward + IC稳定性分析
- 检查: 测试了不同lookback、min_icir、optimizer、ML vs ICIR
- 结论: 验证流程完整
- 当前状态: 回测假设完美执行(但有滑点建模)
- 检查: 实盘需考虑网络中断(已有CircuitBreaker+Kill Switch)
- 结论: 已有风控熔断机制
- 当前状态: 因子有经济逻辑,代码已审查
- 检查: 修复了wide-format因子计算bug、代码补零bug
- 结论: 模型风险可控
| 参数 | 值 |
|---|---|
| 股票池 | 500只(97只有效) |
| 因子数 | 22个(10技术+12衍生) |
| Alpha方法 | ICIR加权(min_icir=0.1) |
| 优化器 | Mean-Variance (cvxpy) |
| 调仓频率 | 月度 |
| 行业约束 | max_sector_exposure=25% |
| 单票上限 | 8% |
| 换手约束 | 30% |
| 初始资金 | 100万 |
| 因子 | ICIR | 含义 |
|---|---|---|
| idio_vol | +0.2445 | 特质波动率(低波溢价) |
| size | +0.2257 | 市值(小盘溢价) |
| vol_of_vol | +0.2044 | 波动率的波动率 |
| quality | +0.2000 | 换手率波动(低换手=高质量) |
| pb_spread | +0.1450 | PB偏离度 |
| reversal | +0.1314 | 5日反转 |
| earnings_yield | +0.1190 | 盈利收益率 |
| volatility_20d | -0.2763 | 20日波动率(负IC=低波更好) |
| amplitude_20d | -0.2737 | 20日振幅(负IC=低振幅更好) |
| 指标 | 值 |
|---|---|
| Sharpe Ratio | 0.64 |
| 年化收益 | 14.43% |
| 年化波动 | 17.93% |
| 最大回撤 | -21.55% |
| 超额收益(vs CSI300) | +109.02% |
| 信息比率 | 0.63 |
| 指标 | 值 |
|---|---|
| 测试期Sharpe | 0.26 |
| 测试期年化收益 | 8.07% |
| 测试期最大回撤 | -20.57% |
| 测试期超额 | -21.85%(结构性:小盘价值在大盘牛市跑输) |
- 因子有效: idio_vol/size/quality/vol_of_vol四个因子ICIR>0.2,在train和test期都稳定
- 无过拟合: Walk-forward测试期Sharpe仍为正(0.26),因子IC无结构性断裂
- 无未来函数: Point-in-time IC加权,每个时间点只用历史数据
- ML无效: LightGBM/XGBoost standalone Sharpe为负,ensemble不如纯ICIR
- 行业约束生效: 97只股票分布在10+个CSRC行业,max_sector_exposure=25%
- 交易成本合理: 佣金+印花税+滑点完整建模
- 因子计算格式错误: 从stacked改为wide-format,Numba从不可用变为6个JIT内核
- CSV缓存加载失败:
_load_cache只试parquet,加了CSV回退 - ICIR权重符号错误:
abs(v) >= min_icir保留负ICIR符号 - ML信号未来函数: 改为walk-forward训练(train[:i]预测data[i])
- Regime时序无效: 从后处理信号改为前置调整因子权重
- 股票代码补零缺失:
_from_bs_code返回1而非000001,导致行业分类全部失效 - 行业数据静默失败: 5种sector约束静默失效模式已排查