3、特征工程基础:什么是Alpha因子?Qlib内置因子库、自定义因子编写、因子有效性初判
聊到量化选股,有个概念你绕不开——Alpha因子。
说白了,Alpha因子就是能预测股票未来收益的某种信号。它可以是市盈率、动量、换手率,甚至是你从新闻里挖出来的情绪指标。我个人的理解是:因子就是市场规律的数字化投影。你找到的因子越有效,你的选股模型就越能跑赢大盘。
核心观点:Alpha因子 = 能够产生超额收益的预测信号。它不是玄学,是统计学意义上的显著关系。
3.1 什么是Alpha因子?
先讲个故事。我记得刚入行时,有个老交易员跟我说:「小子,你看那些涨停的票,第二天往往还会冲一下。」这就是一个朴素的动量因子。后来我用Qlib回测了一下,发现这个因子在A股市场上确实有统计显著性——当然,前提是你要做好风险调整。
Alpha因子的数学定义其实很简单:
Alpha = 实际收益 - Beta × 市场收益
嗯,这里要注意:Alpha因子不等于Alpha收益。因子是输入,Alpha收益是输出。你构建的因子组合如果能稳定产生正Alpha,那才叫找到了「真因子」。
常见的Alpha因子类型包括:
- 动量因子:过去N天的收益率、乖离率等
- 价值因子:市盈率、市净率、股息率等
- 质量因子:ROE、毛利率、资产负债率等
- 情绪因子:换手率、波动率、资金流向等
- 另类因子:新闻情感、搜索热度、供应链数据等
你想想看,这些因子本质上都是在捕捉市场参与者的行为偏差。比如动量因子利用的是「反应不足」和「羊群效应」,价值因子利用的是「过度反应」和「均值回归」。
3.2 Qlib内置因子库
Qlib最让我喜欢的一点,就是它内置了一套相当完整的因子库。你不用从零开始写,直接调用就行。我个人习惯先用内置因子跑一遍基线,再考虑自定义。
Qlib的因子库主要分为几类:
| 类别 | 因子名称 | 说明 |
|---|---|---|
| 基础因子 | Ref、Mean、Std | 滞后、均值、标准差等基础运算 |
| 动量因子 | ROC、RSI、MACD | 价格动量与反转信号 |
| 波动因子 | ATR、Bollinger | 波动率与通道突破 |
| 量价因子 | VWAP、OBV、MFI | 成交量与价格结合 |
| 财务因子 | PE、PB、ROE | 基本面指标 |
调用方式也很简单:
from qlib.data import D
from qlib.data.dataset import DatasetH
# 加载内置因子
fields = ["Ref($close, 1)", "Mean($volume, 5)", "ROC($close, 20)"]
data = D.features(["sh600519"], fields, start_time="2020-01-01", end_time="2023-12-31")
print(data.head())
你看,三行代码就能拿到贵州茅台的动量因子数据。Qlib的表达式引擎支持类似SQL的语法,你可以组合出各种复杂的因子。
小技巧:我建议你先用 D.list_all_features() 看看Qlib到底支持哪些因子。有时候你想要的因子其实已经内置了,只是你不知道而已。
3.3 自定义因子编写
内置因子虽然方便,但真正赚钱的因子往往是你自己挖出来的。我在项目中遇到过好几次这样的情况:用公开因子跑出来的结果平平无奇,但加上一个自定义的「资金流强度因子」后,夏普比率直接翻倍。
Qlib支持两种自定义因子方式:
- 表达式因子:用Qlib的表达式语法快速构建
- Python因子:用Python代码实现复杂逻辑
先看表达式因子:
# 自定义一个「量价背离因子」
# 价格涨但成交量萎缩 → 看空信号
custom_factor = "If(Greater(ROC($close, 5), 0), -1 * Std($volume, 5), Std($volume, 5))"
data = D.features(["sh600519"], [custom_factor], ...)
再看Python因子——这个更灵活:
from qlib.data.dataset import DatasetH
from qlib.contrib.data.handler import Alpha158
class MyCustomFactor(Alpha158):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def get_feature_config(self):
# 自定义特征计算逻辑
config = {
"group": "custom",
"fields": [
"Ref($close, 1) / $close - 1", # 昨日收益率
"($volume - Mean($volume, 20)) / Std($volume, 20)", # 成交量Z-score
],
}
return config
嗯,这里有个坑要提醒你:自定义因子一定要做数据对齐。我曾经写过一个因子,忘记处理停牌日的数据,结果回测结果异常漂亮——因为因子在停牌日自动填充了前值,产生了未来信息。这种「假因子」在实盘中会让你亏得很惨。
避坑指南:写自定义因子时,务必检查未来函数。一个简单的方法:用因子值去预测未来1天的收益,如果R²超过0.1,大概率是数据泄露了。
3.4 因子有效性初判
因子写好了,怎么判断它是不是「真因子」?我一般用三个维度来初判:
- IC(信息系数):因子值与未来收益的相关系数。IC > 0.05 算及格,> 0.1 算不错。
- Rank IC:排序后的相关系数,对极端值更鲁棒。
- 分组收益:将股票按因子值分成10组,看多空组合的收益曲线。
Qlib提供了现成的分析工具:
from qlib.contrib.report import analysis_model, analysis_position
from qlib.data.dataset import DatasetH
# 计算IC序列
ic_series = analysis_model.model_ic(model, dataset)
print(f"Mean IC: {ic_series.mean():.4f}")
print(f"IC IR: {ic_series.mean() / ic_series.std():.4f}")
# 分组收益分析
report = analysis_position.report(dataset, model)
print(report.group_return) # 打印各组累计收益
我个人习惯先看分组收益图。如果第1组(因子值最大)和第10组(因子值最小)的收益曲线明显分离,且多空组合稳定向上,那这个因子就值得深入挖掘。
你想想看,一个有效的因子应该满足什么条件?
- 显著性:IC的t统计量 > 2
- 稳定性:IC的标准差小,IR(IC/IC_std)> 0.5
- 单调性:分组收益从第1组到第10组单调递减或递增
如果这三个条件都满足,恭喜你,你找到了一个不错的Alpha因子。但别高兴太早——单因子在实盘中往往表现不佳,因为市场风格会切换。真正赚钱的是多因子组合,这个我们后面章节会详细讲。
核心总结:因子有效性初判 = IC显著性 + 稳定性 + 单调性。三者缺一不可。
本章知识体系
下面这张图帮你梳理了本章的核心逻辑:
这张图把本章的核心逻辑串起来了:从Alpha因子的定义出发,到Qlib内置因子库的调用,再到自定义因子的两种写法,最后用IC和分组收益来验证因子有效性。你跟着这个路径走,基本不会迷路。