← 文件目录notebook5_multifactor_modeling_proposal.md查看原文件

Notebook 5 多因子建模企划

1. 文档目的

本企划定义 05_factor_evaluation.ipynb 的研究任务、数据接口、训练系统、模型比较、模型保存与推理输出。Notebook 5 承接 Notebook 1–4 已完成的单因子研究,将所有预先构造的候选因子统一为日频多因子面板,并在严格的滚动时间切分下比较三个模型:Ridge、LightGBM LambdaRank、Incremental PCA + LSTM。

Notebook 5 的重点是预测研究,而不是正式策略回测。它输出逐日股票预测分数、横截面排名、分位数和研究性 long-only 权重。交易约束、订单执行、交易成本以及最终绩效归因由 Notebook 6 处理。

1.1 核心研究问题

  1. Notebook 1–4 的全部候选因子能否合并为无未来信息泄漏的日频面板?
  2. 高度相关的因子应该如何处理:正则化、排序树模型,还是 PCA?
  3. 使用过去 60 个交易日因子序列的 LSTM,是否比只使用当日截面特征的 Ridge 和 LightGBM 提供稳定增量?
  4. 在固定三年训练、随后一年样本外测试的滚动框架中,模型表现是否跨年度稳定?
  5. 模型能否被完整保存,并对新的时间区间生成可复现的股票分数与研究性权重?

1.2 预先固定的研究规则

这些规则应在运行 OOS 测试之前固定。Notebook 5 不允许根据最终测试年度表现修改规则后再次把同一年称为独立 OOS。


2. Notebook 5 与 Notebook 6 的职责边界

2.1 Notebook 5 负责

2.2 Notebook 5 不负责

2.3 Notebook 6 负责

Notebook 6 读取 Notebook 5 的冻结信号,执行组合构建和正式回测。建议采用双引擎:

  1. 向量化引擎,用于快速比较少量已冻结模型和权重映射。
  2. Backtrader 事件驱动引擎,用于订单、现金、T+1、成本和成交限制验证。

Backtrader 不进入 Notebook 5 的训练循环。训练阶段调用事件驱动回测会显著增加计算成本,并把预测模型与执行规则过度耦合。


3. Part 1:统一日频 Panel Data

3.1 现有数据体量

当前四张主表均约有 12,019,585 行,键为 instrument × datetime:

来源 主文件 大小 字段数 模型候选
Notebook 1 momentum_factors_real.parquet 约 0.35 GB 18 10
Notebook 2 factor_N2.parquet 约 3.56 GB 51 21 个 *_mad_z
Notebook 3 factor_N3.parquet 约 3.49 GB 58 23 个 *_mad_z
Notebook 4 technical_factors_checkpoint.parquet 约 4.00 GB 67 30

候选特征总数为 84。当前机器内存约 3.8 GB,不能同时把四张宽表读入 pandas,更不能预先生成完整的三维 LSTM 数组。

3.2 推荐存储架构

使用 Parquet + PyArrow Dataset 或 DuckDB,按 year/month 分区:

notebook_data/notebook5/
├── panel_store/
│   ├── year=2014/
│   │   ├── month=01/part-000.parquet
│   │   ├── month=02/part-000.parquet
│   │   └── ...
│   ├── year=2015/
│   └── ...
├── manifests/
│   ├── feature_catalog.csv
│   └── panel_manifest.json
├── models/
├── predictions/
└── diagnostics/

选择该架构的原因:

不推荐 SQLite。SQLite 适合事务和点查询,不适合反复扫描数千万行浮点特征,也不能像 Parquet 一样高效进行列裁剪。

3.3 统一面板字段

每个分区只保留:

datetime
instrument
84 个模型特征
future_return_20
target_rank_20
eligible
universe_member

不重复保存四本 notebook 中重复的 OHLCV,不同时保存 raw 与 MAD-z 两套模型输入,不保存仅供中间计算的滚动列。

3.3.1 因子命名

为避免字段冲突,建议增加来源前缀:

n1__mom_3m
n2__ivo_30
n3__log_amount_20
n4__QTLD60

feature_catalog.csv 应记录:

feature_name
source_notebook
source_column
family
frequency
availability_rule
normalization
expected_dtype
description

3.4 Notebook 1 月频因子的日频对齐

Notebook 1 的因子研究口径是月频,不能把月末因子直接错误地当作每天重新计算的信号。

推荐规则:

  1. 在每只股票每个月最后一个有效交易日取得因子值。
  2. 该值从下一个交易日开始生效。
  3. 向前填充至下一次月末更新后的第一个交易日前。
  4. 月末当日不能使用当日收盘后才完整形成的值进行当日预测或成交。
  5. 保存 feature_asof_date 或通过自动测试验证每行因子值的来源日期早于当前预测日期。

这会产生“低频信号在日频面板中保持不变”的区段,但不代表每天产生新的独立信息。模型训练与统计解释必须认识这一点。

3.5 Notebook 2–4 因子选择

3.6 标签定义

未来 20 日收益沿用 Notebook 2–4 的定义:

[ r_{i,t\rightarrow t+19} =\prod_{k=0}^{19}(1+\Delta p_{i,t+k})-1. ]

每日对具备有效未来收益的股票做横截面排序:

[ y_{i,t}=2\times\operatorname{PercentileRank}(r_{i,t\rightarrow t+19})-1. ]

因此 target_rank_20 位于约 [-1, 1]。该标签:

3.7 样本资格与缺失值

eligible 至少要求:

eligible 只表示可进入预测研究样本,不等同于可成交。停牌、涨跌停、T+1 和容量等执行资格由 Notebook 6 单独定义。

缺失值处理规则必须在每个训练窗口内拟合:

3.8 构建算法与内存控制

Panel 构建按月执行:

  1. 读取目标月份的键 datetime, instrument。
  2. 对每个 notebook 只投影所需因子列。
  3. 按键 join,不载入重复 OHLCV。
  4. 生成标签和资格字段。
  5. 将浮点特征转换为 float32。
  6. 原子写入临时 Parquet 后 rename。
  7. 写入行数、日期范围、股票数、缺失率和校验值。
  8. 释放对象,再处理下一个月。

禁止:

3.9 Panel 验收标准


4. Part 2:滚动训练系统

4.1 时间切分

固定三年训练、下一年 OOS:

2014–2016 训练 → 2017 OOS
2015–2017 训练 → 2018 OOS
2016–2018 训练 → 2019 OOS
2017–2019 训练 → 2020 OOS
2018–2020 训练 → 2021 OOS
2019–2021 训练 → 2022 OOS
2020–2022 训练 → 2023 OOS
2021–2023 训练 → 2024 OOS
2022–2024 训练 → 2025 OOS

2026 如果只有半年度数据,不与完整年度直接比较。可以保存为 provisional prediction,但不能与完整 OOS 年度同权汇总。

4.1.1 内部验证集

三年训练窗口内部,将最后约 6 个月作为 validation,用于:

训练拟合区与 validation 之间,以及完整训练窗口与 OOS 之间,都应执行至少 20 个交易日的 purge,防止未来 20 日标签跨越边界。

不再额外使用一个完整自然年作为 validation,否则实际训练样本过少。

4.2 建议类接口

trainer = MultiFactorTrainer(
    panel_store=Path(...),
    model_store=Path(...),
    train_years=3,
    test_year=2020,
    validation_months=6,
    horizon=20,
    purge_days=20,
    model_type="ridge",          # ridge | lambdarank | pca_lstm
    sequence_length=60,
    pca_components=24,
    random_seed=42,
)

建议公开方法:

trainer.prepare_split()
trainer.fit()
trainer.evaluate_validation()
bundle_path = trainer.save_bundle()
prediction = trainer.predict(start_date, end_date)

类职责:

类不负责:

4.3 模型一:Ridge

4.3.1 定位

Ridge 是必须保留的线性基准。它回答:复杂非线性或序列模型是否真的超过一个能处理共线性的简单模型?

4.3.2 输入与目标

[ \min_\beta|y-X\beta|_2^2+\lambda|\beta|_2^2. ]

Ridge 会压缩高度相关因子的系数,不要求显式求相关矩阵逆。其输出是连续 score,可直接做每日横截面排名。

4.3.3 为什么需要它

4.4 模型二:LightGBM LambdaRank

4.4.1 定位

LightGBM LambdaRank 是本企划推荐的主表格模型。每个交易日构成一个 ranking group,模型学习同一天股票的相对排序。

4.4.2 为什么选择 LightGBM 而不是 XGBoost

XGBoost 同样可行,但本项目资源约束下不作为首选。企划不同时维护两个相似的 boosting 模型,避免模型空间膨胀。

4.4.3 标签和 group

4.4.4 风险

4.5 模型三:Incremental PCA + LSTM

4.5.1 定位

该模型检验过去 60 个交易日的因子路径是否包含超过当日截面状态的增量信息。

4.5.2 PCA

每个三年训练窗口内:

  1. 只用训练拟合区估计缺失处理和标准化参数。
  2. 使用 IncrementalPCA 分批拟合。
  3. 主方案固定保留 24 个主成分。
  4. 将同一 scaler 和 PCA 载荷应用到 validation 和 OOS。
  5. 下一滚动年度重新拟合 PCA。

PCA 只解释输入方差,不保证主成分具有预测力。它的作用是降低维度、缓解共线性和减少 LSTM 参数,不是监督式选因子。

90% 累计解释方差规则可作为稳健性实验,但不是主方案,防止每年维度变化导致模型难以比较。

4.5.3 序列

4.5.4 网络规模

第一版保持小型:

不引入 attention、Transformer 或大型多任务结构,除非 LSTM 已经稳定超过 Ridge 和 LambdaRank。

4.6 Loss Function

4.6.1 主损失:Pairwise Logistic Ranking Loss

在同一个交易日内抽取股票对。若股票 i 的未来 20 日收益高于股票 j,要求模型 score 满足 s_i > s_j:

[ L_{pair} =\frac{1}{|\mathcal P|} \sum_{(i,j)\in\mathcal P} \log\left(1+\exp[-q_{ij}(s_i-s_j)]\right), ]

其中:

[ q_{ij}=\operatorname{sign}(r_{i,t+20}-r_{j,t+20}). ]

该损失可导,并与“选出未来相对收益更高的股票”直接一致。

4.6.2 Pair 采样

全部股票对是 O(N²),不可行。推荐每天分层采样:

4.6.3 三模型的损失对应

不强行让三模型使用完全相同的数学损失;它们必须使用相同的标签定义、训练/OOS 日期和评价指标。

4.6.4 为什么不直接优化策略收益或 Sharpe

策略收益和 Sharpe 应是 Notebook 6 的最终评价,而不是 Notebook 5 第一版的唯一训练损失。

4.7 因子重叠与去冗余

4.7.1 不建议直接逆相关矩阵加权

原始构想:

[ w\propto C^{-1}\sqrt{IC} ]

存在问题:

4.7.2 可保留的解释性基准

可以增加一个非主模型的 shrinkage IC combination:

[ w\propto(C+\lambda I)^{-1}\tilde\mu, ]

其中 C 和 μ 只在训练期估计。μ 可使用经过显著性收缩的训练期 IC:

[ \tilde\mu_j=IC_j\times\frac{t_j^2}{t_j^2+c}. ]

该基准用于解释“相关性修正后的传统因子组合”表现,不进入三大主模型,避免扩大企划范围。

4.7.3 三个主模型如何处理重叠

额外输出训练窗口内的因子相关簇,帮助解释模型,而不是用全样本相关性预删因子。

4.8 统一评价指标

Notebook 5 比较模型时使用完全相同的逐年 OOS 预测:

预测指标

排序诊断

模型比较

Notebook 5 的分组收益仅为预测诊断,不形成正式可交易净值。


5. Part 3:模型保存、推理与研究性权重

5.1 模型目录

models/
└── test_year=2020/
    ├── ridge/
    │   ├── model.*
    │   ├── preprocessor.*
    │   └── manifest.json
    ├── lambdarank/
    │   ├── model.txt
    │   └── manifest.json
    └── pca_lstm/
        ├── scaler.*
        ├── incremental_pca.*
        ├── network_weights.*
        └── manifest.json

5.2 Manifest

每个 bundle 必须记录:

加载模型时必须验证输入特征的名字、顺序和 dtype;不允许静默忽略或重排缺失字段。

5.3 推理接口

bundle = ModelBundle.load(model_path)
prediction = bundle.predict(
    panel_store=panel_store,
    start_date="2020-01-01",
    end_date="2020-12-31",
)

输出 schema:

datetime
instrument
raw_score
rank
percentile
research_weight
model_type
model_id
train_start
train_end
test_year

预测文件按测试年和模型分区:

predictions/
└── test_year=2020/
    ├── model=ridge/*.parquet
    ├── model=lambdarank/*.parquet
    └── model=pca_lstm/*.parquet

5.4 Long-only 研究性权重

推荐使用 top-decile 映射,而不是全市场 softmax:

  1. 每日按 score 计算 percentile。
  2. 只保留 percentile ≥ 0.90 的股票。
  3. 令基础强度为 max(percentile - 0.90, 0)。
  4. 对基础强度归一化,使权重和为 1。
  5. 设置研究性单票上限 2%。
  6. 超出上限的剩余权重迭代分配给未达上限股票。
  7. 无合格股票时权重为 0,剩余视为现金。

这是研究性权重,不是正式目标仓位。它不处理行业、规模、容量、当前持仓和交易限制。

5.5 输出到 Notebook 6 的接口

Notebook 6 只依赖:

Notebook 6 不应重新训练模型或重新拟合 PCA。它读取冻结的预测,执行组合约束和事件驱动回测。


6. Backtrader 企划

6.1 是否使用

建议使用,但放在 Notebook 6,而不是 Notebook 5。

6.2 适合模拟的内容

6.3 需要自定义的 A 股规则

Backtrader 不会自动正确实现:

6.4 双引擎验证

先使用向量化引擎快速计算,然后用 Backtrader 对少量冻结候选做事件驱动验证。在关闭复杂约束时,两者结果应大致一致。若不一致,应优先排查:


7. Notebook 5 建议章节结构

  1. Research contract:固定任务、时间切分和禁止事项。
  2. Source audit:列出四本数据 schema、体量与候选字段。
  3. Feature catalog:生成 84 因子目录。
  4. Partitioned panel build:按年月构建统一日频 panel。
  5. Panel QA:键、日期、缺失率、as-of 和标签审计。
  6. Rolling split definition:三年训练、一年 OOS、20 日 purge。
  7. Trainer interface:定义统一类和模型 bundle。
  8. Ridge baseline:训练、保存、OOS 预测。
  9. LightGBM LambdaRank:按日 group 排序训练。
  10. Incremental PCA + LSTM:流式 PCA、60 日序列、pairwise loss。
  11. OOS prediction comparison:RankIC、单调性和稳定性。
  12. Research weight export:top-decile long-only 研究权重。
  13. Model persistence validation:保存、重载、预测一致性。
  14. Notebook 6 handoff:明确预测文件和正式回测接口。
  15. Conclusions and failure criteria:模型是否提供稳定增量。

8. 风险与失败标准

8.1 主要风险

8.2 模型失败标准

以下任一情况都不应宣称复杂模型有效:

8.3 成功标准


9. 实施顺序

阶段 A:Panel Store

阶段 B:统一训练接口与 Ridge

阶段 C:LightGBM LambdaRank

阶段 D:Incremental PCA + LSTM

阶段 E:比较与交接


10. 建议的最小版本与扩展版本

10.1 最小可行版本

10.2 暂不纳入

10.3 后续可选扩展


11. 最终决策摘要

Notebook 5 被定义为日频多因子预测研究,而不是正式回测:

该结构能把“因子研究”“预测模型”和“策略执行”分离,使每个环节可验证、可复现,并避免把复杂回测逻辑提前混入模型训练。