CMB Alpha Combination
Why combining mediocre signals creates something far better than any one alone
Learning Objectives
- •Understand the mathematical basis for signal combination benefits
- •Implement and compare different signal weighting methods
- •Recognize and account for signal correlation in combination
- •Know when combination helps and when it does not
Explain Like I'm 5
Combining signals works for the same reason diversification works in portfolios: uncorrelated sources of information add up. Three 0.03 IC signals combined can outperform a single 0.06 IC signal.
Think of It This Way
Think of it like asking multiple experts for directions. Each one might be slightly wrong, but if their errors are independent, the average of their answers gets you closer to the destination than any single opinion.
1Why Combination Works
2Weighting Methods
3The Correlation Trap
4How Production Systems Combine Signals
5When Combination Does Not Help
Key Formulas
Combined IC
Theoretical combined IC from N signals with average IC and average pairwise correlation rho
Effective Independent Signals
The number of truly independent signal sources after accounting for cross-correlation
Hands-On Code
Signal Combination Methods
import numpy as np
def combine_signals(signals, method='equal', ic_values=None, lookback=252):
"""
Combine multiple trading signals using various weighting methods.
Parameters:
signals: array of shape (T, N) with standardized signal values
method: 'equal', 'ic_weighted', 'inverse_var'
ic_values: array of IC values per signal (for ic_weighted)
lookback: rolling window for variance estimation
"""
T, N = signals.shape
if method == 'equal':
weights = np.ones(N) / N
combined = signals @ weights
elif method == 'ic_weighted':
positive_ics = np.maximum(ic_values, 0)
weights = positive_ics / positive_ics.sum() if positive_ics.sum() > 0 else np.ones(N) / N
combined = signals @ weights
elif method == 'inverse_var':
combined = np.zeros(T)
for t in range(lookback, T):
window = signals[t-lookback:t]
variances = np.var(window, axis=0) + 1e-8
inv_var_weights = (1 / variances) / np.sum(1 / variances)
combined[t] = signals[t] @ inv_var_weights
# Winsorize at +/- 3 std
std = np.std(combined[combined != 0]) if np.any(combined != 0) else 1.0
combined = np.clip(combined, -3 * std, 3 * std)
# Normalize to unit variance
final_std = np.std(combined[combined != 0]) if np.any(combined != 0) else 1.0
combined = combined / final_std if final_std > 0 else combined
return combinedImplements three signal combination approaches (equal weight, IC-weighted, inverse variance) with winsorization and normalization for production use.
Knowledge Check
Q1.Four uncorrelated signals, each with IC = 0.03, produce a combined IC of approximately:
Q2.Ten signals with average pairwise correlation of 0.7 are effectively equivalent to how many independent signals?
Q3.Which combination method is the hardest to beat in practice?
Assignment
Construct three simple FX signals (momentum, mean-reversion, volatility-based) for EUR/USD. Compute the pairwise correlations and individual ICs. Then combine using equal weighting and IC-weighting. Compare the combined IC to the individual ICs and calculate the theoretical vs. realized improvement.