拓冰建站拓冰建站
首页 / 资讯中心 / 正文

机器学习交易实战:定义学习任务——从数据质量到标签、信号检验与多重检验的完整研究流水线(machine-learning-for-trading 第七章深度解析)

机器学习交易实战定义学习任务——从数据质量到标签、信号检验与多重检验的完整研究流水线machine-learning-for-trading 第七章深度解析【免费下载链接】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 项目第七章 Defining the Learning Task07_defining_the_learning_task/README.md展开系统拆解一条可审计、防泄漏的量化研究流水线从数据质量诊断与 split-aware 预处理到执行一致的标签工程再到单因子 IC 评估、多重检验校正与因果性 sanity check。读完本文你将掌握SplitAwarePreprocessor的防 lookahead 机制、triple-barrier 等主流标签的配置语义、HAC/Block Bootstrap 推断、BH-FDR/Holm-Bonferroni 校正以及 DAG 式机制合理性检验并能直接在本仓库中运行对应 Notebook 复现全部实验。本文全部技术细节均可溯源至 07_defining_the_learning_task 目录下的 8 个 Notebook 脚本及其依赖的ml4t-engineer库。为什么定义学习任务是量化研究的起点本章的核心命题是特征研究远在建模之前就已经开始。原始的、但已经过验证的市场数据必须被转换成稳定、协议安全的输入途径是强制 train-only 拟合、有纪律的异常值处理、显式的表示选择以及可见的缺失数据规则。其回报不是表面上的整洁而是可比性comparability不同数据集、不同章节之间可以公平对照可审计性auditability每一步清洗与转换都有据可查防泄漏protection against leakage避免任何形式的前视偏差lookahead bias——否则后续所有信号评估都会失去意义。从源码结构看本章的 9 个 Notebook 精确对应五个学习目标sections 7.1–7.5形成了一个层层递进的漏斗数据质量 → 预处理 → 标签 → 单因子评估 → 多重检验 → 因果合理性。Section 7.1 数据预处理与编码先诊断再清洗01_data_quality_diagnostics只评估、不清洗的健康报告01_data_quality_diagnostics.py 提供一个跨全部 ML4T 数据集的标准化诊断调查覆盖 ETFs、US Equities、Crypto、CME Futures、FX、Firm Characteristics 等面板数据。它不执行任何清洗只输出健康报告回答哪些数据集需要主动预处理哪些已经处于良好状态。诊断函数库遵循一致接口——输入 DataFrame返回诊断结果Index Integrity Check验证时间索引的 dtype、单调性、唯一性对面板数据检查(date, symbol)二元组是否唯一。源码特意强调单调性检查必须按每个 symbol 读取其行序若先排序再检查则任何乱序输入都会返回 True——那是一个无法失败的检查Missingness / Duplicates / Outliers / Gaps四类常见金融数据质量问题的系统探测数据集特有怪癖识别影响 ML pipeline 设计的结构性特征。该 Notebook 内存峰值约9 GB RSS官方建议系统 RAM ≥ 16 GB。它使用的加载器来自仓库data模块如load_etfs()、load_us_equities()统一返回标准列名的 Polars DataFrame。02_preprocessing_pipelinesplit-aware 清洗的完整示范02_preprocessing_pipeline.py 对需要清洗的数据集实施实战清洗核心教学产物是SplitAwarePreprocessor类——它通过在训练集上学习参数、并把这些参数应用到验证/测试集来杜绝前视偏差。内存峰值约12 GB RSS建议 ≥ 24 GB。可复用清洗工具函数脚本先定义了四个通用工具源码 L98-L343函数作用关键参数ensure_symbol_alias将asset列暴露为symbol统一标识符命名—filter_from_start无时区/单位错配的起始日期过滤time_col,start_valueremove_duplicates精确重复与近重复处理key_colsstrategy∈keep_first/keep_last/drop_all默认keep_lastwinsorize_panel在分位数边界截断极值fields,limits(0.01, 0.99)by_periodTrue时按时间逐日横截面计算分位数否则全局截断winsorize_panel的by_period模式体现了金融数据的特殊性按日期分组计算上下界df.group_by(period_col).agg(quantile...)再做左连接与pl.when截断源码 L370-L386保证每天的分位数基准互不影响。SplitAwarePreprocessor 的实现原理SplitAwarePreprocessor源码 L409-L536是一个dataclass其设计原则一句话概括任何用于预处理的统计量均值、标准差、中位数、编码器词表都必须只在训练数据上计算。配置字段dataclass class SplitAwarePreprocessor: scale_cols: list[str] # 需标准化的列 winsorize_cols: list[str] # 需分位数截断的列 winsorize_limits: tuple[float, float] (0.01, 0.99) impute_cols: list[str] # 需缺失填充的列 impute_strategy: Literal[median, mean, zero] median rank_cols: list[str] # 需横截面排序rank的列fit(train_df)阶段源码 L440-L479学习三类参数缩放参数对每个scale_cols列在drop_nulls()后计算 mean/std 存入_scale_params截断边界对每个winsorize_cols列计算winsorize_limits对应的上下分位数存入_winsorize_params填充值按impute_strategy学习 median/mean/0.0 存入_impute_params。transform(df)阶段源码 L481-L519先检查_fitted标志未拟合直接抛ValueError再依次应用填充缺失 → 分位数截断pl.col(col).clip(lower, upper)→ 标准化(x - mean) / std且仅在std 0时执行避免除零→ 横截面排名rank().over(timestamp)无需拟合。此外提供fit_transform()一步到位、save()/load()的 pickle 序列化源码注释明确生产环境建议改用ml4t-engineer的序列化。泄漏演示fit on train only vs fit on full data脚本用合成数据1000 行训练 200 行测试并在 3 月份放大波动模拟高波动 regime做了对照组实验源码 L931-L1090# 正确做法只在训练集上 fit preprocessor SplitAwarePreprocessor( scale_cols[returns], winsorize_cols[returns], winsorize_limits(0.01, 0.99), ) preprocessor.fit(train_df) train_processed preprocessor.transform(train_df) test_processed preprocessor.transform(test_df) # 错误做法全量数据 fitBUG: includes future data! leaky_preprocessor.fit(full_data)结果测试集的标准差并不等于 1——这是正确行为因为测试集代表统计特性可能不同的未来数据。而全量拟合会把未来信息渗入训练表示虽然单参数差异看似微小但在数十个特征、数千条测试样本上这种系统性偏差会累积显著虚增 Sharpe 比率与 IC 估计。两张共享分箱与坐标轴的直方图证明均值线的微小偏移就是泄漏的纯特征。Walk-Forward Refit逐折重拟合在 walk-forward 评估中预处理器必须在每个 fold 边界用截至该点的数据重新 fit源码 L1094-L1140。3 折扩窗循环演示了 mean/std/分位数边界如何随扩张的训练窗漂移——合成数据是平稳的所以漂移小真实市场中的 regime 切换会产生更大的均值、方差与尾部边界摆动。跨数据集对齐as-of join 防未来泄漏Crypto spot/perps 对齐8 小时 K 线做 inner join 计算 basispremium × 100源码 L819-L835日频价格 × 月频特征 as-of join源码 L863-L871daily_df.with_columns(monthpl.col(timestamp).dt.truncate(1mo)) daily_df.join(monthly_chars, left_on[permno, month], right_on[permno, timestamp])这确保每条日频观测只能看到该时点可用的信息防止未来特征更新造成前视。分类编码handle_unknownignore用OneHotEncoder演示训练集只含 5 个行业、测试集出现未见的 Utilities 类别时源码 L895-L919handle_unknownignore会把未见类别映射为全零向量——模型看到的是中性表示而不是崩溃或静默错编码。美国股票四步深度清洗US Equities 是本章最复杂的数据集源码 L539-L719Penny stock 过滤close 1.0剔除 1 美元以下股票其微观结构噪声会主导横截面模型Domain 规则过滤正价格OHLC 全 0、非负成交量、OHLC 一致性low open/close且high open/close极端日收益剔除MAX_ABS_DAILY_RETURN 2.0|return| 2的行大多落在拆股日——源码敏锐地指出该阈值只能捕获向上的异常收益下界是 -1因此无法用作拆股探测器但作为过滤器仍有效Spike 检测单根 K 线反转急涨后立即回落很可能是数据错误而非真实价格移动spike_filter(close, threshold0.5, actionflag)。脚本还专门可视化了 winsorize 的效果分布主体不受影响被移动的是远尾——1st/99th 之外的每一行都被重新赋到该分位数上因此右图在每个边界处长出一根窄尖峰。这是该方法所做的权衡拟合在截断序列上的 scaler 不再被少数极端日拖拽代价是序列不再能表达那些极端日有多极端。Section 7.2 标签工程让预测目标执行一致03_label_methods.py 是全书建模章节选择与配置标签的权威参考在真实 ETF 数据SPY 单资产 全宇宙横截面上演示所有主流标签方法。它从ml4t.engineer.labeling导入全套实现fixed_time_horizon_labels、rolling_percentile_binary_labels、triple_barrier_labels、atr_triple_barrier_labels、trend_scanning_labels、meta_labels、sequential_bootstrap、compute_bet_size、calculate_label_uniqueness。固定时间窗标签Fixed Time Horizon最简单的方案计算固定窗口的前向收益。21 个交易日是日频数据中一个月的通用约定HORIZON 21。支持三种 methodmethod说明适用场景returns原始百分比收益回归目标binary收益 0 取 1否则 -1分类log_returns对数收益回归统计性质更优横截面百分位标签Cross-Sectional Percentile当目标是排序型做多前 20%、做空后 20%时使用区分时间序列与横截面两种百分位基准——横截面版本每天在所有标的中取分位天然消除了市场整体波动的干扰。Triple-Barrier 标签路径依赖的交易结果来源于 De Prado《Advances in Financial Machine Learning》用LabelingConfig.triple_barrier配置config LabelingConfig.triple_barrier( upper_barrier0.02, # 2% 止盈 lower_barrier0.01, # 1% 止损 max_holding_period20, # 最长持有 20 天 side1, # 仅多头 ) labels_tb triple_barrier_labels( spy, configconfig, price_colclose, timestamp_coltimestamp, calculate_uniquenessTrue, )上轨触及止盈 → 1下轨触及止损 → -1时间轨两者均未触及 → 按期末收益打标。源码强调了屏障测试对象的关键细节传入high_col/low_col/open_col时会检测 K 线范围内的触碰并以开盘价执行跳空穿透gap-through省略时如本节演示则退化为仅用收盘价——屏障只有被close穿越才算触及成交价记为屏障价。两种简化都会美化标签集这正是后文要测量的内容。路径可视化示例刻意展示下轨案例标签记录的是 -1% 的止损而该路径其后实际又跌了 28%——这就是止损的全部意义也是把标签当作市场描述而非交易描述的全部风险。ATR 自适应屏障与 MFE/MAE 的经验校准04_maximum_favorable_adverse_excursion.py 为 triple-barrier 参数提供经验依据与其随意选屏障宽度不如分析真实价格的有利/不利偏移MFE/MAE来确定阈值。脚本同时演示了ml4t-engineer的库版 ATRatr_triple_barrier_labels。趋势扫描标签、Meta-Labeling 与样本权重Trend Scanning LabelsL1172对不同趋势斜率窗格做扫描识别结构性趋势区间Meta-LabelingL1388第一层模型判断方向第二层模型判断是否下注bet sizing用meta_labels与compute_bet_size配合样本权重calculate_label_uniqueness计算标签重叠度sequential_bootstrap在重叠标签上做去相关重采样两者共同支撑更诚实的样本加权训练。重叠、解析时间与隐含交易强度本节反复强调一个 bar 的时间错配、糟糕的阈值选择、被忽视的重叠都可能制造出一个一碰到实盘就消失的信号。每类标签都必须回答三个问题重叠程度相邻样本共享多少结果窗口、解析行为屏障被谁、在什么价格触发、隐含交易强度标签隐含的换手与持仓时长。各 case study 在各自的02_labelsNotebook 中按config/setup.yaml里的 horizon 通过utils.artifact_specs.resolve_label_horizon生产正式标签见case_studies/etfs/02_labels、case_studies/crypto_perps_funding/02_labels、case_studies/nasdaq100_microstructure/02_labels等 9 个案例目录。Section 7.3 单因子特征-标签评估第一道严肃的筛选层05_signal_evaluation.py 构建全书第一道严肃的候选信号筛选层按顺序回答四个问题决策时点上特征是否正确、是否与标签相关、分布形态是否支持映射为仓位、考虑换手/成本/流动性后是否经济可行。它把因子研究重新定义为可审计的筛选流程而非寻找一个吸引眼球的统计量。IC 分析及其两种口径IC 是信号与前向收益的横截面秩相关$$IC_t \text{Spearman}(\text{signal}{t}, \text{return}{t \to th})$$脚本区分两种口径Pooled IC把所有期合并与Cross-Sectional IC逐日计算后对日序列取均值后者是主口径因为能保留时间序列特性、支持后续推断。IC 量级的解释锚点标准误而非头条数字一个关键的解读纪律源码 L341-L378解释平均 IC 的锚点不是头条数值而是其均值标准误$$\text{SE}(\bar{\text{IC}}) \approx \frac{\sigma_{\text{IC}}}{\sqrt{T}}$$脚本用一个固定的IC_SCENARIO_MEAN 0.02在三种场景下演示场景Tσ_IC结论十年、紧致的日 IC25000.05与 0 显著区分十年、宽散的日 IC25000.30不可区分一年、宽散的日 IC2500.30完全不可区分ICIR IC 均值 / IC 标准差是信号级的信息比率序列不相关时 t ≈ ICIR × √T现实的自相关情形需用 HAC 调整的 t。脚本还内置了权益因子文献的 |mean IC| 参考带宽表从等于或低于多年日 IC 噪声地板到更高区间用于给因子 IC 分档。Quantile 分析单调性与多空价差按信号分位分组如五分位考察收益核心判据是单调性信号越高收益是否越单调上升以及顶底分位之间的 spread。此外包含正确性前置检查decision-time 可用性与 IC 时间序列可视化。Section 7.4 搜索核算与多重检验把反过拟合变成会计纪律06_ic_inference.py 处理 IC 的统计推断我们对信号 IC 不是噪声有多大的信心HACNewey-West调整带宽必须感知标签地平线重叠标签 慢变信号导致 IC 序列强自相关。Newey-West 估计量使用自协方差的加权和Bartlett 核 $w_j 1 - j/(L1)$L 为滞后截断$$\hat{\sigma}^2_{HAC} \hat{\gamma}0 2\sum{j1}^{L} w_j \hat{\gamma}_j$$关键教训L 不能交给样本量自动规则。自动规则 $L \lfloor 4(T/100)^{2/9} \rfloor$ 只读 T在本序列上返回 9但标签是 h 日重叠前向收益日期 t 与 tj 对每个 j h 共享部分结果窗口且 21 日动量信号的横截面排序变化缓慢——重叠结果 × 持久排序 ⇒ IC 在约一个标签地平线内共同移动。因此只提重叠不足以论证 $h-1$——IC 是秩相关而非收益若信号排序每日独立重抽IC 可以序列不相关$h-1$ 是对持久信号的保守、地平线感知带宽实测 ACF 在滞后约 16 之前都跑在白噪声带外调用compute_ic_hac_stats(ic_series, label_horizonLABEL_HORIZON)让库取 $L \max(h-1, \text{auto rule})$不传label_horizon会触发库的UserWarning自动带宽对重叠标签可能 anti-conservative那是库在尽职。带宽值多少side-by-side 测量同一 IC 序列两种跑法对比源码 L287-L346口径LSEtp自动规则9较小较高较小label_horizon 感知h-1放大SE 比约 1.x 倍收缩放大对比还包括 Naive SEstd/√T与 HAC SE 的膨胀倍数、Naive t vs HAC t、Naive p vs HAC p以及Naive 显著但 HAC 不显著的警告分支——这正是泄漏式推断的典型症状。Block bootstrap 以长度为 h 的连续块重采样天然尊重重叠因此与地平线感知的 HAC 一致两侧对照证实差异来自带宽而非估计量家族。Factor Zoo 与多重检验校正07_multiple_testing.py 直面因子动物园问题即使推断正确大量测试后的最佳也会被选择偏差抬高。先定义被搜索的集合searched set、把探索与确认分离再引入两类校正BH-FDRBenjamini-Hochberg——控制所有发现中假阳性的期望比例$$FDR E\left[\frac{\text{False Positives}}{\text{All Discoveries}}\right]$$三步程序排序 p 值 p₍₁₎ ≤ ... ≤ p₍ₙ₎ → 找最大 k 使 p₍ₖ₎ ≤ (k/n)×α → 拒绝假设 1..k。脚本先在合成面板上跑 100 因子对比 Naivep0.05 的发现数与 BH-FDR发现数锐减期望假阳性降为 0并可视化 p 值直方图零假设下应均匀与 BH 阈值线源码 L339-L419。Holm-Bonferroni FWER源码 L461——控制至少一次假阳性的家庭错误率步骤化 Bonferroni比原始 Bonferroni 保留更多功效。一处重要的数据纪律源码 L351-L361喂给校正程序的 p 值必须是 HAC 调整过的而非 naive 的——否则06_ic_inference的依赖性问题原封不动被带进校正。合成面板因逐期独立、标签不重叠而显式传NON_OVERLAPPING真实 ETF 搜索则传实际 horizon。Section 7.5 从相关到因果机制合理性作为证伪层08_causal_sanity_checks.py 为通过统计筛选的特征引入因果思维作为证伪层。用小 DAG 与机制合理性检查提问该信号反映的是持久通道还是混杂代理、时序伪影或聚合错误其价值不在于证明因果而在于尽早拒绝弱故事、为后续多元工作携带更良设定的假设。轻量证伪测试用compute_cross_sectional_ic建立 21 日地平线的HAC 调整基线 IC对扫描网格执行 grid-wide BH 校正每个 cell 报告 raw p 与校正后的q_bh/sig_bh决策避免只看 raw p 而把校正已拒绝的 cell 误报为显著演示了 lookup 必须以 feature 列而非显示标签 join——两者拼写不同会导致静默空结果这正是该表要防的安静的漏检。一个贯穿性的结论源码 L783-L79912-1 动量拥有网格内最大 IC却通不过 grid-wide BH 校正——raw p 是选择后的数字这个特征和地平线是通过看扫描结果才选出来的因此每一次参与选择的比较都必须被计入成本BH 就是那张账单而 Reversal 的 IC 在任何口径下都与零不可区分。这精确演示了 7.4 与 7.5 的衔接HAC 放宽单次检验的区间BH 设定该检验在全部其他检验中必须越过的阈值——两者独立且同时适用。REVISE 是预期结果而非失败。在有效市场中横截面 IC 本来就小HAC 显著性是保守的极少有单个特征能干净通过全部三项双变量检查。诊断信息——特征在哪里、何时有效——比分类标签更有价值。运行本章 Notebook所有 Notebook 均以 Jupytext percent 格式保存.py与.ipynb一一对应从仓库根目录运行# 运行单个章节脚本 uv run python 07_defining_the_learning_task/notebook.py # 测试模式Papermill 注入精简数据 uv run pytest tests/test_chapter_notebooks.py -v -k 07_defining_the_learning_task内存与运行时间注意Notebook资源消耗建议01_data_quality_diagnostics峰值约 9 GB RSS系统 RAM ≥ 16 GB02_preprocessing_pipeline峰值约 12 GB RSS系统 RAM ≥ 24 GB08_causal_sanity_checks约 6 分钟200 次置换零分布 × 多特征多地平线耐心等待ml4t 库生态贯穿第 7–12 章的工具链10_ml4t_library_ecosystem.py 介绍贯穿第 7–12 章的 ml4t 库生态以 etfs 数据演示ml4t-datadata模块七个数据集的统一加载接口返回标准列名的 Polars DataFrame如load_etfs()ml4t-engineer120 预构建特征get_registry()列出全目录每个特征携带默认参数、输入要求、描述与闭式公式元数据约四分之一的目录有标准公式动量与价格变换类居多估计量型波动率与微观结构特征没有compute_features()支持三种输入格式——特征名列表默认参数、dict 列表逐特征自定义参数如{name: rsi, params: {period: 10}}注意 Bollinger 上下轨按 TA-Lib 惯例分开传nbdevup/nbdevdn、YAML 配置可复现的 pipelineml4t-diagnostic特征评估工具预览其analyze_signal支撑本节与后续章节的 IC/分位/价差评估每个模块构建自己的DiagnosticLogger可用quiet_ml4t_logging()将其 INFO 旁白压制到 WARNING 以下源码 L80-L94。关键要点速览预处理必须 split-aware一切统计量均值/标准差/中位数/编码词表只在训练集拟合见SplitAwarePreprocessorDomain 过滤器抓明显错误负价格、不可能的 OHLC 关系Spike 检测识别数据伪影单 K 线反转常是错误Winsorization 处理离群值但边界必须来自训练数据分类编码必须处理未见类别handle_unknownignore映射为全零Walk-forward 逐折重拟合捕获跨市场 regime 的参数漂移跨频对齐用 as-of join每日观测只看到该时点的信息HAC 带宽要感知标签地平线、p 值必须 HAC 后喂给多重检验校正报告显著性必须连同 searched set 与校正决策否则就是选择后的数字机制合理性检验把因子研究从寻找漂亮统计量重构为可审计的筛选流程。延伸阅读第一章过程即优势Process is Edge——研究流程纪律的整体框架第二章金融数据宇宙——七个数据集的加载与 EDA第六章策略定义与交叉验证基础——leakage-aware splitting§6.3是本篇预处理原则的前置知识第八章金融特征工程——承接本章筛选出的稳定输入各 case study 的02_labels目录如 case_studies/etfs/02_labels、case_studies/cme_futures/02_labels——生产级标签的落地实例。【免费下载链接】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),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门