IC 分析:如何衡量你的因子是否真正有预测力
IC 分析是评估因子质量的主要工具。以下是如何计算、解读和避免常见错误。
你构建了一个 alpha 因子。你回测了它,多空组合年化收益 18%,Sharpe 1.4。在你分配资本之前,你需要回答一个问题:这个因子真的在预测未来收益,还是你只是在回测期幸运?
IC 分析是你严谨回答这个问题的方法。
什么是 IC?
IC(信息系数)测量你的因子在时间 t 的值与资产从 t 到 t+1 的实现收益之间的相关性。
对于有用的因子,你需要:
- IC 在时间内持续为正
- IC 统计显著(t-stat > 2.0)
- IC 在不同市场结构下稳定
Pearson IC 测量线性相关性。Spearman(rank)IC 测量单调相关性。对异常值更稳健——使用它作为主要指标。
在 Python 中计算 IC
import numpy as np
import pandas as pd
from scipy import stats
def compute_ic(factor_values, returns, method='spearman'):
"""
计算因子值与下期收益之间的 IC。
Parameters
----------
factor_values : DataFrame
因子值 (date x asset)
returns : DataFrame
收益 (date x asset)
method : str
'spearman' 或 'pearson'
Returns
-------
ic_df : DataFrame
每日 IC 时间序列
mean_ic : float
平均 IC
t_stat : float
IC 均值的 t 统计量
"""
ic_list = []
dates = factor_values.index
for date in dates[:-1]:
if date not in returns.index:
continue
next_date = returns.index[returns.index.get_loc(date) + 1]
fv = factor_values.loc[date].dropna()
ret = returns.loc[next_date].dropna()
common = fv.index.intersection(ret.index)
if len(common) < 10:
continue
if method == 'spearman':
ic, _ = stats.spearmanr(fv[common], ret[common])
else:
ic, _ = stats.pearsonr(fv[common], ret[common])
ic_list.append({'date': date, 'ic': ic})
ic_df = pd.DataFrame(ic_list).set_index('date')
ic_series = ic_df['ic']
mean_ic = ic_series.mean()
t_stat = mean_ic / (ic_series.std() / np.sqrt(len(ic_series)))
return ic_df, mean_ic, t_stat
def compute_rolling_ic(factor_values, returns, window=60, method='spearman'):
"""
计算滚动窗口 IC。
"""
ic_list = []
dates = factor_values.index
for i in range(window, len(dates) - 1):
window_factors = []
window_returns = []
for date in dates[i-window:i]:
if date not in returns.index:
continue
next_date_idx = returns.index.get_loc(date) + 1
if next_date_idx >= len(returns.index):
continue
next_date = returns.index[next_date_idx]
fv = factor_values.loc[date].dropna()
ret = returns.loc[next_date].dropna()
common = fv.index.intersection(ret.index)
if len(common) > 10:
window_factors.extend(fv[common].values)
window_returns.extend(ret[common].values)
if len(window_factors) > 30:
if method == 'spearman':
ic, _ = stats.spearmanr(window_factors, window_returns)
else:
ic, _ = stats.pearsonr(window_factors, window_returns)
ic_list.append({'date': dates[i], 'ic': ic})
return pd.DataFrame(ic_list).set_index('date')
如何解读 IC
| IC 范围 | 解读 |
|---|---|
| IC < 0.01 | 弱——可能经济上不显著 |
| IC 0.01–0.03 | 中等——配合足够换手率和多元化可能有效 |
| IC 0.03–0.05 | 强——真正的预测信号 |
| IC > 0.05 | 非常强——要么是好因子要么是前视偏差 |
持续的 IC 才是重要的。 在一年内 IC = 0.05 但下一年 IC = 0.00 的因子不可靠。你需要跨多年持续一致的 IC。
t 统计量比 IC 本身更重要
IC = 0.03 听起来不错。但如果 t-statistic 是 1.2,统计上不显著——很可能只是噪声。
有用的规则:要求 mean IC 的 t-stat > 2.0。这意味着在原假设(真实 IC = 0)下,偶然观察到这种 IC 的概率低于 5%。
def test_ic_significance(ic_series, min_t_stat=2.0):
"""
测试 IC 是否统计显著。
"""
n = len(ic_series)
mean_ic = ic_series.mean()
std_ic = ic_series.std()
t_stat = mean_ic / (std_ic / np.sqrt(n))
return {
'mean_ic': mean_ic,
'std_ic': std_ic,
't_stat': t_stat,
'significant': abs(t_stat) > min_t_stat,
'positive_pct': (ic_series > 0).mean()
}
IC 随时间衰减
即使好因子也会衰减。2010 年 IC = 0.05 的因子在 2020 年可能只有 IC = 0.02,因为更多量化基金交易相同信号。因子衰减是正常的——问题是因子在经济上是否仍然可行。
绘制 6 个月或 12 个月滚动窗口的 IC。如果你看到 3 年以上单调衰减,因子正被套利。如果 IC 在较低水平企稳,因子已达到均衡。
IC 在组合构建中的作用
IC 是因子权重的关键输入:
def ic_weighted_portfolio(factor_dict, returns, lookback=252):
"""
按 IC 加权的因子组合。
每个时期的因子权重与该时期的滚动 IC 成正比。
"""
dates = list(factor_dict[list(factor_dict.keys())[0]].index)
factor_names = list(factor_dict.keys())
weights_history = []
for i in range(lookback, len(dates) - 1):
ic_weights = {}
for name in factor_names:
fv = factor_dict[name].iloc[i-lookback:i].dropna()
ret = returns.iloc[i-lookback:i].dropna()
common = fv.index.intersection(ret.index)
if len(common) > 30:
ic, _ = stats.spearmanr(fv[common], ret[common])
ic_weights[name] = max(ic, 0) # 丢弃负 IC
else:
ic_weights[name] = 0
total = sum(ic_weights.values())
if total > 0:
weights = {k: v / total for k, v in ic_weights.items()}
else:
weights = {k: 1/len(factor_names) for k in factor_names}
weights_history.append(weights)
return pd.DataFrame(weights_history, index=dates[lookback:])
常见错误
只看平均 IC。 IC = 0.04 但 2018-2020 年 IC = 0.08、2021-2024 年 IC = 0.00 的因子是结构性依赖的。绘制滚动 IC 来发现这一点。
忽略 IC 波动性。 IC = 0.05 但 std(IC) = 0.08 的因子不如 IC = 0.04 但 std(IC) = 0.03 的因子可靠。信噪比很重要。
用样本内 IC 来论证样本外分配。 如果你在 2015-2020 数据上优化了因子并报告同一时期的 IC,你在展示样本内 IC。在 2021-2024 数据上计算的样本外 IC才对真实分配重要。
只测试单个市场。 在美国股票上测试的因子在日本或欧洲股票上可能完全失效。跨市场 IC 测试是必要的稳健性检查。
在知识体系中的位置
IC 分析是因子评估的基础。在将任何因子加入组合之前,你需要建立它具有统计显著且稳定的 IC。因子 decay 研究 IC 如何随不同时间范围变化。横截面稳定性检查 IC 在不同市场结构下是否一致。
参考文献
- López de Prado, Advances in Financial Machine Learning, 第 3 章. Wiley, 2018. ISBN: 978-1-119-48208-6.
- Ang, Asset Management, 第 9 章. Oxford University Press, 2014. ISBN: 978-0-19-995932-3.