这里按横截面因子检验的常见场景,分析说明常用的因子分析指标。
如IC、Rank IC、尾部价差、符号稳定性指标,并尝试进行示例验证。
核心是每个调仓期
,对股票池内每只股票
有因子值
,以及未来一期收益
。
需要先做横截面计算,再在时间序列上汇总。
1 概念分析
1 概念对比
1)线性 IC
线性 IC指标因子值与未来收益的线性相关程度,核心含义是Pearson 相关系数。
优点是直观、可解释,缺点是受异常值影响大;只捕捉线性关系。
2)Rank IC
Rank IC指标计算因子排序与收益排序的相关程度,相比线形IC,这里采用Spearman 秩相关。
优点是对异常值稳健;捕捉单调关系,缺点是忽略收益幅度;尾部信息不直接。
3)尾部价差
尾部价差指标计算因子最高组与最低组的未来收益差,为Top 组平均收益-Bottom 组平均收益。
优点是直接对应多空组合;反映尾部区分度,缺点是样本少、噪声大;受分组数和加权方式影响。
4)符号稳定性指标
符号稳定性指标计算因子预测方向在时间上是否稳定名,
即IC正比例、与均值同号比例、滚动窗口胜率等。
优点是避免平均 IC高但靠少数期的假象,缺点是定义多样;样本长度影响大。
1.2 精简解释
线性 IC:因子和收益是否同涨同跌。
Rank IC:因子排名靠前的股票,收益排名是否也靠前。
尾部价差:最好的一组是否显著跑赢最差的一组。
符号稳定性:这个预测方向是不是经常有效,而不是偶尔有效。
2. 计算过程
2.1 线性 IC
每个横截面:
时间序列汇总:
2.2 Rank IC
先对因子值和未来收益分别求横截面排名:
然后计算 Spearman 相关:
无并列值时也可用:
其中是因子排名与收益排名之差。
2.3 尾部价差
按因子值从低到高排序,分成若干组。
常用 Top 10%、Top 20% 或 Top 30%。
每期:
汇总:
如果因子越大越好,则看Top - Bottom;
如果因子越小越好,则看 Bottom - Top。
2.4 符号稳定性
常见定义:
1)若预期因子方向为正:
2)与全样本 IC 均值同号:
3)滚动窗口胜率:
也可以统计正负切换频率、平均游程长度。符号稳定性高,说明因子方向更可靠。
3 分析示例
3.1 单期示例
这里简单示例线性 IC、Rank IC、尾部价差
假设某期有 5 只股票:
| 股票 | 因子值 f | 下期收益 r |
|---|---|---|
| A | 1 | 2% |
| B | 2 | 1% |
| C | 3 | 4% |
| D | 4 | 3% |
| E | 5 | 6% |
1)线性 IC
说明因子与未来收益有较强正线性相关。
2)Rank IC
因子排名:
收益排名:
对应收益排名为:
排名差平方和:
线性 IC 约 0.822,Rank IC 约 0.8,两者接近,说明关系较单调,且不是极端值单独驱动。
3)尾部价差
按因子排序:
低因子组 Bottom 40%:A、B,平均收益
高因子组 Top 40%:D、E,平均收益
如果按 Top 20% 和 Bottom 20%:
Top 20%:E,收益 6%
Bottom 20%:A,收益 2%
说明高因子组明显跑赢低因子组,尾部区分度较好。
3.2 多期示例
多期示例主要展示符号稳定性。
假设已经得到 12 期线性 IC:
计算:
正 IC 期数:
因此若预期因子方向为正,符号稳定性约为:
样本标准差约:
解读如下
平均 IC 为正,ICIR 约 0.8,t 值约 2.75,说明整体有一定正向预测能力。
正 IC 比例 66.7%,符号稳定性中等,说明方向不是每期都稳定。
如果尾部价差也长期为正,且胜率较高,则因子更可信。
如果 IC 均值高但符号稳定性低,可能是少数几期大 IC 拉高了均值,需要警惕。
3.3 Python伪代码
以下是计算过程所用的python示例代码
import numpy as np
import pandas as pd
from scipy.stats import pearsonr, spearmanr
def single_period_metrics(df, factor_col='factor', ret_col='ret', q=0.2):
df = df.dropna(subset=[factor_col, ret_col]).copy()
# 线性 IC
ic = pearsonr(df[factor_col], df[ret_col])[0]
# Rank IC
rank_ic = spearmanr(df[factor_col], df[ret_col])[0]
# 尾部价差
df = df.sort_values(factor_col)
n = len(df)
k = max(1, int(n * q))
bottom_ret = df.head(k)[ret_col].mean()
top_ret = df.tail(k)[ret_col].mean()
tail_spread = top_ret - bottom_ret
return ic, rank_ic, tail_spread
# 时间序列汇总
ic_series = np.array([...]) # 每期 IC
mean_ic = ic_series.mean()
std_ic = ic_series.std()
icir = mean_ic / std_ic
t_stat = icir * np.sqrt(len(ic_series))
sign_stability = (np.sign(ic_series) == np.sign(mean_ic)).mean()
positive_rate = (ic_series > 0).mean()
分析时需要注意一些问题。
1)未来收益必须对齐到,避免前视偏差。
2)因子通常先做去极值、标准化、行业市值中性化。
3)线性 IC 和 Rank IC 都是每期横截面计算,再在时间序列上求均值、ICIR、t 值、胜率。
4)尾部价差要明确分组:Top/Bottom 10%、20% 还是 30%,等权还是市值加权。
5)符号稳定性要明确预期方向:正向因子看 IC > 0 比例,负向因子看 IC < 0 比例。
6)综合判断通常看IC 均值、ICIR、Rank IC、尾部价差、价差胜率、符号稳定性。
单一指标容易误判。