Skip to content

How Risk Parity Changes a Portfolio’s Risk Contributions

Original question

Can you explain risk parity portfolios and compare their performance with traditional mean-variance optimised portfolios?
Risk parity allocates equal shares of estimated portfolio risk to selected assets or sleeves. Mean-variance optimisation uses expected returns and covariance to trade off portfolio risk against expected reward. Risk parity avoids dependence on expected return forecasts, while mean-variance can use a reliable forecast to tilt toward assets with higher expected reward. To compare realised performance, put both portfolios on the same risk and cost assumptions and evaluate subsequent returns.
A 50/50 equity-bond allocation can still derive most of its risk from equities because equity returns are often more volatile. Risk parity reduces the weight of the more volatile or highly correlated sleeve until the sleeves contribute equally to portfolio volatility. Equal shares are a choice. You can instead give each sleeve a specific share of the volatility budget.
The grouping matters. Splitting equities into three regional sleeves and treating bonds as a single sleeve assigns three of four risk budgets to equities in a sleeve-level calculation. Defining the units before optimisation keeps that choice visible. Also, comparing an unlevered allocation with a volatility-targeted allocation introduces a financing and leverage difference that needs to be measured separately.

Work out who contributes the risk

For a portfolio with positive volatility σp=w⊤Σw\sigma_p=\sqrt{w^\top\Sigma w}, the marginal contribution of asset ii is (Σw)i/σp(\Sigma w)_i/\sigma_p. The component contribution is

RCi=wi(Σw)iσp.\mathrm{RC}_i=w_i\frac{(\Sigma w)_i}{\sigma_p}.

The contributions sum to σp\sigma_p. Equal risk contributions require RCi=σp/n\mathrm{RC}_i=\sigma_p/n. For two long-only assets, the same covariance term appears in each component numerator, so equality reduces to w12σ12=w22σ22w_1^2\sigma_1^2=w_2^2\sigma_2^2. The solution has weights proportional to inverse volatility. With three or more assets, correlations generally affect the weights.

For positive risk budgets bib_i summing to one and a positive-definite covariance matrix, minimise 12x⊤Σx−∑ibilog⁡xi\tfrac12x^\top\Sigma x-\sum_i b_i\log x_i over positive xx. Its first-order conditions are xi(Σx)i=bix_i(\Sigma x)_i=b_i. Normalising xx to unit weight preserves the risk shares. This gives a general route to risk budgeting.

The marginal contribution asks how fast portfolio volatility changes if you add a little exposure to one asset while holding the other exposures fixed. Multiplying by the amount held gives that asset's component contribution. Summing components reproduces total volatility by the degree-one homogeneity of w⊤Σw\sqrt{w^\top\Sigma w}. So equalising contributions is a different objective from equalising capital. With two assets and positive weights, the cross-covariance terms cancel when you set the two contributions equal, leaving a simple relation between weights and standalone volatilities.

Suppose equity and bond annual volatilities are 20% and 6%, with correlation 0.25 and expected excess returns of 6% and 2.5%. Risk parity allocates about 23.1% to equities and 76.9% to bonds. Estimated portfolio volatility is 7.30%, with each sleeve contributing about 3.65 percentage points. A fully invested tangency portfolio, one specific mean-variance choice, allocates about 14.7% to equities and 85.3% to bonds. It has estimated volatility of 6.51%. Its expected excess return and volatility imply a slightly higher in-model Sharpe ratio. To compare realised Sharpe, drawdown and turnover, refit both portfolios on past data at each rebalance, apply identical trading cost conventions, and evaluate the weights on the following period.

Compare the risk contributions in Python

import numpy as np volatility = np.array([0.20, 0.06]) correlation = np.array([[1.0, 0.25], [0.25, 1.0]]) cov = correlation * np.outer(volatility, volatility) excess_return = np.array([0.06, 0.025]) risk_parity = 1 / volatility risk_parity /= risk_parity.sum() tangency = np.linalg.solve(cov, excess_return) tangency /= tangency.sum() for label, weights in [("risk parity", risk_parity), ("tangency", tangency)]: risk = np.sqrt(weights @ cov @ weights) contribution = weights * (cov @ weights) / risk print(label, weights.round(4), risk, contribution / risk, "expected Sharpe", (weights @ excess_return) / risk)

Interactive example

See how correlation changes two-asset portfolio risk

Asset A has 15% annual volatility and asset B has 25%. Move the correlation or the long-only weight in A.

Selected portfolio volatility 15.03% · minimum-risk weight in A 80.19%
Portfolio volatility as the weight in asset A changes1520250255075100Weight in asset A (%)Annual volatility (%)
  • Portfolio volatility
  • Selected weight

References and next steps