Technical

Hierarchical Risk Parity (HRP) Guide (2026)

Build hierarchical risk parity portfolios correctly: clustering, quasi-diagonalisation, recursive bisection, runnable Python and failure checks.

14 min read·

What Is Hierarchical Risk Parity?

In May 2016, Marcos López de Prado proposed Hierarchical Risk Parity (HRP), a long-only allocation rule that uses a correlation tree instead of inverting the covariance matrix. His paper, Building Diversified Portfolios that Outperform Out-of-Sample, appeared in the Journal of Portfolio Management, volume 42(4), pages 59 to 69.

The attraction is practical. A sample covariance matrix can be singular when there are more assets than observations and unstable when assets are highly correlated. Classical unconstrained minimum-variance weights are proportional to Σ−11\Sigma^{-1}\mathbf{1}, so small covariance errors can become large weight changes. HRP can still return weights when Σ\Sigma is singular because it never computes Σ−1\Sigma^{-1}.

That does not make HRP an optimiser or guarantee better returns. It is a deterministic risk-allocation heuristic with three stages: cluster assets, reorder them and recursively split capital. DeMiguel, Garlappi and Uppal (2009) found that none of 14 optimised rules consistently beat 1/N1/N across seven datasets on Sharpe, certainty-equivalent return and turnover, which is a useful warning about estimation error rather than proof that HRP wins. See the original study and our modern portfolio theory guide.


The HRP Algorithm

Tree clustering

Start from a valid correlation matrix ρ\rho and convert it to distance:

dij=1−ρij2.d_{ij}=\sqrt{\frac{1-\rho_{ij}}{2}}.

For a positive semidefinite correlation matrix, this is proportional to the Euclidean distance between normalised return vectors. Perfectly correlated assets have distance zero, uncorrelated assets have 1/21/\sqrt{2} and perfectly anti-correlated assets have one.

López de Prado's original algorithm applies single linkage, which defines the distance between two clusters as the shortest pairwise distance. This builds a dendrogram. Single linkage is not innocuous: it can chain assets into a long cluster through a sequence of near neighbours. Average, complete and Ward linkage create different trees, so linkage is a model choice to validate, not a cosmetic plotting option.

Quasi-diagonalisation

The dendrogram supplies a leaf order that places similar assets next to each other. Reordering Σ\Sigma by that order tends to put large covariances near the diagonal. Nothing has been diagonalised algebraically; rows and columns have merely been permuted.

The order matters because the original recursive-bisection routine repeatedly cuts the ordered list in half. It does not always follow each dendrogram node as a separate allocation decision. That distinction is easy to lose in verbal summaries.

Recursive bisection

For each half-cluster CC, form an inverse-variance portfolio

ui=1/σi2∑j∈C1/σj2andVC=uTΣCu.u_i=\frac{1/\sigma_i^2}{\sum_{j\in C}1/\sigma_j^2} \quad\text{and}\quad V_C=\mathbf{u}^{\mathsf T}\Sigma_C\mathbf{u}.

If an ordered cluster splits into AA and BB, give AA the fraction

αA=VBVA+VB,αB=1−αA.\alpha_A=\frac{V_B}{V_A+V_B}, \qquad \alpha_B=1-\alpha_A.

Repeat until each leaf has a weight. The weights are non-negative and sum to one, assuming positive finite variances. This is often described as risk parity, but it does not generally equalise each asset's Euler risk contribution wi(Σw)iw_i(\Sigma w)_i. The split uses stand-alone cluster-variance proxies and ignores cross-covariance between the two child clusters in the allocation formula.


Worked Example and Correct Python

Take four assets with annual volatilities 10%, 12%, 20% and 25%. Suppose A and B correlate at 0.8, C and D at 0.6 and cross-cluster correlations are 0.1. Single linkage places them in the order A, B, C, D.

The inverse-variance proxy variance is about 0.0105 for cluster AB and 0.0387 for CD. The top split therefore gives AB

αAB=0.03870.0105+0.0387=0.786.\alpha_{AB}=\frac{0.0387}{0.0105+0.0387}=0.786.

Splitting within each pair gives approximate final weights A 46.4%, B 32.2%, C 13.1% and D 8.4%. The higher-volatility cluster receives less capital, while correlation determines which assets are treated as a group.

Here is a compact implementation. It keeps labels throughout; mixing integer leaf positions with a covariance matrix indexed by ticker names is a common and consequential bug.

import numpy as np import pandas as pd from scipy.cluster.hierarchy import leaves_list, linkage from scipy.spatial.distance import squareform def cluster_variance(cov: pd.DataFrame, names: list[str]) -> float: sub = cov.loc[names, names] ivp = 1.0 / np.diag(sub) ivp /= ivp.sum() return float(ivp @ sub.to_numpy() @ ivp) def hrp_weights(returns: pd.DataFrame) -> pd.Series: cov, corr = returns.cov(), returns.corr() distance = np.sqrt(np.clip((1.0 - corr) / 2.0, 0.0, 1.0)) tree = linkage(squareform(distance, checks=False), method="single") order = corr.index[leaves_list(tree)].tolist() weights = pd.Series(1.0, index=cov.index) clusters = [order] while clusters: cluster = clusters.pop() if len(cluster) <= 1: continue mid = len(cluster) // 2 left, right = cluster[:mid], cluster[mid:] v_left = cluster_variance(cov, left) v_right = cluster_variance(cov, right) alpha = v_right / (v_left + v_right) weights.loc[left] *= alpha weights.loc[right] *= 1.0 - alpha clusters.extend([left, right]) return weights / weights.sum()

For a library implementation, HRPOpt in PyPortfolioOpt accepts returns or a covariance matrix and exposes the linkage method. Compare its weights with your own implementation on a small labelled covariance matrix before trusting a large backtest.

López de Prado's paper reports Monte Carlo results in which HRP had lower out-of-sample variance than the Critical Line Algorithm and traditional risk parity under the paper's data-generating process. That supports further testing, not the blanket claim that HRP usually outperforms. Returns, turnover, constraints and the covariance estimator can change the ranking.


Where HRP Goes Wrong

No expected return. Vanilla HRP allocates risk without μ\mu. That can be desirable when expected returns are too noisy to estimate, but it cannot express a high-conviction return forecast. A subsequent tilt changes the properties of the original algorithm and must be tested as a separate strategy.

Unstable trees. Hierarchical clustering is discrete. A small correlation change can swap a branch and produce a weight jump even though no inverse is involved. Re-estimate on rolling windows, record cophenetic or cluster stability and compare linkage methods. If the dendrogram changes every rebalance, its economic story is decoration.

Bad covariance in, bad portfolio out. HRP avoids inversion but still depends on every variance and correlation estimate. Pairwise missing-data correlations may not form a positive semidefinite matrix. Stale prices can manufacture high correlations and low volatilities. Use synchronous returns, inspect eigenvalues and compare sample covariance with a shrinkage estimator.

Concentration survives. A very low-volatility asset can receive a large weight. Add explicit position, sector, liquidity and turnover limits after deciding how those constraints interact with the hierarchy. Then measure actual risk contributions rather than assuming the HRP name guarantees parity.

Backtest selection. Choosing the lookback, linkage, covariance estimator and rebalance frequency on the full history is still optimisation. Use a walk-forward design with point-in-time membership and realistic costs. Compare against 1/N1/N, inverse variance and constrained minimum variance, not only an unconstrained Markowitz portfolio that was set up to fail.

The efficient frontier guide explains the optimiser HRP is often compared with. For evaluation, report volatility, drawdown, turnover and the risk-adjusted return, plus weight and cluster stability.

A production review

Start with the return panel rather than the dendrogram. Align market closes across time zones, convert currencies consistently and decide how to treat holidays before calculating correlation. Forward-filling a closed market can create a zero return followed by a catch-up return, depressing same-day correlation and inventing clusters. Pairwise deletion gives each covariance entry a different sample and may leave an invalid matrix.

Then separate estimation from allocation. A shrinkage covariance estimator can reduce sampling noise, but use the same estimate to derive both ρ\rho and Σ\Sigma. Mixing a rank-correlation tree with a Pearson covariance allocation is a valid extension only if it is deliberate. Annualising Σ\Sigma does not change the HRP weights because all entries receive the same scale, though it changes reported portfolio volatility.

Track three forms of stability through the walk-forward test. Weight stability measures turnover and maximum changes. Tree stability measures whether assets remain in similar branches. Risk stability measures realised versus forecast volatility and marginal contributions. A portfolio can have stable weights while its cluster interpretation collapses, or a stable tree while one low-volatility asset dominates capital.

Constraints deserve their own algorithmic decision. Clipping a 35% weight to 10% and renormalising is not HRP and can push the excess into another concentrated branch. One practical approach is to treat HRP as a prior, then solve a small constrained optimisation that penalises distance from those weights. Another is to cap recursively within each branch. Both need independent validation.

Finally, perturb the inputs. Add sampling noise to returns, vary the lookback by one month and compare single, average and complete linkage. Record the dispersion of resulting weights. If a one-basis-point covariance change moves 20% of the portfolio, avoiding matrix inversion has not delivered the operational stability you wanted.

Benchmark on identical information. Equal weight, inverse variance, constrained minimum variance and HRP must use the same universe, rebalance dates, costs and missing-data policy. Report capacity and financing on the same basis as well. Otherwise the comparison measures data handling rather than allocation. A simpler rule that survives these controls is a valid result, not a failed experiment.


Frequently Asked Questions

What is hierarchical risk parity in one sentence?

A long-only allocation heuristic that clusters assets by correlation, reorders them and recursively allocates between cluster-variance proxies without inverting the covariance matrix.

Why is HRP better than Markowitz mean-variance?

It is not always better. HRP remains computable for a singular covariance matrix and avoids error amplification through inversion. Whether it has lower realised risk or turnover is an empirical question.

How does HRP compare with inverse-variance portfolios?

Inverse variance ignores correlation entirely. HRP uses correlation to set the leaf order and applies inverse-variance portfolios when estimating cluster risk. It may beat inverse variance, but no ordering holds for every sample.

What Python library implements HRP?

PyPortfolioOpt provides a documented HRPOpt implementation. Check library conventions for covariance frequency, missing data and linkage before comparing weights.

What paper introduced HRP?

López de Prado (2016), Building Diversified Portfolios that Outperform Out-of-Sample, Journal of Portfolio Management 42(4), 59 to 69.

Does HRP equalise asset risk contributions?

Not generally. Its recursive split uses inverse-variance cluster proxies. Calculate wi(Σw)iw_i(\Sigma w)_i after allocation if equal Euler risk contribution is a requirement.

Skip the £25k programme - try the alternative

Master's programmes are slow and expensive. Quantt is a self-paced alternative. Start free with a real lesson and interview practice, then unlock 50+ courses and your personalised plan.

Free to start · No credit card required