4、因子计算与处理:从原始数据到有效信号

好,我们进入第四章。这一章,说白了就是讲怎么把原始数据变成能用的因子信号。

我个人觉得,因子处理是整个策略开发里最容易被低估的环节。很多人花大把时间找因子,结果处理得马马虎虎,最后回测一塌糊涂。嗯,这里要注意,因子计算只是第一步,后面的标准化、中性化、正交化,才是真正拉开差距的地方。

4.1 常见因子计算:四大类因子

我习惯把因子分成四类:估值、动量、质量、情绪。这四类基本覆盖了市场的主要驱动逻辑。

4.1.1 估值因子

估值因子,说白了就是看股票贵不贵。常用的有:

  • PE(市盈率):市值 / 净利润。越低越便宜。
  • PB(市净率):市值 / 净资产。适合银行、周期股。
  • PS(市销率):市值 / 营业收入。适合亏损但营收高的公司。
  • PCF(市现率):市值 / 经营现金流。现金流为王。

我在项目中遇到过一个问题:有些公司净利润是负的,PE算出来是负数。这时候直接拿负数去排序,逻辑上就乱了。我的做法是:负PE统一赋一个很大的正数,或者干脆剔除。

核心逻辑:估值因子在A股市场长期有效,但要注意行业差异。银行股PE普遍低,科技股PE普遍高,跨行业比较时要小心。

4.1.2 动量因子

动量因子,就是看股票过去涨跌的趋势。你想想看,涨的股票会不会继续涨?跌的会不会继续跌?

  • 过去N日收益率:比如过去20日、60日、120日的累计收益。
  • 过去N日波动率:波动率低的股票,动量更稳定。
  • RSI(相对强弱指标):衡量近期涨跌力度。
  • 均线乖离率:当前价格偏离均线的程度。

我曾经踩过一个坑:用过去5日的收益率做动量,结果发现换手率极高,交易成本吃掉所有收益。后来我改成20日动量,效果就好多了。所以,动量因子的窗口期选择,直接影响策略的实用性

避坑指南:我曾经在回测中用了未来数据——用当天的收盘价计算动量因子,然后预测当天的收益。这显然是错的。记住:因子计算必须使用历史数据,不能包含未来信息

4.1.3 质量因子

质量因子,看的是公司基本面好不好。好公司,长期来看更容易跑赢。

  • ROE(净资产收益率):净利润 / 净资产。越高越好。
  • 毛利率:毛利 / 营业收入。反映定价能力。
  • 资产负债率:总负债 / 总资产。越低越安全。
  • 营收增长率:同比营收增长。成长性的体现。

我个人习惯把ROE和营收增长率结合起来用。ROE高但营收不增长,可能是靠财务杠杆撑起来的,风险大。两者都高,才是真正的优质公司。

4.1.4 情绪因子

情绪因子,反映的是市场参与者的心理状态。这个比较有意思。

  • 换手率:交易活跃度。换手率高,说明情绪亢奋。
  • 成交量:绝对成交量。放量上涨是好事,放量下跌要小心。
  • 融资余额变化:杠杆资金的进出。
  • 北向资金净流入:外资的动向。

我记得有一次,某只股票连续三天涨停,换手率超过20%。很多人觉得还能追,但我一看情绪因子已经到极端值了,果断避开。结果第二天就跌停了。情绪因子,说白了就是物极必反

4.2 因子标准化:让不同因子站在同一起跑线

因子计算出来后,你会发现它们的量纲完全不同。PE可能是几十,换手率可能是百分之几,收益率可能是小数。直接把这些因子放在一起用,量纲大的因子会主导结果。所以,我们需要标准化。

4.2.1 Z-score标准化

Z-score,就是把因子值减去均值,再除以标准差。公式很简单:

Z = (X - mean(X)) / std(X)

标准化之后,因子值的均值为0,标准差为1。这样,不同因子之间就可以直接比较了。

我在项目中遇到过一个问题:如果因子值有极端异常值,Z-score会被严重拉偏。比如某只股票PE是1000,其他都是20左右,那Z-score算出来,这只股票会变成一个巨大的异常点。这时候,我建议先做缩尾处理,把极端值拉回到合理范围。

小技巧:缩尾处理一般用1%和99%分位数。把小于1%分位数的值设为1%分位数,大于99%分位数的值设为99%分位数。这样既保留了信息,又避免了极端值干扰。

4.2.2 Rank标准化

Rank标准化,就是把因子值转换成排名,然后除以总样本数,得到0到1之间的值。公式:

Rank = (因子排名) / (总样本数)

Rank标准化的好处是:对异常值不敏感。不管因子值多大或多小,排名只取决于相对位置。我个人比较喜欢用Rank,尤其是在因子值分布不均匀的时候。

举个例子:某因子90%的股票值都在0到1之间,但10%的股票值在100以上。用Z-score,那10%的股票会严重扭曲结果。用Rank,大家各安其位,互不影响。

4.3 因子中性化处理:剔除干扰因素

因子中性化,说白了就是剔除一些你不想要的系统性影响。最常见的两个中性化对象是:市值行业

你想想看,小市值股票的换手率天然就比大市值股票高。如果你直接用换手率作为因子,那选出来的全是小市值股票。这不是因为换手率本身有效,而是因为市值的影响。所以,我们需要对市值做中性化处理。

具体做法:

  1. 把因子值作为因变量,市值(或行业虚拟变量)作为自变量,做线性回归。
  2. 取回归的残差作为中性化后的因子值。

公式:

Factor_raw = a + b * MarketCap + e
Factor_neutral = e

这样,中性化后的因子值就剔除了市值的影响。行业中性化同理,用行业虚拟变量做回归即可。

重要提醒:中性化处理不是万能的。如果因子本身和市值高度相关,中性化后因子可能变得很弱。这时候,你需要思考:这个因子到底有没有独立于市值的预测能力?

4.4 因子正交化:消除因子间的共线性

因子正交化,是更高级的处理方式。当你有多个因子时,它们之间可能存在相关性。比如,动量因子和质量因子可能有一定正相关。如果不做处理,多因子模型会出现多重共线性问题,导致结果不稳定。

正交化的目标:让所有因子两两之间不相关。常用的方法是施密特正交化(Gram-Schmidt)或PCA主成分分析。

施密特正交化的思路很简单:

  1. 选一个因子作为基准,比如因子1。
  2. 把因子2中与因子1相关的部分剔除掉,剩下的就是正交化后的因子2。
  3. 以此类推,每个新因子都剔除与前面所有因子的相关性。

代码实现(伪代码):

def orthogonalize(factors):
    # factors: 因子矩阵,每列是一个因子
    n = factors.shape[1]
    ortho_factors = np.zeros_like(factors)
    ortho_factors[:, 0] = factors[:, 0]
    for i in range(1, n):
        # 剔除与前面所有因子的相关性
        residual = factors[:, i]
        for j in range(i):
            beta = np.dot(factors[:, i], ortho_factors[:, j]) / np.dot(ortho_factors[:, j], ortho_factors[:, j])
            residual -= beta * ortho_factors[:, j]
        ortho_factors[:, i] = residual
    return ortho_factors

我在项目中用过PCA做正交化。PCA的好处是能自动找到主成分,但缺点是主成分的解释性变差。我个人更倾向于施密特正交化,因为每个因子还能保留一定的经济含义。

避坑指南:我曾经在正交化时,把因子顺序搞反了。先正交化了质量因子,再正交化动量因子。结果发现动量因子的效果被严重削弱。后来我意识到,正交化的顺序会影响结果。一般建议把更重要的因子放在前面。

4.5 本章知识体系

下面这张图,展示了因子计算与处理的完整流程:

因子计算与处理流程 原始数据 因子计算 估值 | 动量 | 质量 | 情绪 因子标准化 Z-score | Rank 因子中性化 市值中性化 | 行业中性化 因子正交化

这张图展示了从原始数据到最终有效因子的完整链条。每一步都有其必要性,跳过任何一步,都可能导致策略效果大打折扣。

4.6 本章小结

因子计算与处理,是量化策略的基石。我见过太多人花90%的时间找因子,只花10%的时间做处理。结果呢?因子之间互相打架,回测曲线漂亮,实盘一塌糊涂。

我个人建议:花50%的时间找因子,花50%的时间做处理。标准化、中性化、正交化,每一步都值得认真对待。尤其是中性化,它能帮你剔除很多隐藏的干扰因素,让因子真正发挥独立预测能力。

嗯,这一章的内容就到这里。记住:好的因子是基础,好的处理是保障。两者缺一不可。


公众号:蓝海资料掘金营,微信deep3321