第一章:因子构建与标准化

各位同学好,我是老张。今天咱们聊聊因子构建与标准化。说实话,这是整个宏观因子交易系统里最基础、也最容易踩坑的环节。我见过太多人因子算对了,但标准化没做好,结果回测曲线漂亮得不行,实盘一跑就崩。嗯,咱们今天就把这块彻底讲透。

1.1 因子计算逻辑

先说说因子是什么。说白了,因子就是能解释资产收益的某种特征。比如GDP增速、CPI变化、利率曲线斜率,这些都是宏观因子。但光有原始数据不行,你得把它变成可交易的信号。

我个人习惯把因子计算分成三步:

  1. 数据清洗:去掉缺失值、处理重复数据
  2. 差分/对数处理:让数据平稳
  3. 方向判断:确定因子是正向还是反向影响

举个例子,假设我们要构建一个“通胀动量因子”:

# 伪代码示例
def calculate_inflation_momentum(cpi_series, lookback=12):
    # 计算12个月滚动变化
    momentum = cpi_series.pct_change(periods=lookback)
    # 去趋势处理
    momentum = momentum - momentum.rolling(60).mean()
    return momentum

这里有个坑:滚动窗口的选择。我记得刚开始做的时候,直接用全样本均值去中心化,结果回测时因子值一直在漂移。后来才明白,必须用滚动窗口,不然就是未来函数。

1.2 Z-score标准化

因子算出来了,但不同因子的量纲不一样。比如GDP增速可能是2.5%,而利率变化可能是0.1%。直接比较没意义,必须标准化。

Z-score是最常用的方法:

Z = (X - μ) / σ

其中μ是均值,σ是标准差

但这里有个细节:用哪个窗口的均值和标准差?

我建议用滚动窗口。比如用过去252个交易日(约1年)的均值和标准差。为什么?因为市场环境在变,5年前的均值对今天没意义。

def zscore_rolling(series, window=252):
    rolling_mean = series.rolling(window).mean()
    rolling_std = series.rolling(window).std()
    zscore = (series - rolling_mean) / rolling_std
    return zscore

小技巧:如果数据量不够,可以先用expanding窗口初始化,再切换到rolling。我一般前60个交易日用expanding,之后用rolling。

1.3 滚动窗口处理

滚动窗口是标准化里的核心。你想想看,如果不用滚动窗口,直接用全样本均值,那每个时间点的因子值都包含了未来的信息。这在回测里是致命的。

常见的窗口选择:

窗口长度 适用场景 我的经验
20天(1个月) 高频因子、短期动量 噪声太大,慎用
60天(3个月) 中期反转因子 比较均衡,我常用
252天(1年) 宏观因子、趋势跟踪 稳定,但反应慢
504天(2年) 长期均值回归 适合债券因子

我曾经犯过一个错误:用20天窗口做利率因子的标准化。结果因子值上蹿下跳,交易信号频繁反转,手续费都亏光了。后来改成60天窗口,信号稳定多了。

1.4 异常值处理

异常值是个大问题。宏观数据经常有突发事件,比如2008年雷曼倒闭、2020年疫情。这些极端值会把Z-score拉偏,导致大部分时间因子值都在0附近,失去区分度。

我常用的方法有三种:

  1. MAD法(中位数绝对偏差):比标准差更稳健
  2. 分位数截断:比如把超过99%分位数的值截断
  3. Winsorize:把极端值替换为边界值

注意:不要直接删除异常值!删除会导致数据不连续,影响滚动窗口计算。我一般用Winsorize,把上下1%的极端值替换为边界值。

def winsorize_series(series, limits=[0.01, 0.99]):
    lower = series.quantile(limits[0])
    upper = series.quantile(limits[1])
    return series.clip(lower, upper)

这里有个实战经验:异常值处理要在标准化之前做。先截断极端值,再算Z-score,这样标准化后的因子值不会因为几个极端点而失真。

知识体系总览

下面这张图是我自己画的,把因子构建与标准化的核心逻辑串起来了:

宏观因子动量与反转交易系统 - 因子构建与标准化流程 原始宏观数据 因子计算逻辑 数据清洗 差分/对数处理 异常值处理 MAD法 / Winsorize 分位数截断 滚动窗口 Z-score 标准化 标准化因子信号 图:因子构建与标准化完整流程

这张图把整个流程串起来了。从原始数据开始,经过因子计算、异常值处理、滚动窗口标准化,最后输出标准化的因子信号。每一步都有坑,每一步都要小心。

核心要点总结

  • 因子计算要避免未来函数,滚动窗口是关键
  • Z-score标准化必须用滚动窗口,不能用全样本
  • 异常值处理要在标准化之前做,推荐Winsorize
  • 窗口长度选择要结合因子特性,没有万能参数

好了,这一章就到这里。因子构建和标准化是基本功,看似简单,但细节决定成败。我见过太多人在这上面栽跟头,希望你们能少走弯路。


专注资料整理