单因子检验框架:IC分析与分组回测
因子有效性检验,说白了就是回答一个问题:这个因子到底能不能赚钱?
我做了这么多年量化,见过太多漂亮的因子曲线,回测时美如画,实盘时惨如狗。为什么?因为检验框架没搭对。今天我们就来聊聊单因子检验的核心三板斧:IC分析、分组回测、因子收益率计算。
一、IC分析:因子与收益的相关性度量
IC(Information Coefficient)是衡量因子预测能力的核心指标。它回答的是:因子值的高低,跟未来收益的大小,有没有关系?
我个人习惯把IC分成三种,每种适用场景不同:
1. Pearson IC
这是最原始的IC,直接计算因子值与未来收益的皮尔逊相关系数。
import numpy as np
import pandas as pd
from scipy.stats import pearsonr
def calc_pearson_ic(factor_values, forward_returns):
"""
计算Pearson IC
factor_values: 因子值序列
forward_returns: 未来收益序列
"""
ic, p_value = pearsonr(factor_values, forward_returns)
return ic, p_value
嗯,这里要注意:Pearson IC假设因子和收益是线性关系。我在项目中遇到过一个问题——因子值有极端值,Pearson IC直接被带偏了。所以后来我很少单独用Pearson IC。
2. Spearman IC
Spearman IC用的是秩相关系数。说白了,就是把因子值和收益都排个序,然后看排序的相关性。
from scipy.stats import spearmanr
def calc_spearman_ic(factor_values, forward_returns):
"""
计算Spearman IC
"""
ic, p_value = spearmanr(factor_values, forward_returns)
return ic, p_value
为什么用Spearman?因为它对极端值不敏感。你想想看,一个股票因子值特别大,但收益一般,Pearson IC会认为这是异常,而Spearman IC只看排名,影响小得多。
3. Rank IC
Rank IC其实跟Spearman IC本质一样,但计算方式略有不同。它先对因子值和收益分别做标准化处理(比如转为百分位排名),再计算相关系数。
def calc_rank_ic(factor_values, forward_returns):
"""
计算Rank IC
"""
# 转为百分位排名
factor_rank = factor_values.rank(pct=True)
return_rank = forward_returns.rank(pct=True)
ic, p_value = pearsonr(factor_rank, return_rank)
return ic, p_value
二、分组回测:验证因子的单调性
IC分析告诉你因子和收益有没有关系,但没告诉你关系是不是单调的。什么叫单调?就是因子值越高,收益越好(或者越差)。
分组回测就是干这个的。
1. 分位数分组
最常见的做法是把股票按因子值分成5组或10组,然后看每组的表现。
def quantile_group_backtest(df, factor_col, return_col, n_groups=5):
"""
分位数分组回测
df: 包含因子值和未来收益的DataFrame
"""
# 按因子值分组
df['group'] = pd.qcut(df[factor_col], n_groups, labels=False)
# 计算每组平均收益
group_returns = df.groupby('group')[return_col].mean()
# 计算多空组合收益(最高组 - 最低组)
long_short_return = group_returns.iloc[-1] - group_returns.iloc[0]
return group_returns, long_short_return
我曾经犯过一个错误:直接用等宽分组而不是分位数分组。结果因子值分布不均匀,有一组只有几只股票,另一组几百只。后来改成qcut分位数分组,问题就解决了。
2. 多空组合
多空组合是分组回测的精华。它做多因子值最高的组,做空因子值最低的组,看看能不能稳定赚钱。
为什么多空组合重要?因为它能剔除市场整体走势的影响。你想想看,如果市场涨了20%,所有组都赚钱,那因子到底有没有用?多空组合告诉你:去掉市场beta之后,因子还能不能产生alpha。
- 各组收益是否单调递增/递减
- 多空组合收益是否显著为正
- 多空组合的夏普比率是否大于1
三、因子收益率计算
因子收益率,也叫因子溢价,是衡量因子能带来多少超额收益的指标。计算方式主要有两种:
1. 简单多空收益
就是最高组收益减去最低组收益。简单粗暴,但有效。
def factor_return_simple(group_returns):
"""
简单因子收益率计算
"""
return group_returns.iloc[-1] - group_returns.iloc[0]
2. 回归法因子收益率
更严谨的做法是用横截面回归。把因子值作为自变量,未来收益作为因变量,回归系数就是因子收益率。
import statsmodels.api as sm
def factor_return_regression(factor_values, forward_returns):
"""
回归法计算因子收益率
"""
X = sm.add_constant(factor_values)
model = sm.OLS(forward_returns, X).fit()
# 因子收益率就是回归系数
factor_return = model.params.iloc[1]
t_stat = model.tvalues.iloc[1]
return factor_return, t_stat
四、知识体系总览
下面这张图总结了单因子检验的完整框架:
五、实战中的注意事项
最后分享几个我踩过的坑:
- IC的时序稳定性:单期IC高不代表因子好。我习惯看IC的时序图,如果IC忽正忽负,那因子大概率是噪音。
- 分组数量要合理:5组是标配,但如果你股票池只有100只,分10组就没意义了。每组至少要有20只股票。
- 多空组合要扣成本:很多因子回测收益很高,但换手率也高。扣掉交易成本后,收益可能就没了。
- 不要只看均值:分组回测的收益均值很重要,但收益的波动率同样重要。一个高收益高波动的因子,实盘很难拿住。
好了,单因子检验框架就聊到这里。记住:IC分析看相关性,分组回测看单调性,因子收益率看赚钱能力。这三板斧用好了,大部分因子的好坏你都能判断个八九不离十。
公众号:蓝海数据掘金营,微信deep3321