Metadata-Version: 2.4
Name: winning
Version: 1.1.0
Summary: Dealing with races, correlated or not
Home-page: https://github.com/microprediction/winning
Author: microprediction
Author-email: peter.cotton@microprediction.com
License: MIT
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: scipy
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pandas; extra == "test"
Provides-Extra: benchmarks
Requires-Dist: pandas; extra == "benchmarks"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: summary

# winning

*A package for dealing with races, correlated or not.*

`winning` began as the reference implementation of the lattice ability
transform (SIAM J. Financial Mathematics, 2021) and owns the whole line:
the original density-agnostic engine, the factor-correlated
generalization developed for "Scalable Share Calibration for Factor
Multinomial Probit Models", an arena of competing methods, and a
standing benchmark database.

- `winning.thurstone` — the core engine, vendored home from the
  thurstone package (now a compatibility shim). Densities on a lattice,
  winner-of-many, dead heats, and the ability transform, for **any**
  base distribution.
- `winning.factor` — the correlated extension: all-share forward pass,
  share calibration, Jacobian-vector products, and factor fitting. One
  general race, `race_probabilities`, takes the distribution and the
  factor rank as parameters; factor probit, the classic independent
  transform, Luce/softmax, and correlated softmax are named special
  cases, and custom standardized bases plug in as callables. The
  Gaussian specialization keeps its dedicated tail-exact kernel.
- `winning.methods` — every contestant behind one interface: the
  lattice transform, direct and Sobol simulation, per-alternative
  factor-RQMC, GHK / Genz separation-of-variables, minimax tilting.
  Each passes closed-form and Monte Carlo anchors before admission.
- `winning.bench` — a seeded problem grid, cached references, and
  append-only accuracy-time records: `python -m winning.bench.runner`.

[![CI](https://github.com/microprediction/winning/workflows/CI/badge.svg)](https://github.com/microprediction/winning/actions)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

![The fastest time, the best offer and the most popular product are the same order statistic](docs/assets/images/winning-pic.png)

## Install

    pip install winning        # core depends only on numpy and scipy

## Quick start

Independent race: shares from abilities, and back.

```python
import numpy as np
from winning import race_probabilities, calibrate_abilities

mu = np.array([-0.5, 0.0, 0.2, 0.3])          # lower is better (min-wins)
p = race_probabilities(mu)                     # array([0.443, 0.232, 0.175, 0.150])
mu_back = calibrate_abilities(p)               # recovers mu (mean zero)
```

Correlated race: a hundred runners moved by two common factors, all
shares in one pass over a shared survival field, then inverted.

```python
rng = np.random.default_rng(0)
N, k = 100, 2
mu = rng.normal(0, 1, N); mu -= mu.mean()
V = rng.normal(0, 0.4, (N, k))                # factor loadings
D = rng.uniform(0.5, 1.5, N)                  # idiosyncratic variances

p = race_probabilities(mu, V=V, D=D)          # all N shares, O(QNL)
mu_hat = calibrate_abilities(p, V=V, D=D)     # inversion
```

Counterfactuals and structure from the same shared field:

```python
from winning import removal_shares, tie_densities

q = removal_shares(mu, V=V, D=D)   # q[i][j] = P(j wins | i removed)
w = tie_densities(mu, V=V, D=D)    # photo-finish weights: the Jacobian's
                                   # graph-Laplacian (circuit) conductances
```

For the probit literature, `winning.probit` speaks max-wins utilities
and shares directly — the paper's own conventions — and is the one
audited reflection onto the internal min-wins race. Both of the paper's
calibrations live here: utilities from observed shares, and the factor
structure itself from a supplied covariance.

```python
from winning.probit import shares, utilities_from_shares, fit_factor_model

utilities = -mu                            # higher is better on this side
p = shares(utilities, V=V, D=D)            # all N choice probabilities
u = utilities_from_shares(p, V=V, D=D)     # the paper's calibration
Sigma = V @ V.T + np.diag(D)
V_hat, D_hat = fit_factor_model(Sigma, k=2)  # certified rank-k contrast fit
p2 = shares(utilities, Sigma=Sigma, k=2)   # same fit applied en route
```

One race, everything a parameter: distribution and correlation chosen
per call, with factor probit just one named point in the family.

```python
from winning.factor import race_probabilities

race_probabilities(mu)                       # the classic independent race
race_probabilities(mu, V=V, D=D)             # factor probit
race_probabilities(mu, base="gumbel")        # Luce / softmax, exactly
race_probabilities(mu, V=V, base="gumbel")   # correlated softmax
race_probabilities(mu, temperature=0.7)      # E[softmin(X/tau)]: soft credit
```

Temperature is exact, not approximate: by the Gumbel-argmin identity the
softmin expectation equals the hard race with each base convolved with
the tau-scaled Gumbel kernel, so the same engine serves it. It is not
identifiable from a single race, so inversion holds it fixed.

Arbitrary densities (skewed, multimodal, empirical) run through custom
bases or `winning.thurstone` — see the module docs and `research/demos/`.

## The paper

The correlated calibration is documented in *Scalable Share Calibration
for Factor Multinomial Probit Models*
([papers/factor-probit-transform](papers/factor-probit-transform),
submitted): all shares of a correlated Gaussian race in one O(QNL)
pass, matrix-free graph-Laplacian derivatives, and inversion at ten
thousand alternatives in under a minute. Every number comes from a
committed, seeded script in
[research/experiments](research/experiments) (index in its README);
`research/experiments/run_all_paper.py` regenerates the lot.

## Demos and other languages

[research/demos](research/demos) holds explanatory scripts (the shared
survival field, the cavity downdate). [js/factor](js/factor) is a
dependency-free JavaScript port at machine-precision parity with the
Python, for browser demos; [r/winning](r/winning) is a pure-R package;
[rust/fastrace](rust/fastrace) holds the optional compiled kernels —
build with `pip install maturin && maturin develop --release`, and
`winning.methods` uses them automatically. Julia is on the roadmap.

## Rating systems (research line)

The renovation-era ratings layer — whole-density beliefs, exact
full-finish-order updates, benchmarked against TrueSkill, OpenSkill,
Glicko-2 and Elo on twelve datasets — lives in [src/](src) pending
integration, with results in [BENCHMARKS.md](BENCHMARKS.md). Headlines:
decisive win on Formula 1 (1,158 grands prix), best calibration on
chess (ECE 0.0047), statistical ties atop WTA/ATP/EPL, and markets
remaining the ceiling wherever they exist. The `ThurstoneRating` API
documented there ships with a future release; it is not importable from
the current package.

## History

Versions 1.x were the SIAM paper's reference implementation, and those
imports still work. A 2.0 renovation explored splitting the numerical
core into the separate thurstone package with winning as an
applications layer; the decision went the other way. `winning` owns the
core — heritage and name — the thurstone implementation is vendored
here as `winning.thurstone`, and the thurstone package is a
compatibility shim whose imports resolve to this one. The renovation's
migration notes and unported ideas are preserved in
[planning/](planning) and [attic/](attic).

## Cite

    @article{doi:10.1137/19M1276261,
    author = {Cotton, Peter},
    title = {Inferring Relative Ability from Winning Probability in Multientrant Contests},
    journal = {SIAM Journal on Financial Mathematics},
    volume = {12},
    number = {1},
    pages = {295-317},
    year = {2021},
    doi = {10.1137/19M1276261},
    URL = {https://doi.org/10.1137/19M1276261}
    }
