precise

Online (incremental) covariance & correlation estimation — the online complement to sklearn.covariance
precise is a small, numpy-only library of online covariance and correlation estimators behind a single sklearn-style partial_fit contract. Where sklearn.covariance estimators are batch-only, every estimator here updates one observation at a time and exposes covariance_, correlation_, precision_ and location_. On top of the estimators it adds a registry, river-style adapters for variables that enter and leave a universe, a panel of assessors for judging an estimate, a recommender that picks an estimator from observable data features, and the Schur pseudo-likelihood — a one-parameter bridge between the full and block-diagonal Gaussian likelihoods.

Install

pip install precise

numpy is the only required dependency (tested on numpy 1.26 and 2.x, Python 3.9–3.13). Optional extras: [pandas] (DataFrame output for the keyed adapters), [research], [dev].

Quick start

import numpy as np
from precise import EwaCovariance

est = EwaCovariance(r=0.05)          # exponentially weighted, online
for y in stream_of_vectors():        # y is a 1-D array, one observation
    est.partial_fit(y)

est.covariance_      # (d, d) ndarray, always symmetric PSD
est.correlation_     # unit-diagonal correlation
est.precision_       # inverse (when well-conditioned)
est.location_        # running mean

Every estimator follows the same contract, so a test harness (or your code) only needs to look for .fit / .partial_fit. Discover them programmatically:

from precise import all_estimators, estimator_from_name
all_estimators()                     # list of estimator classes
estimator_from_name("LedoitWolfCovariance")

Estimators

Fourteen truly-online estimators across families (no buffered recompute):

ClassFamilyNotes
EmpiricalCovariancesampleWelford running covariance
DiagonalCovariancesamplevariances only
EwaCovarianceweightedexponentially weighted
AdaptiveEwaCovarianceweightedsurprise-smoothed forgetting
LedoitWolfCovarianceshrinkageonline linear shrinkage
OASCovarianceshrinkageoracle approximating shrinkage
ShrunkCovarianceshrinkagefixed-intensity target
SchurCovarianceshrinkagecross-block coupling damping (linear/geodesic)
PartialMomentsCovariancesemidownside / semi-covariance
HuberCovariancerobustonline Huber M-estimator
TylerCovariancerobustrecursive Tyler M-estimator
GeodesicEwaCovariancegeometricaffine-invariant SPD geodesic step
DCCCovariancedynamicdecoupled vol & correlation
FactorCovariancefactorlow-rank + diagonal, O(d·k)/step

Dynamic universes

Finance rarely offers a fixed set of variables. The keyed adapters wrap any positional estimator into a river-style one over named variables that enter and leave:

from precise import keyed, EwaCovariance
est = keyed(EwaCovariance(r=0.05))
est.partial_fit({"AAPL": 0.01, "MSFT": -0.02})   # dict in, dict-of-dicts out
est.covariance_["AAPL"]["MSFT"]

FixedUniverse imputes missing keys; DynamicUniverse handles staleness/longevity eviction and pairwise assembly across changing key sets.

Assess & recommend

Because no estimator dominates every regime, precise treats choosing and judging an estimate as first-class:

from precise import all_assessors, suggest
all_assessors()                      # LogLikelihood, BlockPseudoLikelihood,
                                     # SchurLikelihood, SteinLoss, ... (higher = better)
suggest(X, top=3)                    # recommend estimator classes from data features

suggest maps observable, truth-free features (p/n, effective rank, sphericity, condition number, off-diagonal mass, excess kurtosis) to an estimator via a frozen, numpy-only decision tree.

The Schur pseudo-likelihood

The full Gaussian likelihood factorizes exactly, through Schur complements, into block-conditional terms. A single coupling-strength parameter γ ∈ [0,1] damps that conditioning, giving the Schur pseudo-likelihood γ: γ=1 is the full likelihood (fragile in high dimensions), γ=0 is the block-diagonal / composite likelihood (robust), and the interior is the bridge they lack. The same γ damping of the same Schur complement is Schur complementary portfolio allocation — interpolating hierarchical risk parity and minimum variance.

For the estimator/predictive use, the optimal trust has a closed form — the reliability of the coupling (a Wiener / James–Stein shrinkage):

γ* = (n−2) ρ² / [ (n−2) ρ² + (1 − ρ²) ]      (ρ² = block coupling, the conditional R²)

rising to 1 as the sample size or coupling grows, and to 0 as the coupling becomes noise. See the working paper: Schur Covariance Evaluation: A Principled Pseudo-Likelihood in High Dimensions (PDF).