Learning Hub Strategy Development Lesson 24
Phase 3 — Lesson 7 of 8
Hub
Phase 3 · Strategy Development · Lesson 24

Multi-Strategy Portfolio
& Correlation

Combine multiple strategies into a portfolio using equal weight, volatility parity, and Sharpe-weighted allocation — with full correlation analysis.

~45 min
3 Allocation Methods
Phase 3 · Lesson 7 of 8
Phase 3 Progress88%

Correlation Is the Key

Two strategies with identical Sharpe ratios but correlation of 0 combined into a portfolio produce a portfolio Sharpe of √2 × individual Sharpe. Diversification is free return improvement — the only "free lunch" in trading.

PYTHONcorrelation_check.py
import pandas as pd

# Returns for three strategies over same period
returns = pd.DataFrame({
    "EMA_Cross"    : ema_result.returns,
    "Supertrend"   : st_result.returns,
    "VWAP_Reversal": vwap_result.returns,
})

corr = returns.corr()
print(corr)

# ── What to look for ─────────────────────────────────────
# correlation > 0.7  → strategies behave similarly, limited benefit
# correlation 0.3–0.7 → moderate diversification
# correlation < 0.3  → excellent diversification value
# correlation < 0    → negative correlation = hedging effect

Portfolio Construction Methods

MethodFormulaBest for
Equal Weight1/N per strategySimilar volatility strategies
Volatility Parity1/σ per strategy, normalisedStrategies with different risk levels
Sharpe WeightSharpe_i / Σ SharpeWhen strategies have different edge strength
Min CorrelationMaximise portfolio Sharpe via covarianceFull portfolio optimisation
PYTHONportfolio.py
import pandas as pd
import numpy  as np

class StrategyPortfolio:
    def __init__(self, strategy_returns: dict[str, pd.Series]):
        """strategy_returns: {name: pd.Series of per-candle returns}"""
        self.returns = pd.DataFrame(strategy_returns).dropna()

    def correlation_matrix(self) -> pd.DataFrame:
        return self.returns.corr().round(2)

    def equal_weight(self) -> pd.Series:
        w = 1 / len(self.returns.columns)
        return (self.returns * w).sum(axis=1)

    def volatility_parity(self) -> pd.Series:
        vols = self.returns.std()
        w    = (1 / vols) / (1 / vols).sum()
        return (self.returns * w).sum(axis=1)

    def sharpe_weight(self, risk_free: float = 0.065 / 94500) -> pd.Series:
        excess = self.returns - risk_free
        sharpes = excess.mean() / excess.std() * np.sqrt(94500)
        sharpes = sharpes.clip(lower=0)          # ignore negative-Sharpe strategies
        if sharpes.sum() == 0:
            return self.equal_weight()
        w = sharpes / sharpes.sum()
        return (self.returns * w).sum(axis=1)

    def equity_curve(self, method: str = "vol_parity", capital: float = 100_000) -> pd.Series:
        portfolio_rets = getattr(self, {
            "equal"     : "equal_weight",
            "vol_parity": "volatility_parity",
            "sharpe"    : "sharpe_weight",
        }[method])()
        return capital * (1 + portfolio_rets).cumprod()

    def compare_methods(self, capital: float = 100_000) -> pd.DataFrame:
        methods = {
            "Equal Weight"    : self.equal_weight(),
            "Vol Parity"      : self.volatility_parity(),
            "Sharpe Weight"   : self.sharpe_weight(),
        }
        from performance import PerformanceReport
        rows = []
        for name, rets in methods.items():
            eq  = capital * (1 + rets).cumprod()
            rpt = PerformanceReport(eq, pd.DataFrame())
            s   = rpt.summary()
            rows.append({"method": name, **s})
        return pd.DataFrame(rows).set_index("method")

Portfolio in Practice

PYTHONrun_portfolio.py
# Run three strategies on same data
engine = BacktestEngine()
r_ema  = engine.run(df, ema_cross_signal)
r_st   = engine.run(df, supertrend_signal)
r_vwap = engine.run(df, vwap_reversal_signal)

# Build portfolio
port = StrategyPortfolio({
    "EMA"     : r_ema.returns,
    "ST"      : r_st.returns,
    "VWAP"    : r_vwap.returns,
})

print(port.correlation_matrix())
print(port.compare_methods())
Aim for different strategy types

The best portfolio mixes trend-following (EMA cross, Supertrend), mean-reversion (VWAP, Bollinger) and momentum (RSI breakout) strategies. These tend to have naturally low or negative correlation because they profit in different market conditions.