Schur-complementary allocation

One slider from HRP to minimum variance, over a smooth ordering.

Hierarchical risk parity splits the universe in two, allocates between the halves by inverse variance, and recurses — never inverting a matrix, but also never using the covariance between the halves. Minimum variance uses all of it, through Σ⁻¹. The Schur-complementary portfolio connects them with a single coupling parameter: at γ = 0 the recursion is exactly HRP; as γ → 1 the off-diagonal blocks are folded back in via Schur complements and the weights approach minimum variance.

One more substitution matters for streaming use. Classic HRP orders assets by an agglomerative dendrogram, which can reorder discontinuously as the covariance drifts. Here the order comes from Fiedler seriation — the second eigenvector of the similarity graph's Laplacian — which moves continuously with the covariance. The second widget shows what that is worth in turnover.

Try it: drag γ

Daily returns of 28 Dow names, 2010–2024. The heatmap is the empirical correlation in the chosen order; the bars are the Schur weights, recomputed by the actual package (compute_monotonic_weights) on a grid of γ and shown in the same order.

0.00
0 — HRP (block-diagonal)minimum variance — 1

Two things to notice. The weights deform continuously in γ — there is no point at which the portfolio switches regime. And the slider quietly stops helping: past γ ≈ 0.67 on this covariance, pushing further no longer reduces variance, so the estimator caps the effective γ there (the keep_monotonic behaviour; the readout shows both the requested and effective value). Portfolio variance falls from 1.39× the unconstrained minimum-variance level at γ = 0 to 1.34× at the cap — a modest gain on this particular covariance, priced long-only and without ever inverting Σ.

Out of sample, the middle of the bridge wins

In sample, variance can only fall as γ rises — more of the covariance is used. Out of sample the question is different: the cross-block terms that γ folds in are estimated, and estimation error grows with how aggressively they are used. Here weights are fitted on one-year windows drawn from 2010–2017 (raw weights, no monotonic cap, so the whole bridge shows) and evaluated on the 2018–2024 covariance, averaged over 26 windows:

Neither endpoint is best. HRP (γ = 0) ignores cross-block covariance it could have used; γ = 1 trusts estimated cross-block terms it shouldn't, and pays 21% for it. The minimum sits mid-bridge, at γ ≈ 0.55, about 2.5% below HRP — a modest dip, but a real interior optimum: the coupling parameter is a bias–variance dial, not a formality. The γ slider above moves the marker here too.

The natural objection is that raw one-year covariances overfit by construction, and a practitioner would shrink first. The toggle answers it: switch the training covariances to Ledoit–Wolf and the interior optimum survives — slightly deeper (0.97× at γ = 0.6) and γ = 1 still pays 24%. On this data, shrinkage moves the best γ a little to the right; it does not rescue the far end of the bridge.

Nor is the interior optimum an accident of this dataset — it is provable. In a four-asset, two-block example with a two-point error on one cross-block covariance entry, the expected out-of-sample variance satisfies F(0.9) < F(0) and F(0.9) < F(1) as exact rational inequalities (every step of the recursion is rational arithmetic, so the comparison is a certificate, not a simulation), while γ = 0 is structurally noise-immune — the HRP recursion never reads the cross block, so the minimizer is never at 0 and, above the exhibited noise level, never at 1 either. The construction and certificate: experiments/schur_interior_optimum.py.

What the smooth ordering is worth

Same experiment twice: an EWMA covariance (60-day halflife) over the same 28 names, rebalanced weekly at γ = 0.5, 2011–2024. The only difference is the ordering fed to the recursion — a dendrogram recomputed each week, versus Fiedler seriation warm-started from the previous week. Cumulative one-way turnover:

The dendrogram portfolio pays about 40% more turnover for the same recursion on the same covariance — the extra trades are pure reordering, not information. The gap is the point of replacing the combinatorial step with a spectral one: the allocation becomes a continuous function of the covariance end to end, which is what makes a streaming partial_fit cheap to follow in practice.

Reproducible: experiments/gen_schur_gamma_data.py computes everything shown here (orders, weight grid, turnover series) with the allocation package. Estimator: allocation/schur.py (SchurComplementary, and HierarchicalRiskParity as its γ = 0 case). Background and bibliography at schur.microprediction.org.