Systematic Alpha Signal Discovery Framework
A statistically rigorous framework for identifying, validating, and characterizing tradeable signals in financial time series. Designed for quantitative researchers who need to distinguish genuine predictive relationships from statistical artifacts.
Intended Audience: Quantitative researchers and systematic traders with familiarity in statistical hypothesis testing and signal processing. The mathematics assumes comfort with rank correlation, multiple testing correction, and basic time series concepts.
The fundamental challenge in quantitative alpha research is not finding signals that backtest well--it is finding signals that will continue to work out-of-sample. This framework addresses the core failure modes:
- Multiple Testing Bias: Testing hundreds of signal candidates guarantees false discoveries
- Execution Slippage: Theoretical alpha vanishes when realistic trading costs are applied
- Signal Decay: Most predictability decays faster than execution latency allows
- Regime Dependence: Signals that work in low-vol fail in high-vol (and vice versa)
- Factor Exposure: Apparent alpha is often repackaged exposure to known risk factors
Signal Hunter systematically quantifies each of these failure modes.
Signal Monitor -- Companion tool for production deployment. While Signal Hunter discovers and validates signals, Signal Monitor tracks their health in real-time:
Signal Hunter (discovery) --> Signal Monitor (production monitoring)
"Which signals work?" "Are they still working?"
Recommended workflow: Use Signal Hunter for initial signal selection, then deploy Signal Monitor to track IC degradation, crowding, and regime shifts.
For each signal S_t, we compute the Information Coefficient (Spearman rank correlation) against forward returns:
IC = corr_rank(S_t, R_{t+1:t+h})
Statistical significance is assessed via the Fisher transformation:
z = arctanh(IC) * sqrt(n-3)
With m signals tested at significance level alpha, we expect m * alpha false positives by chance. We apply:
Benjamini-Hochberg FDR Control: Sort p-values p_(1) <= ... <= p_(m) and reject all H_i where:
p_(i) <= (i/m) * alpha
This controls the False Discovery Rate (expected proportion of false discoveries among rejections) rather than the more conservative Family-Wise Error Rate.
Signal predictability decays with horizon. We model IC decay as exponential:
IC(h) = IC_0 * exp(-h/tau)
The half-life t_1/2 = tau * ln(2) determines how quickly alpha dissipates. A signal with half-life shorter than execution latency has no tradeable alpha.
Note: When the exponential decay model fails to fit (non-monotonic IC profile, or tau <= 0), half-life returns NaN rather than infinity. This indicates the model is inapplicable, not that the signal persists forever.
Raw IC is insufficient for signal comparison. The economic value incorporates:
V = |IC| * sqrt(Capacity) * f(half_life, latency)
Where:
- Capacity is estimated via Almgren-Chriss market impact: Impact ~ sigma * sqrt(Q/V)
- f(half_life, latency) = max(0, 1 - latency/half_life) -- penalizes signals whose half-life is shorter than execution window. A signal with half-life equal to latency has f=0 (no tradeable value); half-life >> latency approaches f=1.
To isolate novel alpha from factor exposure, we regress signals against known factors:
S_t = beta_0 + sum_i(beta_i * F_i,t) + sum_i(gamma_i * F_i,t^2) + sum_{i<j}(delta_ij * F_i,t * F_j,t) + epsilon_t
The residual epsilon_t represents alpha orthogonal to factors. Nonlinear terms capture state-dependent exposure (e.g., momentum signals with convex momentum factor loading).
Signals are evaluated separately across volatility regimes using fixed thresholds (not data-dependent quantiles):
| Regime | Annualized Vol |
|---|---|
| Low Vol | < 15% |
| Normal | 15-25% |
| High Vol | 25-40% |
| Crisis | > 40% |
A signal is flagged as unstable if:
- IC sign flips across regimes, OR
- IC coefficient of variation across regimes exceeds 1.0
| Category | Count | Examples |
|---|---|---|
| Momentum | 25 | ROC, RSI, MA crossovers, breakouts, acceleration (5/10/20/40/60 day lookbacks) |
| Mean Reversion | 15 | Z-score (multiple windows), Bollinger position, RSI fade |
| Volatility | 15 | Realized vol, Parkinson, Garman-Klass, vol ratio (short/long) |
| Microstructure | 12 | Price-volume divergence, volume imbalance, Amihud illiquidity, VPIN |
| Total | 67 |
Theoretical IC computed at close prices is meaningless. We compute IC against achievable returns:
Entry: VWAP[t+delay]
Exit: VWAP[t+delay+holding_period]
Slippage: 2 * slippage_bps
Impact: 2 * sigma * sqrt(participation_rate)
The gap between theoretical and achievable IC quantifies execution cost drag.
# Synthetic data (for testing framework behavior only)
# WARNING: Synthetic data has embedded signals - FDR survival rates
# will be artificially high (~39% vs 5-15% on real data)
python signal_hunter.py --synthetic 1000 --holding 5 --delay 1 --slippage 10
# Your data (CSV with Date, Open, High, Low, Close, Volume)
python signal_hunter.py --data prices.csv --holding 5 --output results.csvfrom signal_hunter import SignalHunter, DataLoader
# Initialize
hunter = SignalHunter(
holding_period=5, # Forward return horizon (days)
execution_delay=1, # Days between signal and execution
slippage_bps=10, # Round-trip slippage estimate
alpha=0.05 # Significance level
)
# Load data
data = DataLoader.load_csv('prices.csv')
hunter.load_data(data)
# Or generate synthetic data
hunter.load_synthetic(n_days=1000, seed=42)
# Run analysis
results = hunter.hunt(
include_regime_analysis=True,
include_factor_analysis=True
)
# View report
print(hunter.generate_report())
# Export
results.to_csv('signal_results.csv', index=False)| Column | Type | Description |
|---|---|---|
signal |
str | Signal identifier |
ic |
float | Raw Information Coefficient |
ic_se |
float | IC standard error (Fisher) |
t_stat |
float | t-statistic |
p_value |
float | Raw p-value |
p_value_fdr |
float | FDR-adjusted p-value |
significant_fdr |
bool | Passes FDR threshold |
half_life_days |
float | Signal decay half-life (NaN if model fails) |
achievable_ic |
float | IC after execution costs |
capacity_mm |
float | Estimated capacity ($M) |
signal_value |
float | Economic value metric |
factor_r2 |
float | Variance explained by factors |
residual_ic |
float | IC after orthogonalization |
regime_stable |
bool | Stable across vol regimes |
worst_regime_ic |
float | IC in worst regime |
Strong signal characteristics:
significant_fdr = Truehalf_life_days > execution_delay * 2achievable_ic / ic > 0.7(low execution drag)factor_r2 < 0.3(not just factor exposure)residual_icclose to rawicregime_stable = True
Red flags:
half_life_days = NaNwith low IC (noise, decay model inapplicable)factor_r2 > 0.5(repackaged factor)regime_stable = False(regime-dependent)- Large gap between
icandachievable_ic
numpy>=1.21.0
pandas>=1.3.0
scipy>=1.7.0
- Capacity estimates are approximate: True capacity depends on order book dynamics, not just ADV
- Factor model is simplified: Production systems use richer factor specifications (e.g., Barra, Axioma)
- Regime thresholds are fixed: May need calibration for different asset classes (e.g., crypto vol thresholds would be higher)
- Single-asset analysis: Cross-sectional signals require panel data extension
- No transaction cost optimization: Turnover is not explicitly penalized
- Synthetic data caveat: FDR survival rates on synthetic data (~39%) are artificially high; expect 5-15% on real market data
- Harvey, C., Liu, Y., & Zhu, H. (2016). ...and the Cross-Section of Expected Returns. Review of Financial Studies
- Benjamini, Y., & Hochberg, Y. (1995). Controlling the False Discovery Rate. JRSS-B
- Almgren, R., & Chriss, N. (2001). Optimal Execution of Portfolio Transactions. Journal of Risk
- Bailey, D., Borwein, J., Lopez de Prado, M., & Zhu, Q. (2014). Pseudo-Mathematics and Financial Charlatanism. Notices of the AMS
MIT