allocation
Online (streaming) portfolio construction.
scikit-learn / skfolio-compatible estimators
(fit / partial_fit / weights_ / predict)
on a keyed dynamic-universe layer, so they survive reconstituting universes where assets
come and go. Two methods are novel; the rest are the standard
toolkit, re-engineered to stay smooth under streaming updates.
Methods
Novel
Thurstone portfolio
Weights are the winning probabilities of a Thurstonian race. Abilities calibrate the race to a benchmark; the tilt re-runs it under the estimated correlation. A common-seed transport keeps streaming updates low-turnover.
Schur-complementary
The Schur gamma coupling (HRP at 0, minimum variance toward 1), but ordered
by Fiedler seriation instead of a dendrogram — so the hierarchy, and the
weights, are a smooth function of the covariance. Background and bibliography at
schur.microprediction.org.
Standard, kept smooth
Read weights = allocator(cov(data)) as two factors. For the closed-form linear
allocators (minimum variance, max diversification / decorrelation, inverse variance,
mean–variance) the allocator is already smooth in the covariance — pair them with a
smooth online covariance and you are done. The novelty in Thurstone and Schur is the cases
where the allocator itself is rough: sampling noise (common-seed transport), combinatorial
ordering (Fiedler seriation), and long-only kinks (kept interior).
Estimators
Every method has a batch estimator and a streaming twin
(Streaming…) for a changing universe.
| Batch | Streaming | Kind | Notes |
|---|---|---|---|
| ThurstonePortfolio | StreamingThurstone | novel | ability tilt; common-seed transport |
| SchurComplementary | StreamingSchur | novel | Schur gamma coupling; Fiedler seriation |
| HierarchicalRiskParity | StreamingHRP | standard | HRP; the gamma=0 case of Schur |
| RiskParity | StreamingRiskParity | standard | equal risk contribution; interior, warm-started |
| MinimumVariance | StreamingMinimumVariance | standard | Σ⁻¹1; shrinkage; signed |
| MaximumDiversification | StreamingMaximumDiversification | standard | Σ⁻¹σ; signed |
| MaximumDecorrelation | StreamingMaximumDecorrelation | standard | min-variance on the correlation; signed |
| MeanVariance | StreamingMeanVariance | standard | tangency Σ⁻¹μ; μ from EWMA mean or supplied |
| EqualWeight | StreamingEqualWeight | standard | 1/n |
| InverseVariance | StreamingInverseVariance | standard | w ∝ 1/σ² |
Usage
pip install allocation
from allocation import SchurComplementary, RiskParity, MinimumVariance
SchurComplementary(gamma=0.5).fit(returns).weights_ # novel
RiskParity().fit(returns).weights_ # standard
MinimumVariance(shrinkage=0.1).fit(returns).weights_
# streaming, over a changing universe
from allocation import StreamingSchur
est = StreamingSchur(gamma=0.5)
for x in stream: # x = {asset_id: return}
est.learn_one(x) # assets may enter / leave
w = est.predict_one() # {asset_id: weight}
Why a separate package
skfolio is the scikit-learn-native portfolio library, but it is batch: a changing
universe is handled by NaN/incomplete-data mechanics, not by carrying per-asset state across
streaming updates. allocation is the online complement —
partial_fit, a keyed dynamic universe (in the spirit of
precise), and turnover control by
construction — while staying API-compatible so each estimator can be contributed upstream.