深度解析 US Equities Panel 案例研究:用 3,200 只美股验证横截面信号规模化的端到端 ML 交易工作流
【免费下载链接】machine-learning-for-tradingCode for Machine Learning for Trading, 3rd edition — from data sourcing to live execution.项目地址: https://gitcode.com/GitHub_Trending/ma/machine-learning-for-trading
本案例研究是《Machine Learning for Trading》(3rd edition) 配套代码仓库中最宽的横截面股票工作流:以 NASDAQ Data Link 提供的约 3,200 只美股 1990–2018-Q1 日频 OHLCV 数据为宇宙,以"主动管理基本定律"(单只股票边际很小,但横截面广度可以补偿)为检验命题,用 16 折 walk-forward、多周期标签、多家族模型、配对 Bootstrap 置信区间与显式 holdout 窗口,回答一个核心问题:经过如此多测试仍存活的毛信号,能否在考虑选择偏差与交易摩擦后转成一个可交易的策略。读完本文,你将掌握该案例研究从可行性分析到策略评估的 21 个流水线阶段、setup.yaml的完整配置语义、运行方式,以及最终验证与 holdout 结论的事实依据。
案例定位:全书最宽的横截面与最长的流水线
在九个贯穿第 6–20 章的案例研究中,US Equities Panel 有两个"之最":
- 宇宙最宽:约 3,200 只美股(NYSE/NASDAQ/AMEX),覆盖 1990 年至 2018-Q1;
- 折数最多:16 折 walk-forward(10 年训练、1 年验证),是全仓库折叠数最多的案例研究。
它的主标签是fwd_ret_1d(次日收益),另有fwd_ret_5d与fwd_ret_21d两个变体。特征面板混合了动量、均值回归、波动率、流动性、价值代理以及 walk-forward 时序模型输出。策略本身刻意保持朴素:日频多空 top-K 横截面排序器,美元中性构造,叠加依赖时代的有形交易成本(十进制化前每腿 15–30 bps,之后 5–15 bps)。
该案例研究的运行框架是主动管理基本定律(Fundamental Law of Active Management):单票边际很小,但横截面广度应当补偿。案例研究的职责就是把这个论断放到实测信号质量、配对 Bootstrap 置信区间和显式 holdout 窗口上去检验——不是背书,而是检验。
At a Glance
| 属性 | 值 |
|---|---|
| 资产类别 | 广泛美股(NYSE/NASDAQ/AMEX) |
| 频率 | 日频 |
| 宇宙 | 约 3,200 只股票(价格 > $5、ADV > $1M,点及时刻) |
| 历史区间 | 1990 – 2018-Q1 |
| 主标签 | fwd_ret_1d |
| CV 折数 | 16(10 年训练,1 年验证) |
| 成本模型 | 有形成本(每腿 5–30 bps,时代相关 + 借券) |
上述概览、流水线表与关键结果均出自 案例研究 README,配置细节与结论数据以 config/setup.yaml 及对应 notebook 源码为准。
数据宇宙:点及时刻过滤与成本时代
宇宙过滤的三个阈值声明在 01_feasibility_analysis.py 的参数单元格中:
MIN_PRICE = 5.0 # 价格下限 $5 MIN_ADV_USD = 1_000_000 # 日均成交额下限 $1M ADV_WINDOW = 21 # 成交额平均窗口:21 个交易日要点是"点及时刻"(point-in-time):某个决策日期上策略允许持有的股票,只能用该日期之前存在的信息判定,因此过滤不会引入前视偏差。该 notebook 只做可行性检查——不拟合模型、不做预测,也什么都不写,证据全部留在 notebook 内部。
成本方面,setup.yaml将"一笔交易花多少钱"声明为带(band)而非点(point):每次往返按交易金额的一定比例计费,取带的中点并翻倍(两腿)。配对的第二种计费方式——每股固定美分数——作为对照,但由于宇宙价格分布极宽($5 到数百美元)且历史 bar 价格经过拆股、分红调整,每笔费用作用于调整后价格并不等于当年实际支付的费用,因此在 19_costs.py 中每份费用仅作探索性对照,基点(bps)体制才是本案例的正式成本模型。
评估协议:16 折 walk-forward 与 2016–2018 holdout
config/cv_config.json 定义了交叉验证协议:
{ "n_splits": 16, "train_size": "10Y", "test_size": "1Y", "embargo_td": "P1D", "label_horizon": "P1D", "timestamp_col": "timestamp", "calendar_id": "NYSE", "test_start": "2016-01-01", "test_end": "2018-03-31" }setup.yaml的evaluation段同步声明:n_splits: 16、train_size: 10Y、val_size: 1Y、holdout 区间 2016-01-01 至 2018-03-31、日历 NYSE、年化周期 252。这个 holdout 是设计阶段完全不触碰的一段历史:当策略最终在那里被评估时,结果不是对已调参数据的排练。
标签侧(labels段)规定主标签fwd_ret_1d(缓冲 1 个交易日),变体fwd_ret_5d/fwd_ret_21d(缓冲 5/21 个交易日)。每个标签还有一个向量化回测的"抽稀步长"(rebalance_step):1/5/21,对应持有期不重叠。
流水线全景:21 个阶段、21 个 notebook
下表完整继承自案例 README,并给出各阶段在本书中的章节映射与实际产物(路径均以仓库根为起点):
| 阶段 | Notebook | 章节 | 职责 | 写出 |
|---|---|---|---|---|
| 可行性 | 01_feasibility_analysis | Ch6 | 每个决策日期的宇宙广度、成本时代、move-to-cost 尺度、walk-forward 折叠 | 无——证据留在 notebook 内 |
| 标签 | 02_labels | Ch7 | 1 日、5 日、21 日前向收益 | labels/fwd_ret_{1d,5d,21d}.parquet,各带.digest.json边车 |
| 特征 | 03_financial_features | Ch8 | 62 个横截面因子:动量、波动率、流动性、价值 | features/financial.parquet |
| 时序特征 | 04_model_based_features | Ch9 | Walk-forward Wasserstein regime 距离、FFD、GARCH 特征 | features/model_based.parquet |
| 评估 | 05_evaluation | Ch7–9 | 全面板特征-标签 IC 诊断 | evaluation/triage_ledger.parquet、evaluation/ic_timeseries.parquet |
| 线性 | 06_linear | Ch11 | 全特征矩阵上的 Ridge、LASSO、ElasticNet | 训练与预测集入run_log/registry.db;系数在run_log/training/{hash}/、分数在run_log/predictions/{hash}/ |
| GBM | 07_gbm | Ch12 | LightGBM 叶子轮廓 × 损失函数网格 | 训练与预测集;booster、learning_curves.parquet、fold_metrics.parquet在run_log/training/{hash}/ |
| Tabular DL | 08_tabular_dl | Ch12 | TabM 注意力式集成 | 训练与预测集;checkpoint 在run_log/training/tabular_dl/ |
| NLinear | 09_dl_nlinear | Ch13 | 末值归一化的最小时序基线 | 训练与预测集;checkpoint 在run_log/training/deep_learning/ |
| LSTM | 10_dl_lstm | Ch13 | 日收益窗口上的顺序记忆 | 同上 |
| TSMixer | 11_dl_tsmixer | Ch13 | 60 日回看上的时间混合与特征混合 | 同上 |
| 周频 DL | 12_dl_weekly | Ch13 | 周频节奏 LSTM/NLinear 对比 | 同上 |
| 潜在因子 | 13_latent_factors | Ch14 | PCA + IPCA 索引 notebook | 无——只读注册表 |
| PCA | 13a_pca | Ch14 | 收益协方差静态因子提取 | 训练与预测集 |
| IPCA | 13b_ipca | Ch14 | 特征条件载荷的器械化 PCA | 训练与预测集 |
| 因果 DML | 14_causal_dml | Ch15 | 12-1 动量对日收益的因果效应 | 注册表causal_runs一行 |
| 模型分析 | 15_model_analysis | -- | 跨模型 IC 对比与折叠稳定性诊断 | 无——只读注册表 |
| 回测 | 16_backtest | Ch16 | 日频多空 top-K 策略仿真 | 每个预测集与入场方案一个回测;daily_returns.parquet、weights.parquet、trades.parquet、fills.parquet、equity.parquet、portfolio_state.parquet、spec.json在run_log/backtest/{hash}/ |
| 组合管理 | 17_portfolio_management | Ch17 | 最高 IC GBM 信号上的配置扫描 | 每种配置方法一个回测,同 artifact 布局 |
| 风险 | 18_risk_management | Ch19 | 仓位级与组合级风险叠加 | 每个叠加变体一个回测,同布局 |
| 成本 | 19_costs | Ch18 | 最优配置组合上的成本网格扫描 | 每个成本水平一个回测,同布局 |
| 策略分析 | 20_strategy_analysis | Ch20 | 端到端策略评估:信号、谱系、holdout、归因 | results/strategy_assessment.json、20_strategy_synthesis/output/us_equities_panel/us_equities_panel_tearsheet.html |
注:README 的 Pipeline 表中章节号与文件名存在一处错位——实际文件系统中 18_risk_management.py 承载 Ch19 的风险叠加内容,19_costs.py 承载 Ch18 的成本扫描内容(
setup.yaml注释也明确写着"read by Ch18 19_costs.py")。运行请以实际文件名(18_risk_management、19_costs)为准。
特征工程:62 个横截面因子与模型基特征
03_financial_features.py 是全书最宽横截面上的特征工程:它的任务是让一个特征在数千只股票之间排序,而不是对单只股票做择时。源码中可以看到其导入的因子族(来自ml4t.engineer.features):momentum 族的adx/cci/macd/rsi/stochastic、trend 族的ema/kama/sma、volatility 族的natr等,最终汇总为 62 个横截面因子并写入features/financial.parquet。
工程细节值得注意:
- 顺序敏感:按 per-symbol 窗口、资格过滤、横截面排名依次计算,使每一步都作用于赋予它意义的那个 frame;
- Winsorize 时机:对特征所处的横截面做缩尾,而不是对一个策略尚未经历过的样本做缩尾,避免泄漏;
- 评估封印:特征评估在标签终点处封口,holdout 在此处不参与评分;
- 多重检验与自相关校正分离:把 Benjamini-Hochberg FDR(
benjamini_hochberg_fdr)与 HAC 统计(compute_ic_hac_stats)分开处理,以严格解读主动管理基本定律的两个输入。
04_model_based_features 写第二份矩阵(features/model_based.parquet),与金融因子矩阵并列,由utils/modeling.py的load_modeling_dataset在模型阶段加载时拼接。其核心组件在setup.yaml的model_based段逐项声明:
- regime:
n_clusters: 2(平静月与下跌月的二态切分,呼应动量崩溃文献)、window: 21、overlap: 5、burnin: 756(约 3 年)、refit_every: 63(每季度重估质心); - garch:
burnin: 504(约 2 年,低于此 ML 三参数估计的标准误过大致使持续性项不可靠)、refit_every: 63,规格为常数均值 + GARCH(1,1) + Normal 创新(p:1, o:0, q:1, dist: Normal)。这里刻意不拟合杠杆项(o: 0),因为宽横截面的单票在两年估计窗口内的大阴线太少,无法将 gamma 与 alpha 分开。
模型家族:从线性基线到深度学习与因果
训练配置按标签组织在 config/training/fwd_ret_5d.yaml 中(fwd_ret_1d.yaml、fwd_ret_21d.yaml同构),每条配置引用 case_studies/config 下的模型预设:
- 线性族:
ols+ridge_a0.001到ridge_a10000000.0的 11 档 alpha 网格,加上lasso_a0.01/0.1与enet_a0.01/0.1; - GBM 族:
default_{mse,mae,huber}+leaves_{7,15,31,63}_{mse,mae,huber}的容量 × 损失函数交叉; - 深度时序:
nlinear、lstm_h64、tsmixer、nbeats_weekly; - Tabular DL:
tabm_s/m/l;潜在因子:pca、ipca;因果:dml。
以最终胜出的 leaves_31_huber.yaml 为例,其预设揭示了容量控制的完整手段:
checkpoint_interval: 50 huber_alpha_scale: 0.5 max_iterations: 500 model_class: lightgbm.Booster params: bagging_fraction: 0.8 bagging_freq: 1 feature_fraction: 0.7 lambda_l1: 0.5 lambda_l2: 5.0 learning_rate: 0.05 min_child_samples: 50 num_leaves: 31 objective: huber seed: 4207_gbm.py 明确解释了三个调节旋钮的语义:容量由num_leaves决定(7 片叶子只能表达少数条件,63 片可以切出足以描述训练窗口的分区);损失函数决定"错在哪"——横截面股票收益是厚尾的,平方误差会给少数极端行情数百倍权重,而 rank IC 恰好对平方误差追逐的量值不敏感,因此mse/mae/huber的对比就是"尾部能在多大程度上主导拟合"的对比;何时停由树的数量控制,且每个配置沿训练过程取 10 个 checkpoint 分别计分——checkpoint 是配置的一部分,把每个配置最佳迭代当"一个候选"来报,等于把十个数的最大值当成一个数。
setup.yaml的modeling段还给出本案例特有的工程决策:gbm.max_bin: 255(LightGBM 的 CPU 默认;此前从 GPU 迁移时误带了 63 的 GPU 默认值,导致 CPU 拟合把设计矩阵量化到四分之一的桶数);latent_factors下调了 SDF 训练轮数(n_epochs_unc: 128、n_epochs_moment: 32、n_epochs_cond: 512等),使大 N 横截面上的训练时间保持在隔夜预算内。
从排序到组合:回测、配置与风险
16_backtest.py 是全流程中第一次"以钱计"的阶段:每个调仓日按模型预测排序,做多 top-k、做空 bottom-k,等权建仓。它坚持两点:
- 等权是正确的基线而非弱基线——聪明的配置器可以粉饰或埋葬一个排序,等权加入的假设最少,是任何配置器最难意外击败的对手;
- 整个模型群体全部回测,而非按 IC 先筛短名单——排序准确性与策略表现是两个问题,一个模型可能排序很好但换手率吞噬全部收益。
setup.yaml的backtest段定义了从信号到最终策略的递进选取:
top_n_predictions:signal: 0(全部预测)、allocation: 10(按等权基线 Sharpe 取前 10)、cost_sensitivity: 1、risk_overlay: 1(每标签取 1);top_k_grid:三个标签均为[20, 50](更大的宇宙需要更宽的 top-k 网格);allocators:equal_weight、score_weighted、inverse_vol、risk_parity、mvo_ledoit_wolf(显式lookback: 126覆盖 6 个月,避免 top_k=50 时 N/K < 2.5 导致 Ledoit-Wolf 收缩退化为恒等目标)、hrp、conformal_weighted;刻意不加max_weight上限(接近 top_k 时封顶会迫使等权,毁掉对比);cost_grid_bps: [0, 1, 2, 3, 5, 7, 10, 15, 20, 30, 50],配套每股半价差网格[0.0, 0.005, 0.01, 0.025, 0.05, 0.10];risk_controls:15 个仓位级叠加——stop_loss_{3,5,10,15}pct、trailing_{1,2,3,5,10,15,20}pct、time_exit_{10,20,40}。
17_portfolio_management.py 保持名称不变、只改资金分配:score_weighted信任预测幅值,conformal_weighted按预测区间宽度倒数加权(宽度取当日横截面第一百分位下限,避免单一过度自信的名字占满整腿),inverse_vol/risk_parity从各自波动率出发,mvo_ledoit_wolf/hrp则读取协方差——只有它们能识别"总是一起动的两只股票是一个下注押了两次"。注意它先按等权 Sharpe 取短名单再做配置对比,这是真正的选取决策:配置器能拯救被等权埋没的模型,是这种设计看不到的。
18_risk_management.py 在组合之上叠加风险控制,19_costs.py 则是敏感性分析而非又一轮选取:先固定每标签一个配置(此前三阶段产生的最高验证 Sharpe 者),再对该固定策略施以每个声明的成本值,且成本扫描不允许替换已选配置——会重排名次的扫描是在用成本假设做选取,而不是在测量策略。
信号质量:IC 结果与跨家族低相关
setup.yaml的kill_conditions段先给出门槛(IC 下限 0.01、edge-to-cost 下限 1.2×、微市值集中度上限 0.5、借券后净 Sharpe 下限 0.3)。实测结果(见案例 README):
- 信号方向:
leaves_31_huber(5 日变体标签)取得最高的跨阶段验证 Sharpe。在fwd_ret_1d网格上,日池化 IC 为0.0357,HAC 调整 95% CI[0.0293, 0.0421],覆盖 4,018 个日横截面,t_HAC = 10.96,显著远离零; - IC 随周期单调:GBM 的 rank-1 IC 沿 1d→5d→21d 为 0.032→0.043→0.058,线性族为 0.016→0.022→0.029,且每个 CI 都不含零;
- 跨家族低相关:树模型与线性家族信号两两相关低,因此跨家族集成不会是在"合并同一个共享信号"。
策略阶段表现:Bootstrap CI、DSR 与 PBO
- 该谱系的
risk_overlay载体(score_weightedtop_k=20 +time_exit_40)验证 Sharpe 2.028,配对 Bootstrap 95% CI[1.464, 2.549](PSR p ≈ 2e-15,分类excludes_zero_strong); - 相对同期等权美股宇宙高出 1.11 [0.48, 1.76](p ≈ 0,
excludes_zero_strong); - FF5+MOM HAC 回归把验证边际记为alpha 驱动:年化 alpha ≈ 0.76、t_HAC ≈ 7.7、残差 Sharpe ≈ 2.04、R² ≈ 0.01;
- 选取偏差度量来自
cohort_metrics:家族队列(risk_overlay/fwd_ret_5d/gbm,K_variants = 20,K_eff_MP ≈ 2.0,K_eff_ER ≈ 2.5)记录DSR_ER 0.106(p ≈ 0)、PBO 0.0(12,870 种 CSCV 组合 × 16 折);在更宽的标签队列(label/fwd_ret_5d,K_variants = 314)上同一领导者 DSR_ER 0.065(p ≈ 7e-13,K_eff_ER ≈ 12.2)——领导者的边际在小的叠加队列修正与跨阶段跨家族修正下都存活。
Holdout 闭合:验证边际没有穿越时代
- 2016-Q1 至 2018-Q1 holdout 上,该谱系 Sharpe 为−0.492;相对验证的指数配对差为−2.520 [−3.804, −1.117](p ≈ 5e-4),CI 在负侧排除零,恶化在统计上已被认定;
- 同期等权参考宇宙 Sharpe 高达 1.71(远高于其验证期 0.92,反映该时期市值加权牛市);相对该抬高的基准,策略减基准在 holdout 上为−2.363 [−4.591, −0.213](p ≈ 0.03);
- 总体结论:在所选调仓节奏下,验证边际没有跨越 holdout 时代。这正是显式 holdout 的价值——预测性验证证据与单次 holdout 评估被清晰区分。
摩擦底线:成本曲线的陡峭程度
成本敏感性扫描给出中等陡峭的包络(数据见案例 README):
- 跨阶段 rank-1 预测谱系内,零成本毛 Sharpe 2.503(5 日标签 / 日计值策略下的毛收益天花板);
- 10 bps(十进制化后成本区间中点)时 Sharpe2.117;
- edge-to-cost 比率稳超 1.2× 淘汰条件(
evidence_passes)。
Ch20 全局门全部落定:验证 Sharpe 下限(1.46)高于零,holdout 策略对等权基准的 CI 在负侧排除零。成本曲线的陡峭度与日频调仓节奏,使该策略处于"执行质量是约束性运营瓶颈"的区间。
运行方式
从仓库根目录按顺序运行(每个.py是 jupytext 百分号格式的 notebook 脚本,.ipynb 与 .py 成对存在):
uv run python case_studies/us_equities_panel/01_feasibility_analysis.py uv run python case_studies/us_equities_panel/02_labels.py uv run python case_studies/us_equities_panel/03_financial_features.py uv run python case_studies/us_equities_panel/04_model_based_features.py uv run python case_studies/us_equities_panel/05_evaluation.py uv run python case_studies/us_equities_panel/06_linear.py uv run python case_studies/us_equities_panel/07_gbm.py uv run python case_studies/us_equities_panel/08_tabular_dl.py uv run python case_studies/us_equities_panel/09_dl_nlinear.py uv run python case_studies/us_equities_panel/10_dl_lstm.py uv run python case_studies/us_equities_panel/11_dl_tsmixer.py uv run python case_studies/us_equities_panel/12_dl_weekly.py uv run python case_studies/us_equities_panel/13_latent_factors.py uv run python case_studies/us_equities_panel/13a_pca.py uv run python case_studies/us_equities_panel/13b_ipca.py uv run python case_studies/us_equities_panel/14_causal_dml.py uv run python case_studies/us_equities_panel/15_model_analysis.py uv run python case_studies/us_equities_panel/16_backtest.py uv run python case_studies/us_equities_panel/17_portfolio_management.py uv run python case_studies/us_equities_panel/18_risk_management.py uv run python case_studies/us_equities_panel/19_costs.py uv run python case_studies/us_equities_panel/20_strategy_analysis.py其中20_strategy_analysis.py以template="full"写出完整诊断 tear sheet(us_equities_panel_tearsheet.html)到该案例 gitignore 的输出目录,读者可在本地重新生成。关于端到端运行案例、降参测试与 headless 执行的通用模式,可参考 docs/running-notebooks.md;九个案例研究的目录布局与阶段-章节映射总览见 case_studies/README.md。
Run Log:内容寻址的结果注册表
模型训练、预测与回测结果都记录在内容寻址注册表run_log/registry.db中,这是全案例唯一的结果事实源(第 6.7 节"run log"的实现)。每个模型运行由其配置 hash 内容寻址:run_log/training/{hash}/存放规格、系数、booster、checkpoint,run_log/predictions/{hash}/存放预测数组,run_log/backtest/{hash}/存放收益、交易、权重与配置。策略分析 notebook 通过注册表重开不可变的验证回测集合、施加确定性选取规则(最高验证 Sharpe,hash 破平),从而保证评估独立于注册表行序与后续实验。注册表 schema 与查询 API 见 case_studies/RUN_LOG.md;scripts/download_artifacts.py可在不重训的情况下安装已验收的 run log 与存储产物,scripts/create_experiment.py可创建可写的实验副本。
结语:这条流水线证明了什么
US Equities Panel 案例研究把"主动管理基本定律"拆成了可检验的一串论断:信号在统计上显著(IC 0.0357,t_HAC ≈ 11)、在选取修正后仍存活(DSR 与 PBO 全过)、边际确为 alpha 而非因子暴露(FF5+MOM 残差 Sharpe ≈ 2.04)、摩擦底线足够宽(10 bps 下仍有 2.117 的 Sharpe)——但显式 holdout 给出了诚实的一击:2016–2018 时代该边际消失(Sharpe −0.492,差分为负且显著)。它同时示范了 21 阶段流水线的工程纪律:点及时刻宇宙、跨特征缩尾、checkpoint 计入候选数、整个模型群体回测、成本扫描不重排名次、唯一结果事实源注册表。对任何要在大横截面股票数据上做端到端 ML 策略研究的读者,这份案例研究都是一份可逐行复现的参考实现。
【免费下载链接】machine-learning-for-tradingCode for Machine Learning for Trading, 3rd edition — from data sourcing to live execution.项目地址: https://gitcode.com/GitHub_Trending/ma/machine-learning-for-trading
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考