第四章:因子挖掘基础

因子挖掘,说白了就是量化策略的「找矿」环节。我做了这么多年量化,见过太多人一上来就堆代码、跑回测,结果策略上线就崩。为什么?因为因子没选好,地基就不稳。

今天咱们就聊聊因子到底是什么,怎么分类,以及怎么搭建一个靠谱的单因子测试框架。嗯,这部分内容,我个人觉得是整个量化流程里最容易被低估的一环。

一、什么是因子?

因子,你可以理解成「能解释股票收益的某种特征」。比如市盈率低是不是更容易涨?换手率高是不是代表资金关注?这些特征就是因子。

更学术一点说,因子是资产定价模型中的自变量。经典的Fama-French三因子模型里,市值、账面市值比、市场超额收益就是三个因子。但在公募量化里,我们用的因子要丰富得多。

我习惯把因子比作「选股的筛子」。每个筛子能筛出不同特点的股票,多个筛子叠在一起,就能找到我们想要的标的。

核心要点:因子必须满足三个条件——可量化、可复现、有经济含义。缺一不可。

二、因子的分类

因子分类方式很多,我按最常见的三类来讲:基本面因子、技术面因子、另类因子。

1. 基本面因子

这类因子来自公司财报和经营数据。比如市盈率、市净率、ROE、营收增长率、资产负债率等等。

我在项目中遇到过一个问题:很多人直接用原始财报数据做因子,结果回测效果很好,实盘却一塌糊涂。为什么?因为财报有滞后性。你看到的Q2数据,可能已经是两个月前的了。

所以处理基本面因子时,我建议一定要做「时点对齐」。也就是确保你用的数据,在回测时点上是真实可得的。

因子名称 计算方式 常见方向
市盈率倒数(EP) 净利润 / 总市值 正向(越高越好)
ROE 净利润 / 净资产 正向
营收增长率 (本期营收 - 上期营收)/ 上期营收 正向
资产负债率 总负债 / 总资产 负向(越低越好)

2. 技术面因子

技术面因子来自量价数据。比如动量因子、反转因子、波动率因子、换手率因子等。

这类因子有个特点:更新频率高,每天都能算。但也容易过拟合。我记得有一次,我团队里一个小伙伴发现了一个「神奇」的因子——过去5天涨幅的平方。回测收益高得离谱,但仔细一看,纯粹是数据挖掘出来的噪音。

技术面因子我建议重点关注两个方向:

  • 动量/反转:A股市场短期反转效应明显,中期动量也存在
  • 波动率:低波动率股票长期有超额收益,这个在A股也成立

小技巧:技术面因子一定要做「滞后处理」。用今天的因子预测明天的收益,而不是用今天的因子解释今天的收益。这个坑我踩过,说出来都是泪。

3. 另类因子

另类因子就是「非传统数据」衍生出来的因子。比如舆情因子、搜索热度、供应链数据、卫星图像等。

公募量化里,另类因子用得越来越多。我见过有人用招聘网站的数据来预测公司业绩——如果一家公司突然大量招人,说明业务在扩张。这个逻辑说得通,但数据清洗的难度也大。

另类因子的核心难点不在因子本身,而在数据获取和清洗。我曾经花了两周时间处理一份舆情数据,最后发现数据源本身就有偏差。嗯,从那以后我养成了一个习惯:先用小样本验证数据质量,再大规模使用。

三、单因子测试框架搭建

因子挖出来了,怎么知道它有没有用?这就需要单因子测试框架。说白了,就是给每个因子「体检」。

我搭建框架的思路是这样的:

  1. 数据准备:股票池、因子值、收益数据
  2. 因子处理:去极值、标准化、中性化
  3. 分组回测:按因子值分组,看各组收益
  4. 评价指标:IC、IR、分组收益、多空收益

下面是一个简化的单因子测试框架代码示例:

import pandas as pd
import numpy as np

def single_factor_test(factor_df, return_df, groups=10):
    """
    单因子测试框架
    factor_df: 因子值,index为日期,columns为股票代码
    return_df: 收益数据,index为日期,columns为股票代码
    """
    results = {}
    
    for date in factor_df.index:
        # 获取当日因子值
        factor = factor_df.loc[date].dropna()
        # 获取次日收益
        returns = return_df.shift(-1).loc[date]
        
        # 分组
        factor_rank = factor.rank(pct=True)
        factor_group = pd.qcut(factor_rank, groups, labels=False)
        
        # 计算各组收益
        group_returns = returns.groupby(factor_group).mean()
        results[date] = group_returns
    
    result_df = pd.DataFrame(results).T
    return result_df

这个框架虽然简单,但核心逻辑都在了。实际项目中,我还会加入:

  • 市值中性化处理(防止因子选到大市值股票)
  • 行业中性化处理(防止因子选到特定行业)
  • 换手率约束(考虑交易成本)

注意:单因子测试最容易犯的错误是「幸存者偏差」。一定要用全样本数据,包括已经退市的股票。否则你的回测结果会虚高,实盘直接打脸。

四、因子测试的核心指标

因子好不好,不能光看收益。我一般看这几个指标:

指标 含义 合格标准
IC(信息系数) 因子值与未来收益的相关系数 绝对值 > 0.02
IR(信息比率) IC均值 / IC标准差 > 0.5
分组单调性 各组收益是否单调递增/递减 单调性明显
多空收益 最高组 - 最低组的收益 显著为正

我个人最看重的是IR。为什么?因为IC高但波动大,说明因子不稳定,今天有用明天就没用。IR综合考虑了IC的稳定性和大小,更能反映因子的真实质量。

我曾经见过一个因子,IC高达0.08,但IR只有0.2。回测曲线看着漂亮,但实盘三个月就失效了。原因就是IC波动太大,运气成分居多。

五、框架搭建的避坑指南

最后分享几个我踩过的坑:

  • 未来函数:我曾经用当天的收盘价计算因子,然后用当天的收益做回测。结果因子和收益天然相关,回测曲线完美,实盘一塌糊涂。记住:因子数据必须滞后于收益数据。
  • 过拟合:因子参数不要调太多。比如均线因子,5日均线和10日均线选哪个?都试试,哪个好选哪个。但如果你试了3日、5日、7日、10日、15日...总有一个能拟合出好结果。这就是过拟合。
  • 数据质量:因子值出现极端值怎么办?我习惯用MAD法去极值,然后用z-score标准化。不要直接删除极端值,因为极端值可能包含重要信息。

总结一下:因子挖掘不是玄学,是科学。好的因子要有逻辑支撑、有统计显著性、有稳定性。单因子测试框架就是帮你验证这些的工具。别嫌麻烦,这一步做扎实了,后面的策略开发才能事半功倍。

单因子测试框架流程图 数据准备 因子处理(去极值/标准化) 分组回测 评价指标(IC/IR/分组收益) 是否有效? 纳入因子库 重新挖掘 股票池 因子值 收益数据 MAD去极值 z-score标准化 按因子值分组 计算各组收益 IC > 0.02 IR > 0.5

好了,因子挖掘的基础就聊到这儿。记住一句话:因子是策略的基石,框架是验证的工具。这两样东西搞明白了,后面的路就好走了。

专注资料整理