4、因子构建方法论:标准化与去极值、因子正交化、因子动量与反转处理

各位同学,今天我们来聊聊因子构建中最核心的几个实操环节。说实话,很多人在做多因子模型时,花了大把时间找因子,结果一跑回测,效果惨不忍睹。问题出在哪?往往不是因子本身不行,而是构建流程出了问题。

我个人习惯把因子构建比作「做饭」——原材料再好,清洗、切配、调味这些工序没做好,端上桌照样没人吃。标准化、去极值、正交化,就是这些关键工序。咱们一个一个来拆解。

4.1 标准化与去极值:让因子站在同一起跑线

先问个问题:你手上有两个因子,一个市盈率(PE),数值在5到100之间;另一个是动量因子,数值在-0.3到0.5之间。直接把它们扔进模型会怎样?

结果就是,PE因子会「吃掉」动量因子的影响。因为数值量级差太多,模型会天然偏向数值大的变量。这就是为什么我们需要标准化。

4.1.1 标准化方法

常用的标准化方法有三种,我列个表给你看:

方法 公式 适用场景
Z-score标准化 (x - μ) / σ 数据近似正态分布时
Min-Max标准化 (x - min) / (max - min) 数据有明确边界时
Rank标准化 排序后映射到[0,1] 数据分布未知或含异常值

我在项目中用得最多的是Rank标准化。为什么?因为金融数据很少是正态分布的,你想想看,收益率分布经常是尖峰厚尾,用Z-score反而容易出问题。

核心要点:标准化不是为了改变数据分布,而是为了消除量纲影响。记住这个目的,你就不会选错方法。

4.1.2 去极值处理

说到去极值,我得讲个真实案例。有一次我在做A股因子测试,发现一个因子在2015年股灾期间表现异常好。仔细一查,原来是某只股票因为停牌后复牌,一天涨了10倍,把整个因子的统计量全带偏了。

这就是极值的危害——一个异常点,就能让你的因子分析结果完全失真。

常用的去极值方法:

  • MAD法:中位数 ± 3倍MAD(绝对中位差)。稳健性比标准差法好很多。
  • 百分位法:直接截断1%和99%分位数以外的值。
  • Winsorize法:把极值替换为分位数边界值,而不是直接删除。

我的建议:先用MAD法做第一轮去极值,再用Winsorize法做第二轮。这样既保留了样本量,又控制了极端值的影响。

4.2 因子正交化:解决「多重共线性」这个老问题

因子多了,难免会互相「串通」。比如估值因子和市值因子,天然就有相关性。如果你不处理,模型就会陷入多重共线性的泥潭——系数估计不稳定,今天跑出来一个结果,明天换段数据又变了。

正交化,说白了就是把这些「串通」的因子拆开,让它们各说各的话,互不干扰。

4.2.1 Gram-Schmidt正交化

这个方法很经典,思路也简单:

  1. 选一个基准因子,比如市值因子。
  2. 把其他因子对基准因子做回归,取残差。
  3. 这个残差就是「剔除基准因子影响后」的新因子。

代码实现也很直接:

import numpy as np
from sklearn.linear_model import LinearRegression

def gram_schmidt_orthogonalize(factors, base_idx=0):
    """
    Gram-Schmidt正交化
    factors: 因子矩阵,每列一个因子
    base_idx: 基准因子的列索引
    """
    n_factors = factors.shape[1]
    orthogonalized = np.zeros_like(factors)
    
    # 基准因子保持不变
    orthogonalized[:, base_idx] = factors[:, base_idx]
    
    for i in range(n_factors):
        if i == base_idx:
            continue
        # 对基准因子做回归
        reg = LinearRegression().fit(
            factors[:, base_idx].reshape(-1, 1), 
            factors[:, i]
        )
        # 取残差作为正交化后的因子
        orthogonalized[:, i] = factors[:, i] - reg.predict(
            factors[:, base_idx].reshape(-1, 1)
        )
    
    return orthogonalized

注意:Gram-Schmidt的缺点是结果依赖于基准因子的选择。你选市值做基准,和选动量做基准,得到的结果完全不同。所以这个方法适合你「明确知道哪个因子更重要」的场景。

4.2.2 PCA正交化

PCA就不一样了。它不偏袒任何一个因子,而是找到数据中「方差最大」的方向。

我个人更喜欢用PCA做正交化,原因有三:

  • 不依赖基准选择,结果唯一
  • 能自动降维,剔除冗余信息
  • 主成分之间天然正交,相关性为零

但PCA也有坑——主成分失去了经济含义。你原来有「估值因子」「动量因子」,PCA之后变成了「主成分1」「主成分2」,解释起来就费劲了。

我的经验:做研究阶段用PCA,追求预测精度;做归因分析时用Gram-Schmidt,保留经济含义。两者不冲突,看场景切换就行。

4.3 因子动量与反转处理:抓住时序上的规律

最后一个话题,也是很多人容易忽略的——因子本身也有「动量」和「反转」效应。

什么意思?你想想看,一个因子今天表现好,明天是不是大概率继续好?不一定。有时候是强者恒强(动量),有时候是盛极而衰(反转)。

4.3.1 因子动量的处理

因子动量,说白了就是「过去表现好的因子,未来一段时间可能继续好」。我在做CTA策略时深有体会——有些因子就像有惯性一样,趋势一旦形成,能持续好几周。

处理方法:

  • 滚动窗口平滑:用过去N期的均值代替当期值,过滤噪音
  • 指数加权移动平均:给近期数据更高权重,捕捉趋势
  • 动量打分:根据因子过去表现给权重,表现越好权重越高

4.3.2 因子反转的处理

反转效应正好相反——涨多了要跌,跌多了要涨。这在A股市场尤其明显,特别是短期反转。

我曾经犯过一个错误:在日频策略中用了动量因子,结果回测漂亮,实盘亏得一塌糊涂。后来才发现,A股市场短期反转效应太强,动量因子在日频上根本跑不通。

处理反转的方法:

  • 差分处理:用因子值的变化量代替绝对值
  • 均值回复模型:假设因子会回归长期均值
  • 周期分解:把因子拆成趋势项和周期项,分别处理

避坑指南:做因子动量/反转处理前,先做一下自相关分析。如果自相关系数为正,用动量处理;为负,用反转处理。别拍脑袋决定。

知识体系总览

说了这么多,我把整个因子构建的流程画了张图,方便你理解各环节的关系:

因子构建方法论知识体系 原始因子数据 第一步:标准化与去极值 Z-score / MAD / Winsorize 第二步:因子正交化 Gram-Schmidt / PCA 第二步:动量与反转处理 平滑 / 差分 / 周期分解 干净、正交、稳定的因子

这张图把整个流程串起来了。你从原始因子出发,先做标准化和去极值,把数据「洗干净」。然后分两条路——要么做正交化消除相关性,要么做动量/反转处理捕捉时序规律。两条路可以都走,最终得到的就是干净、正交、稳定的因子。

嗯,这一章的内容就到这。因子构建是基本功,但基本功往往决定你能走多远。下次你跑因子回测时,记得先问问自己:标准化做了吗?极值去了吗?因子之间正交了吗?时序规律处理了吗?

把这四步走完,你的因子质量至少提升一个档次。

专注资料整理