HRP vs minimum variance: where the out-of-sample drift comes from
Because the panel is generated from a known factor model, its true covariance is available, and every allocator's out-of-sample volatility drift can be split into optimism (the in-sample estimate sits below the true volatility of the chosen weights) and luck (the test window's own noise). Minimum variance's +13.6% is +13.5% optimism and +0.1% luck: the optimiser fitted the estimation error in a 120-period sample covariance and reported a volatility it could never have. HRP's +1.3% is +2.8% optimism and −1.5% luck. Across 50 seeds HRP drifts less than minimum variance every time, but its realised volatility is lower than minimum variance's in only 40% of them, and a 0.3-shrunk minimum variance ends lowest in 64%. Drift measures honesty, not performance.
The question the verification report left open
The HRP verification report fits six allocators on 120 periods of a 20-asset panel, holds the weights fixed for 400 more, and finds HRP's volatility drifting +1.3% against minimum variance's +13.6%. It suggested varying the training length as the next experiment. This note does that, and first explains the drift, with one instrument the report did not use: the panel's true covariance. Everything is synthetic.
Setup
The report's generator draws a market factor (σ 0.008), four block factors (σ 0.010) and, per asset, a market beta in [0.6, 1.3], a block beta in [0.7, 1.2] and an idiosyncratic σ in [0.006, 0.018]. Mirroring it call for call gives the identical 520×20 panel (the tests assert this) and the true covariance Σ = σm²βmβm′ + σb²(block mask)βbβb′ + diag(σi²). For a weight vector w, voltrue = √(w′Σw)·√252 is what those weights would deliver on average. Then
luck = volout / voltrue − 1
(1 + optimism)(1 + luck) = 1 + drift
The oracle is minimum variance computed from Σ itself: the best any covariance-based allocator could do with perfect information.
Part A: the published split, decomposed
| Train 120, test 400 | vol in | vol true | vol out | Optimism | Luck | Drift | Max weight | Short | N effective |
|---|---|---|---|---|---|---|---|---|---|
| HRP (single) | 0.1401 | 0.1440 | 0.1419 | +2.8% | −1.5% | +1.3% | 0.106 | 0 | 16.3 |
| HRP (Ward) | 0.1419 | 0.1439 | 0.1425 | +1.5% | −1.0% | +0.4% | 0.110 | 0 | 16.7 |
| Minimum variance | 0.1311 | 0.1489 | 0.1489 | +13.5% | +0.1% | +13.6% | 0.229 | −0.112 | 7.4 |
| Minimum variance, long-only | 0.1325 | 0.1450 | 0.1460 | +9.4% | +0.7% | +10.2% | 0.206 | 0 | 9.5 |
| Minimum variance, shrinkage 0.3 | 0.1330 | 0.1444 | 0.1432 | +8.6% | −0.8% | +7.7% | 0.169 | −0.019 | 11.8 |
| Equal weight | 0.1474 | 0.1464 | 0.1443 | −0.7% | −1.4% | −2.1% | 0.050 | 0 | 20.0 |
| Oracle: minimum variance from Σ | 0.1412 | 0.1388 | 0.1377 | — | — | — | 0.129 | −0.056 | 10.2 |
Three readings. First, minimum variance's drift is not bad luck in the test window: luck is +0.1%. Its in-sample 0.1311 was an artefact of fitting 20 assets to 120 observations (sample covariance condition number 43 against 35 for the truth), and the weights it chose have a true volatility of 0.1489, higher than HRP's 0.1440 and higher than the oracle's 0.1388. Second, HRP is not free of optimism (+2.8%) but nearly so, because it never inverts the covariance: its weights are ratios of cluster variances, which the sample estimates reasonably even at n = 120. Third, the oracle shows what the sample optimiser was aiming for and missed: a 0.1388 portfolio with a 5.6% short position and 10 effective names. The sample version doubled the short position and halved the effective names.
Part B: training length
A longer panel (seed + 1, 2,400 periods) with a fixed 400-period test window; training uses the T periods immediately before it.
| T | HRP drift (optimism / luck) | MinVar drift (optimism / luck) | MinVar |w − woracle| | Shrunk 0.3 drift | HRP vol out | MinVar vol out |
|---|---|---|---|---|---|---|
| 60 | +10.0% (+6.3 / +3.5) | +49.7% (+39.7 / +7.2) | 1.66 | +26.4% | 0.1655 | 0.1924 |
| 120 | +18.7% (+14.7 / +3.5) | +29.3% (+22.0 / +5.9) | 0.98 | +25.1% | 0.1641 | 0.1658 |
| 250 | +8.4% (+5.3 / +3.0) | +17.8% (+11.7 / +5.5) | 0.71 | +15.0% | 0.1630 | 0.1616 |
| 500 | +3.7% (+0.4 / +3.3) | +8.4% (+2.4 / +5.9) | 0.59 | +6.4% | 0.1665 | 0.1602 |
| 1,000 | +3.8% (+0.4 / +3.4) | +6.6% (+1.0 / +5.5) | 0.40 | +5.5% | 0.1660 | 0.1579 |
| 2,000 | +5.9% (+2.5 / +3.3) | +7.2% (+2.5 / +4.6) | 0.21 | +6.8% | 0.1642 | 0.1552 |
On this seed the test window is a high-volatility stretch, so every allocator carries a positive luck term of 2–7%; that is the part no training length can remove. Minimum variance's optimism falls from +39.7% at T = 60 to about +1–2.5% from T = 500 on, and its distance from the oracle weights shrinks eightfold. HRP's optimism is small from T = 250 on but is +14.7% at T = 120 on this seed: the clustering step is also estimated from the sample and can also be wrong. And once T is 250 or more, minimum variance's realised volatility is below HRP's on this panel, because with enough data the optimiser finds the diversification that HRP's tree structure cannot express.
Part C: 50 seeds at the published split
| Train 120, test 400, 50 panels | Drift median [p25, p75] | Optimism median | Vol out median | Lowest vol out in |
|---|---|---|---|---|
| HRP (single) | +2.3% [−1.6, +7.6] | +1.4% | 0.1456 | 2% of seeds |
| HRP (Ward) | +2.1% [−1.8, +6.9] | +1.6% | 0.1458 | 4% |
| Minimum variance | +20.4% [+12.9, +24.4] | +19.6% | 0.1427 | 4% |
| Minimum variance, long-only | +8.8% [+2.8, +13.6] | +7.5% | 0.1406 | 26% |
| Minimum variance, shrinkage 0.3 | +11.5% [+6.3, +14.7] | +10.7% | 0.1389 | 64% |
| Equal weight | +0.9% [−4.2, +4.6] | +0.1% | 0.1494 | 0% |
HRP drifts less than minimum variance in 50 of 50 seeds. It also ends with lower realised volatility than minimum variance in only 20 of 50, has lower true volatility in 17 of 50, and is the lowest-volatility allocator in one seed. Shrunk minimum variance takes that title in 32. The verification report's claim, that HRP “drifts far less”, holds without exception; the stronger claim people tend to make, that HRP therefore builds lower-risk portfolios, does not hold on this panel.
Part D: shrinkage
| Shrinkage toward diagonal | vol in | vol out | Drift | Optimism | Short | N effective |
|---|---|---|---|---|---|---|
| 0.0 | 0.1311 | 0.1489 | +13.6% | +13.5% | −0.112 | 7.4 |
| 0.1 | 0.1315 | 0.1462 | +11.2% | +11.5% | −0.054 | 9.0 |
| 0.3 | 0.1330 | 0.1432 | +7.7% | +8.6% | −0.019 | 11.8 |
| 0.5 | 0.1352 | 0.1419 | +4.9% | +6.0% | 0 | 14.3 |
| 0.7 | 0.1382 | 0.1416 | +2.5% | +3.6% | 0 | 16.5 |
| 1.0 (inverse variance) | 0.1457 | 0.1437 | −1.3% | −0.5% | 0 | 18.6 |
Drift falls monotonically with shrinkage and crosses zero at full shrinkage, where the allocator is plain inverse variance. Realised volatility bottoms out around 0.5–0.7 (0.1416–0.1419), level with HRP's 0.1419 on the same split. The crude diagonal target used here is a stand-in for Ledoit–Wolf; a proper shrinkage estimator would pick its own intensity from the data.
What this does not establish
- A factor-model panel with four clean blocks is the structure HRP was designed for and the structure that makes a sample covariance ill-conditioned; real markets are neither this clean nor stationary.
- No transaction costs and no rebalancing anywhere; fixed weights flatter every allocator and the least stable one most.
- “Optimism” and “luck” are defined for volatility only. Returns are not modelled (the panel has zero drift by construction), so nothing here speaks to Sharpe ratios.
- 50 seeds of one generator. The ordering of allocators by realised volatility could change with different block sizes, betas or idiosyncratic noise.
Reproduce
python experiment.py
python ../tests/test_hrp_drift.py # expected: 6 passed
Runtime about four seconds. The first test asserts that the mirrored panel is identical to the report's; the second that the published split reproduces 0.1401 / 0.1419 / 0.1311 / 0.1489 and that optimism and luck multiply to the drift exactly. Code and output on GitHub.
References
- López de Prado, M. (2016). Building Diversified Portfolios that Outperform Out of Sample. Journal of Portfolio Management, 42(4), 59–69.
- Michaud, R. O. (1989). The Markowitz Optimization Enigma: Is ‘Optimized’ Optimal? Financial Analysts Journal, 45(1), 31–42.
- Ledoit, O. and Wolf, M. (2004). A well-conditioned estimator for large-dimensional covariance matrices. Journal of Multivariate Analysis, 88(2), 365–411.
- DeMiguel, V., Garlappi, L. and Uppal, R. (2009). Optimal Versus Naive Diversification: How Inefficient is the 1/N Portfolio Strategy? Review of Financial Studies, 22(5), 1915–1953.