Home Verified Methods Reports Papers Methodology About
HomeLearn › HRP vs minimum variance: where the out-of-sample drift comes from

HRP vs minimum variance: where the out-of-sample drift comes from

Short answer

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

optimism = voltrue / volin − 1
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 400vol invol truevol outOptimismLuckDriftMax weightShortN effective
HRP (single)0.14010.14400.1419+2.8%−1.5%+1.3%0.106016.3
HRP (Ward)0.14190.14390.1425+1.5%−1.0%+0.4%0.110016.7
Minimum variance0.13110.14890.1489+13.5%+0.1%+13.6%0.229−0.1127.4
Minimum variance, long-only0.13250.14500.1460+9.4%+0.7%+10.2%0.20609.5
Minimum variance, shrinkage 0.30.13300.14440.1432+8.6%−0.8%+7.7%0.169−0.01911.8
Equal weight0.14740.14640.1443−0.7%−1.4%−2.1%0.050020.0
Oracle: minimum variance from Σ0.14120.13880.13770.129−0.05610.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.

THRP drift (optimism / luck)MinVar drift (optimism / luck)MinVar |w − woracle|Shrunk 0.3 driftHRP vol outMinVar vol out
60+10.0% (+6.3 / +3.5)+49.7% (+39.7 / +7.2)1.66+26.4%0.16550.1924
120+18.7% (+14.7 / +3.5)+29.3% (+22.0 / +5.9)0.98+25.1%0.16410.1658
250+8.4% (+5.3 / +3.0)+17.8% (+11.7 / +5.5)0.71+15.0%0.16300.1616
500+3.7% (+0.4 / +3.3)+8.4% (+2.4 / +5.9)0.59+6.4%0.16650.1602
1,000+3.8% (+0.4 / +3.4)+6.6% (+1.0 / +5.5)0.40+5.5%0.16600.1579
2,000+5.9% (+2.5 / +3.3)+7.2% (+2.5 / +4.6)0.21+6.8%0.16420.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 panelsDrift median [p25, p75]Optimism medianVol out medianLowest vol out in
HRP (single)+2.3% [−1.6, +7.6]+1.4%0.14562% of seeds
HRP (Ward)+2.1% [−1.8, +6.9]+1.6%0.14584%
Minimum variance+20.4% [+12.9, +24.4]+19.6%0.14274%
Minimum variance, long-only+8.8% [+2.8, +13.6]+7.5%0.140626%
Minimum variance, shrinkage 0.3+11.5% [+6.3, +14.7]+10.7%0.138964%
Equal weight+0.9% [−4.2, +4.6]+0.1%0.14940%

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 diagonalvol invol outDriftOptimismShortN effective
0.00.13110.1489+13.6%+13.5%−0.1127.4
0.10.13150.1462+11.2%+11.5%−0.0549.0
0.30.13300.1432+7.7%+8.6%−0.01911.8
0.50.13520.1419+4.9%+6.0%014.3
0.70.13820.1416+2.5%+3.6%016.5
1.0 (inverse variance)0.14570.1437−1.3%−0.5%018.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

Reproduce

cd quantmedia-research/hrp-drift-anatomy
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