winning

A generalization of factor multinomial probit models that scales to millions of variables

This package prices the winner of many: N competitors whose performances can be correlated through common factors, and for the independent and factor grammars can follow any smooth noise distribution (the block, nested and tree kernels are Gaussian, and say so rather than silently ignoring a base). One pass over a shared survival field gives all N win probabilities, and the same field answers removal and photo-finish queries; complete all-pairs tables of those have quadratic output size and are priced per query. Calibration runs in the other direction, from observed shares back to abilities. Factor probit, Luce's softmax and the finite-temperature softmin are special cases of one parameterized race.

one race, five grammars O(QNL) shared field photo-finish densities Python · R · Rust parity-locked ports

The model, live

Six runners moved by two common luck factors; whichever draws the smallest performance wins. Drag each runner's ability and its two factor loadings, pick the noise distribution (and its skew), and the win probabilities update live — computed in your browser by the factor lattice algorithm this package ships, at verified parity with the Python. Runners loading the same factor with the same sign are teammates, opposite signs rivals; zero loadings recover the independent race, where Gumbel noise reproduces softmax exactly.

noise:

Forward pricing to ten million, inversion to one million. All shares of a correlated race in one O(QNL) pass, with graph-Laplacian derivatives that are matrix-free for the factor grammar, and inversion of observed shares back to utilities. A million alternatives price in 29 seconds under a rank-one factor; inversion at a million takes 80 seconds independent and about twenty minutes rank-one — every number from a committed, seeded script. The paper (PDF, tag paper-r11) →
Rating systems live on this engine. Whole-density beliefs, exact full-finish-order updates, benchmarked prequentially on twelve datasets against TrueSkill, OpenSkill, Glicko-2 and Elo. The ratings page →

Quick start

from winning import race_probabilities, calibrate_abilities, removal_shares

p = race_probabilities(mu, V=V, D=D)     # all N shares, one field pass
mu_hat = calibrate_abilities(p, V=V, D=D)  # abilities back from shares
q = removal_shares(mu, V=V, D=D)         # P(j wins | i removed), all pairs

Max-wins semantics for the probit literature live in winning.probit (shares, calibrate_utilities, supplied-covariance fitting); the density-agnostic engine in winning.thurstone; the paper-faithful kernels in winning.factor.

One race, five covariance grammars

Every model in the package is the same Gaussian min-race $Y = \mu + \text{noise}$; the grammars are declarative descriptions of the noise covariance that admit $O(N)$-per-lattice-point evaluation. Pass any of them as structure= to the front-door verbs.

from winning import (Independent, Factor, Blocks, Nested, Tree,
                     race_probabilities, polish_race)

tree = Tree.from_linkage(Z)                    # floored cophenetic correlation
race_probabilities(mu, structure=Factor(V, D))        # Σ = VV' + diag(D)
race_probabilities(mu, structure=Blocks(cluster, loading, D))
race_probabilities(mu, structure=Nested(cluster, loading, D, coupling, gamma))
race_probabilities(mu, structure=tree)
polish_race(p0=w, structure=tree, name_caps=0.05)     # nearest race under caps

Tree.from_linkage builds the race whose implied correlation is the floored cophenetic correlation of a hierarchical clustering (merge height maps through $\rho=\max(1-2h^2,0)$; negative cophenetic correlation has no tree representation) — so a portfolio's HRP weights can be inverted, re-priced and polished along the dendrogram they came from. Analytic fixed-grid Jacobians (rows sum to zero; off-diagonals are photo-finish tie densities) ship for the factor, block and nested grammars, with preconditioned Newton inversion throughout. An arbitrary dense $\Sigma$ is priced by fitting the grammar family (seriated blocks under global factors) and promoting the residual to extra factor dimensions — one seeded, reproducible call that beats million-draw Monte Carlo on wall clock at $n = 2000$ and prices tail probabilities Monte Carlo cannot see.

Languages

The numpy implementation is the spec. The compiled kernels (fastrace, thin pyo3 bindings over the pure-rust winning crate) accelerate every path — 232× on the classic calibration, input-bound to ten million runners on the block field — and the base-R package mirrors the complete API with no compiled dependency. All ports are parity-locked: parity/vectors.json embeds inputs and outputs from the reference, and every language replays the same twenty-two scenarios — nineteen to within 1e-7 (most to 1e-10), the three fit- or optimizer-mediated ones to between 5e-4 and 5e-3.

pip install winning          # pure python (numpy/scipy)
pip install winning[fast]    # + compiled kernels (abi3 wheels)
remotes::install_github("microprediction/winning", subdir = "r/winning")

Random test covariances come from randomcov: fifteen named ensembles, because “a random covariance matrix” means nothing until the measure is named.

Papers

Older presentations

Demos

Heritage

The fastest time, the best offer and
        the most popular product are the same order statistic: winner of many.
The fastest time, the lowest offer and the most popular choice are the same computation: the distribution of the winner of many.

winning began as the reference implementation of the SIAM paper above. By Peter Cotton, with sibling packages at microprediction. The same computation — inferring latent ability from who wins — has been rediscovered field by field for a century, from Thurstone's 1927 law of comparative judgment to language-model leaderboards: the heritage, as a timeline →

Notes: disks do not fail independently — a common-cause factor in the public Backblaze data, and what it costs erasure-coding durability.

Get the source

github.com/microprediction/winning · pip install winning · Research scripts