Home/Quant Research/Alpha Signal Research
Back
๐Ÿ”ญ

Quant Research Guide

Alpha Signal Research

Finding, testing, and validating predictive signals without fooling yourself is the core skill of a quant researcher. The tools โ€” IC, ICIR, signal decay, deflated Sharpe โ€” exist specifically to distinguish real edge from statistical noise in a low signal-to-noise environment.

AlphaICICIRSignal DecayWorldQuantFactor Research

Core Theory

  • 1Information Coefficient (IC): the Spearman rank correlation between the signal value at time t and the forward return at t+h. IC ranges from -1 to +1. IC = 0.02 is practically useful in a diversified portfolio; IC > 0.10 is excellent. Use Spearman (rank) not Pearson to be robust to outlier returns.
  • 2IC IR (ICIR): mean(IC) / std(IC) measured over a rolling window. Measures signal consistency over time. ICIR > 0.5 is good; ICIR > 1.0 is exceptional. A signal with IC = 0.04 and ICIR = 0.8 is more valuable than IC = 0.08 and ICIR = 0.3 โ€” consistency compounds.
  • 3Signal decay analysis: compute IC at forward horizons h = 1, 5, 10, 21, 63, 126 trading days. Plot IC vs h. A fast decay (IC โ†’ 0 by day 5) means the signal is best for short-term trading with high rebalancing frequency. Slow decay (still positive at 63 days) means monthly rebalancing suffices.
  • 4Turnover and after-cost IC: the true test of a signal is net IC after costs. Net IC โ‰ˆ Gross IC ร— (1 - Turnover ร— Cost/IC_units). A signal with IC = 0.06 but 400% annual turnover at 10bp costs earns less net than IC = 0.04 with 50% turnover.
  • 5Deflated Sharpe Ratio (Bailey & Lopez de Prado 2014): adjusts the observed Sharpe for selection bias when testing multiple configurations. DSR = SR ร— (1 - ฮณ ร— ln(N)) / โˆšT where N is number of trials. A backtest Sharpe of 2.0 from 100 configurations has DSR โ‰ˆ 0.4 โ€” the strategy is likely noise.
  • 6WorldQuant alpha expression style: a signal expressed as a formula over price/volume/fundamental data, evaluated daily for each stock. Example: -rank(ts_arg_max(close, 5)) โ€” rank the day on which each stock's 5-day high occurred; stocks near their high get low rank (bearish). Must be cross-sectionally neutral, contain no look-ahead, and pass IC tests.
  • 7Signal neutralization: raw signals contain unwanted factor exposures (market beta, sector effects). Neutralize by regressing the signal on sector dummies and market beta, taking residuals. This isolates the stock-specific alpha from broad factor effects โ€” essential before comparing signals with different sector distributions.
  • 8Combinability: the value of a new signal to a portfolio of existing signals depends on its correlation with existing signals. A new signal with IC = 0.04 that is uncorrelated with all existing signals adds more value than IC = 0.06 with high correlation. Compute pairwise IC correlations and use this to guide signal selection.

Key Formulas

01IC: ICt=Spearmanโ€‰Corr(signali,t,โ€‰ri,t+h)IC_t = Spearman\,Corr(signal_{i,t},\, r_{i,t+h}) across stocks i
02ICIR: ICIR=ICห‰/ฯƒICICIR = \bar{IC} / \sigma_{IC}
03IC t-statistic: t=ICห‰ร—T/ฯƒICt = \bar{IC} \times \sqrt{T} / \sigma_{IC}
04Turnover-adjusted alpha: ฮฑnetโ‰ˆICร—ฯƒrโˆ’Turnoverร—Cost\alpha_{net} \approx IC \times \sigma_r - Turnover \times Cost
05Deflated Sharpe: DSRโ‰ˆSRร—(1โˆ’ฮณ^โ‹…lnโกN)/TDSR \approx SR \times (1 - \hat{\gamma}\cdot\ln N) / \sqrt{T}
06Fundamental Law: IR=ICร—BRIR = IC \times \sqrt{BR}
python
1import numpy as np
2import pandas as pd
3from scipy.stats import spearmanr
4
5np.random.seed(42)
6T = 60 # 60 months
7N = 200 # stocks
8
9# --- Simulate a signal with true IC โ‰ˆ 0.05 at 1-month horizon ---
10true_ic = 0.05
11signal = np.random.randn(T, N) # raw signal (cross-sectional)
12noise = np.random.randn(T, N)
13returns = true_ic * signal + np.sqrt(1 - true_ic**2) * noise # returns correlated with signal
14
15# Shift signal by 1 to simulate proper look-ahead prevention
16signal_df = pd.DataFrame(signal)
17return_df = pd.DataFrame(returns)
18
19# --- Monthly IC (Spearman rank correlation each month) ---
20ic_series = pd.Series([
21 spearmanr(signal_df.iloc[t], return_df.iloc[t + 1])[0]
22 for t in range(T - 1)
23])
24
25mean_ic = ic_series.mean()
26std_ic = ic_series.std()
27icir = mean_ic / std_ic
28t_stat = mean_ic * np.sqrt(T - 1) / std_ic
29
30print(f"Mean IC : {mean_ic:.4f}")
31print(f"IC Std : {std_ic:.4f}")
32print(f"ICIR : {icir:.4f}")
33print(f"IC t-stat: {t_stat:.2f} ({'Significant' if abs(t_stat) > 3 else 'Below t=3 threshold'})")
34
35# --- Rolling 24-month ICIR ---
36rolling_icir = ic_series.rolling(24).apply(lambda x: x.mean() / x.std())
37print(f"\nRolling ICIR (last 12m): mean={rolling_icir.tail(12).mean():.3f}")
38
39# --- Signal Decay Table ---
40horizons = [1, 5, 10, 21, 42, 63]
41decay_ics = {}
42
43for h in horizons:
44 ics = []
45 for t in range(T - h):
46 fwd_ret = return_df.iloc[t:t+h].sum() # h-period cumulative return
47 ic, _ = spearmanr(signal_df.iloc[t], fwd_ret)
48 ics.append(ic)
49 decay_ics[h] = np.mean(ics)
50
51print("\nSignal Decay Table:")
52print(f"{'Horizon':>8} | {'IC':>8} | {'% of 1d IC':>10}")
53print("-" * 32)
54for h, ic in decay_ics.items():
55 pct = ic / decay_ics[1] * 100 if decay_ics[1] != 0 else 0
56 print(f"{h:>8}d | {ic:>8.4f} | {pct:>9.1f}%")
57
58# --- Cross-signal correlation (combinability) ---
59signal2 = np.random.randn(T, N) * 0.3 + signal * 0.7 # correlated signal
60ic2 = pd.Series([
61 spearmanr(signal2[t], returns[t + 1])[0]
62 for t in range(T - 1)
63])
64print(f"\nIC correlation between signals: {ic_series.corr(ic2):.3f}")
65print("High IC correlation => low diversification benefit from combining")

The full signal research workflow: monthly Spearman IC computation with proper look-ahead prevention, rolling ICIR for consistency assessment, signal decay table across multiple horizons (which determines optimal rebalancing frequency), and cross-signal IC correlation to assess combinability.

Worked Interview Problems

3 problems

Problem

A researcher presents a signal with mean monthly IC = 0.04, ICIR = 0.6 over 5 years, and IC decay reaching zero at 21 days. Evaluate this signal.

Solution

1

IC significance: t-stat = 0.04 ร— โˆš60 / (0.04/0.6) = 0.04 ร— 7.75 / 0.0667 = 4.65. Significantly above the t = 3 threshold. The IC is real.

2

ICIR = 0.6 is good โ€” above the 0.5 threshold for a consistent signal. The IC doesn't vary wildly across months.

3

Decay to zero at 21 days (1 month) means the signal's edge is fully captured by monthly rebalancing. Rebalancing more frequently doesn't help; rebalancing less frequently loses alpha.

4

Practical value: using Fundamental Law, with BR = 200 stocks ร— 12 months = 2400 bets/year: IR = 0.04 ร— โˆš2400 = 0.04 ร— 49 = 1.96. Excellent theoretical IR.

5

However: subtract transaction costs. If average one-way turnover = 20% monthly and costs = 10bp: cost drag โ‰ˆ 0.20 ร— 2 ร— 0.001 ร— 12 = 0.48%/yr on a typical position. Still leaves substantial net alpha.

Answer

This is a strong signal. IC = 0.04 with t = 4.65 is statistically convincing. ICIR = 0.6 shows consistency. Monthly rebalancing is optimal. Theoretical IR โ‰ˆ 1.96; after costs likely 1.0โ€“1.5. Research memo ready.

Common Mistakes

!

Computing IC with Pearson correlation instead of Spearman. Extreme return outliers (earnings surprises, halts) heavily distort Pearson IC. Spearman rank IC is robust to these and is the industry standard.

!

Not shifting the signal before computing IC. The signal on date t must be computed using only data available at t-1. A common error: using the same-day return in a rolling window that computes the 'signal'.

!

Treating the in-sample ICIR as the out-of-sample expectation. In-sample ICIR is inflated by selection bias (you're reporting the best-looking version of the signal). The out-of-sample ICIR is typically 30-50% lower.

!

Ignoring the correlation between signals when building a multi-signal model. Two signals with IC = 0.04 each contribute less than 2ร— the single-signal alpha if they are correlated. Always compute pairwise IC correlations before combining.

!

Claiming a signal is 'significant' based on IC alone without computing the IC t-stat. IC = 0.04 over 24 months has t = 0.04 ร— โˆš24 / ฯƒ_IC โ‰ˆ 1.5 โ€” not significant. Need at least 5 years of monthly data for most signals.

Only works in the Electron app

<webview> is an Electron-only tag. Run npm run electron:dev to use this.

25:00Focus
0

25 min focus ยท 5 min break ยท long break every 4 sessions

The Ultimate Grind