IC Analysis: How to Measure Whether Your Factor Actually Predicts
IC analysis is the primary tool for evaluating factor quality. Here's how to compute it, interpret it, and avoid the common mistakes.
You’ve built an alpha factor. You backtested it and the long-short portfolio returns 18% annually with 1.4 Sharpe. Before you allocate capital, you need to answer one question: is this factor actually predicting future returns, or did you just get lucky in your backtest period?
IC analysis is how you answer that question rigorously.
What Is IC?
IC (Information Coefficient) measures the correlation between your factor’s value at time t and the asset’s realized return from t to t+1.
For a factor to be useful, you want:
- IC consistently positive across time
- IC statistically significant (t-stat > 2.0)
- IC stable across market regimes
Pearson IC measures linear correlation. Spearman (rank) IC measures monotone correlation. Rank IC is more robust to outliers — use it as your primary metric.
Computing IC in Python
import numpy as np
import pandas as pd
from scipy import stats
def compute_ic(factor_values, returns, method='spearman'):
"""
Compute IC between factor values and next-period returns.
Parameters
----------
factor_values : DataFrame (date × asset)
Factor values at each date for each asset
returns : DataFrame (date × asset)
Realized returns from t to t+1 for each asset
method : 'pearson' or 'spearman'
Returns
-------
ic_series : Series
IC at each date
mean_ic : float
Mean IC across all dates
t_stat : float
t-statistic of mean IC
"""
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_series, mean_ic, t_stat
def compute_rolling_ic(factor_values, returns, window=60, method='spearman'):
"""
Compute rolling IC with a trailing window.
"""
ic_series, mean_ic, t_stat = compute_ic(factor_values, returns, method)
rolling_ic = ic_series.rolling(window).mean()
return rolling_ic, mean_ic, t_stat
How to Interpret IC
| IC Range | Interpretation |
|---|---|
| IC < 0.01 | Weak — probably not economically significant |
| IC 0.01–0.03 | Moderate — can work with sufficient turnover and diversification |
| IC 0.03–0.05 | Strong — genuine predictive signal |
| IC > 0.05 | Very strong — either a great factor or look-ahead bias |
Sustained IC is what matters. A factor with IC = 0.05 in one year and IC = 0.00 the next year is not reliable. You want consistent IC across multiple years.
The t-Statistic Is More Important Than IC Itself
IC = 0.03 sounds decent. But if the t-statistic is 1.2, it’s not statistically significant — it could easily be noise.
A useful rule: require t-stat > 2.0 for mean IC. This means the probability of observing this IC by chance under the null hypothesis (true IC = 0) is less than 5%.
For a factor to be practically useful, you want:
- Mean rank IC > 0.02
- t-stat of mean IC > 2.0
- IC positive in > 55% of periods (more than half)
- IC stable — no monotonic decay over time
Common Pitfalls
Only looking at average IC. A factor with mean IC = 0.04 but IC = 0.08 in 2018-2020 and IC = 0.00 in 2021-2024 is regime-dependent. Plot rolling IC to see this.
Ignoring IC volatility. A factor with IC = 0.05 but std(IC) = 0.08 is less reliable than one with IC = 0.04 and std(IC) = 0.03. The signal-to-noise ratio matters.
Using in-sample IC to justify out-of-sample allocation. If you optimized your factor on 2015-2020 data and report IC on that same period, you’re showing in-sample IC. Out-of-sample IC (computed on 2021-2024 data) is what matters for real allocation.
Confusing correlation with causation. A factor that correlates with returns doesn’t necessarily predict them causally. The correlation might be spurious or driven by a confounding variable.
IC Decay Over Time
Even good factors decay. A factor with IC = 0.05 in 2010 might have IC = 0.02 in 2020 as more quant funds trade the same signal. Factor decay is normal — the question is whether the factor remains economically viable after transaction costs.
Plot IC over rolling 6-month or 12-month windows. If you see monotonic decay over 3+ years, the factor is being arbitraged. If IC plateaus at a lower level, the factor has reached an equilibrium.
Where It Fits
IC analysis is the foundation of factor evaluation. Before adding any factor to a portfolio, you need to establish that it has statistically significant, stable IC. Factor decay studies how IC changes over different horizons. Cross-sectional stability checks whether IC is consistent across different market regimes.
References
- López de Prado, Advances in Financial Machine Learning, Ch. 3. Wiley, 2018. ISBN: 978-1-119-48208-6. -ISLR Ch. 2 (simple linear regression foundations).
- Ang, Asset Management, Ch. 9. Oxford University Press, 2014. ISBN: 978-0-19-995932-3.
- Green, Hand, Zhang, “The Characteristics That Provide Independent Information,” Review of Financial Studies, 2013.