Factor Combination: How to Blend Multiple Alpha Signals
Real alpha strategies rarely rely on a single factor. Factor combination covers how to blend multiple signals into a single portfolio with better risk-adjusted returns.
No single factor is sufficient for a real investment strategy. Momentum works but crashes in reversals. Value works but is slow. Quality is stable but low Sharpe in isolation. The key to building a robust strategy is combining multiple factors into a portfolio that’s better than any single factor alone.
Why Combine Factors?
Diversification of alpha sources. Different factors exploit different market inefficiencies. Momentum exploits behavioral biases, value exploits mean-reversion, quality exploits the persistent risk premium for low-risk stocks. When one factor is underperforming, others may be working.
More stable returns. A single factor can have long periods of underperformance. A multi-factor portfolio smooths returns because factors cycle in and out of favor.
Better risk-adjusted returns. Combining negatively correlated alpha signals can reduce portfolio volatility without reducing expected return — improving the Sharpe ratio.
Methods for Combining Factors
Method 1: Equal Weighting (Simplest)
Give each factor equal weight:
Equal weighting is simple and robust — it avoids overfitting to historical data. The main drawback is that it doesn’t account for differences in factor quality (a great factor gets the same weight as a mediocre one).
Method 2: IC-Weighted Combination
Weight factors by their information coefficient:
This gives more weight to factors with higher predictive power. The drawback is that IC estimates are noisy, and you may overfit to recent IC.
Method 3: Mean-Variance Optimization (Modern Portfolio Theory)
Treat each factor as an asset and optimize portfolio weights to maximize expected return minus risk:
Where μ is the vector of factor expected returns (often proxied by IC) and Σ is the covariance matrix of factor returns.
The main challenge: μ and Σ are never known exactly. Small errors in μ lead to large errors in optimal weights. This is the Markowitz optimization trap.
Method 4: Risk-Based Weighting (Robust)
Weight factors inversely proportional to their risk contribution:
Or weight by inverse variance to minimize portfolio volatility regardless of expected return.
Combining Factors in Practice
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
def combine_factors_ic_weighted(factor_dict, returns, lookback=252):
"""
Combine factors using IC-weighted combination.
Parameters
----------
factor_dict : dict {name: Series}
Dictionary of factor values (date index, asset columns)
returns : DataFrame
Asset returns
lookback : int
Window for IC estimation
Returns
-------
combined_factor : DataFrame
Combined factor values
weights : DataFrame
Factor weights over time
"""
factor_names = list(factor_dict.keys())
n_factors = len(factor_names)
# Standardize factors
scaler = StandardScaler()
# Compute rolling IC for each factor
ic_history = {name: [] for name in factor_names}
weights_history = []
dates = list(factor_dict[factor_names[0]].index)
for i in range(lookback, len(dates) - 1):
window_factors = []
window_returns = []
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 = np.corrcoef(fv[common].values, ret[common].values)[0, 1]
ic_history[name].append(ic)
else:
ic_history[name].append(0.0)
# Current IC-based weights
current_ics = np.array([ic_history[name][-1] for name in factor_names])
current_ics = np.maximum(current_ics, 0) # Clip negative ICs
if current_ics.sum() > 0:
weights = current_ics / current_ics.sum()
else:
weights = np.ones(n_factors) / n_factors
weights_history.append(weights)
# Compute combined factor value for next period
for name, fv in factor_dict.items():
if dates[i+1] in fv.index:
combined_val = np.dot(weights, [factor_dict[n].loc[dates[i+1]] for n in factor_names])
weights_df = pd.DataFrame(weights_history, columns=factor_names)
return weights_df
def combine_factors_equal_weight(factor_dict):
"""
Simple equal-weight combination of factors.
"""
factor_names = list(factor_dict.keys())
combined = sum(factor_dict[name] for name in factor_names) / len(factor_names)
return combined
Key Considerations
Orthogonalization. If your factors are highly correlated, combining them gives you little diversification benefit. Consider orthogonalizing factors (e.g., via PCA) before combining, or using a smaller number of uncorrelated factors.
Turnover. Combining many factors with different decay rates can lead to high turnover. Use decay-adjusted weights to reduce unnecessary rebalancing.
Factor decay. A factor that worked 5 years ago may not work today. Use rolling IC to adjust factor weights dynamically — give more weight to currently working factors.
Common Pitfalls
Over-fitting the combination weights. Optimizing combination weights on historical data is tempting but dangerous. If you use MVO, use regularization or constraints. Equal weighting is often more robust out of sample.
Ignoring factor correlation. Combining two momentum factors gives you a portfolio with 2x the momentum exposure, not 2x diversification. Combine factors that are genuinely complementary.
Forgetting transaction costs. Each factor requires rebalancing. Adding a fifth factor with high turnover may increase total turnover more than it adds alpha, resulting in lower net Sharpe.
Where It Fits
Factor combination is the bridge between factor research and portfolio construction. Alpha factor defines the signals. IC analysis evaluates them. Factor decay informs rebalancing frequency. Factor combination blends them into a portfolio.
References
- López de Prado, Advances in Financial Machine Learning, Ch. 6. Wiley, 2018. ISBN: 978-1-119-48208-6.
- Ang, Asset Management, Ch. 10. Oxford University Press, 2014. ISBN: 978-0-19-995932-3.
- Kritzman, The Misfortunes of the Golden Ratio. Wiley, 2017.