4、单因子测试框架:IC分析、IR分析、分组回测、多空组合收益

单因子测试,说白了就是给每个候选因子做「体检」。

我入行那会儿,以为找个好因子就能躺赚。结果呢?回测曲线漂亮得不行,实盘一跑就崩。后来才明白——因子测试不是走过场,是帮你排雷的。

这一章,咱们把四个核心测试工具讲透:IC分析、IR分析、分组回测、多空组合收益。嗯,一个一个来。

4.1 IC分析:因子和收益的相关性

IC(Information Coefficient),信息系数。衡量的是因子值跟未来收益之间的相关性。

简单说:因子值高的股票,未来是不是涨得更好?

IC的两种常见计算方式:
  • Spearman秩相关系数:看排名相关性,对极端值不敏感。我个人更常用这个。
  • Pearson相关系数:看线性相关性,但容易被极端值带偏。

我在项目中遇到过一件事:某个因子Pearson IC高达0.12,但Spearman IC只有0.03。一查,原来是某只小盘股因子值异常高,把相关性拉上去了。去掉它,啥也不是。

import pandas as pd
import scipy.stats as stats

# 假设 factor_values 是因子值,forward_returns 是未来N日收益
def calc_ic(factor_values, forward_returns, method='spearman'):
    if method == 'spearman':
        ic, p_value = stats.spearmanr(factor_values, forward_returns)
    else:
        ic, p_value = stats.pearsonr(factor_values, forward_returns)
    return ic, p_value

# 示例
ic_val, p_val = calc_ic(df['factor'], df['ret_5d'])
print(f'IC: {ic_val:.4f}, p-value: {p_val:.4f}')
我的习惯:IC的p-value一定要看。IC再高,p-value大于0.05,基本就是噪音。别被漂亮数字骗了。

4.2 IR分析:IC的稳定性比大小更重要

IR(Information Ratio),信息比率。公式很简单:IR = mean(IC) / std(IC)。

说白了,就是IC的「均值」除以「波动率」。你想想看,一个因子IC均值0.08,但波动率0.15,IR才0.53。另一个因子IC均值0.05,波动率0.03,IR高达1.67。哪个更靠谱?

我曾经踩过一个坑:某个因子IC均值0.10,看着不错。但IR只有0.3,因为IC时正时负,波动极大。实盘一跑,收益曲线跟过山车似的。后来我给自己定了个规矩:IR低于0.5的因子,直接pass。

指标 因子A 因子B 因子C
IC均值 0.08 0.05 0.12
IC标准差 0.15 0.03 0.25
IR 0.53 1.67 0.48
结论 一般 优秀 不稳定,慎用
注意:IR高不代表因子一定好。如果IC均值是0.01,标准差0.001,IR=10,但实际预测能力极弱。所以IR要结合IC绝对值一起看。

4.3 分组回测:看因子能不能分层

分组回测,就是把股票按因子值从大到小分成N组(通常是5组或10组),然后看每组未来的平均收益。

好的因子,应该能清晰分层:第1组收益最高,第5组收益最低,中间组依次排列。

我记得有一次测试一个「营收增长率」因子,分组结果出来,第1组和第5组收益差不多,反而是第3组收益最高。这说明什么?这个因子跟收益不是线性关系,可能是个「倒U型」。嗯,这种因子用起来要小心。

def group_backtest(df, factor_col, ret_col, n_groups=5):
    # 按因子值分组
    df['group'] = pd.qcut(df[factor_col], n_groups, labels=False)
    # 计算每组平均收益
    group_returns = df.groupby('group')[ret_col].mean()
    return group_returns

# 示例
group_ret = group_backtest(df, 'factor', 'ret_20d', 5)
print(group_ret)
分组回测的检查清单:
  • 各组收益是否单调递增/递减?
  • 第1组和第N组的收益差是否显著?
  • 中间组有没有「异常凸起」?
  • 不同时间段(牛市/熊市)分组效果是否稳定?

4.4 多空组合收益:最直接的赚钱检验

多空组合,就是做多第1组(因子值最高的),做空第N组(因子值最低的)。

这个指标最直观——如果多空组合能稳定赚钱,说明因子确实有区分能力。

我习惯把多空组合的累计收益曲线画出来。如果曲线平稳向上,回撤小,那这个因子基本靠谱。如果曲线大起大落,甚至长期横盘,那就要打个问号了。

def long_short_return(df, factor_col, ret_col, n_groups=5):
    df['group'] = pd.qcut(df[factor_col], n_groups, labels=False)
    # 做多第1组,做空第5组
    long = df[df['group'] == 0][ret_col].mean()
    short = df[df['group'] == n_groups-1][ret_col].mean()
    return long - short

# 示例
ls_ret = long_short_return(df, 'factor', 'ret_20d', 5)
print(f'多空组合收益: {ls_ret:.4f}')
避坑指南:我曾经发现一个因子多空收益很高,但仔细一看,收益主要来自空头端。也就是说,这个因子擅长「找烂股票」,而不是「找好股票」。这种因子在融券受限的市场里,实用性大打折扣。

4.5 知识体系总览

下面这张图,是我自己整理的单因子测试框架。每次做因子测试前,我都会瞄一眼,确保没漏掉哪个环节。

单因子测试框架 候选因子 IC分析 相关性检验 IR分析 稳定性检验 分组回测 分层效果 多空组合收益 赚钱能力 因子通过/淘汰决策 四个维度缺一不可,综合判断才能选出真正有效的因子 💡 我个人习惯:IC > 0.05 且 IR > 0.5 且分组单调,才考虑纳入因子库 单因子测试是因子筛选的第一道关卡,宁可错过,不可做错

4.6 四个指标怎么配合使用?

我个人的筛选流程是这样的:

  1. 先看IC:IC均值有没有超过0.05?p-value是否显著?不满足直接淘汰。
  2. 再看IR:IR有没有超过0.5?IC的稳定性如何?波动太大也不行。
  3. 分组回测:收益是否单调?第1组和第5组差距是否明显?
  4. 多空组合:累计收益曲线是否平稳?最大回撤是否可控?

四个维度都过了,这个因子才算「初步合格」。为什么说初步?因为还有后续的因子相关性分析、因子合成、样本外测试等等。嗯,那是后面章节的事了。

最后提醒一句:单因子测试只是筛选工具,不是圣杯。我见过太多人在这一步过度优化,结果样本外一测就崩。保持简单,保持稳健,才是长久之道。

专注资料整理