Skip to main content

OO toolkit for lattice-based performance models and the horse-race inverse problem

Project description

thurstone

An object‑oriented toolkit for lattice‑based performance models and the horse‑race inverse problem (inferring relative ability from market prices, a.k.a. the ability transform). This package seeks to revitalize Thurstone Class V models which have tended to play a poor cousin to Plackett-Luce and other alternatives due to lack of tractability. It implements a relatively recent fast algorithm.

Uses

(Beyond horseracing)

See the notebook for examples of the use of this ability transform.

See the paper for why this is useful in lots of places, according to a wise man. For instance, the algorithm may also find use anywhere winning probabilities or frequencies are apparent, such as with e-commerce product placement, in web search, or, as is shown in the paper: addressing a fundamental problem of trade.

Highlights

This is the successor to the winning package. Essentially a clean up and mild generalization. New and inherited functionality includes:

  • Uniform lattice with explicit L and unit (UniformLattice).
  • Normalized Density with safe integer/fractional shifts, centering, convolution, and dilation. Negative mass is rejected; zero‑mass vectors are allowed as an explicit off‑lattice sentinel in extreme shifts.
  • Clean Race and StatePricer API for risk‑neutral state prices (winning probabilities), now multiplicity‑aware.
  • AbilityCalibrator solves the inverse problem with per‑runner monotone interpolation (sorted price→offset tables) and returns abilities in physical units.
  • ClusterSplitter handles offsets that hang off the lattice (both directions) with symmetric clustering and coarse‑to‑fine recursion, including walkover behavior and an equal‑share rule only when all offsets hang on one side and are tightly bunched (spread < support width).
  • order_stats module: multiplicity‑aware winner_of_many and expected_payoff_with_multiplicity (draws split by 1/(1 + multiplicity)).
  • Tie handling via pluggable TieModel (default: 0.5 split).

Quickstart

from thurstone import UniformLattice, Density, AbilityCalibrator, STD_L, STD_UNIT

lat = UniformLattice(L=STD_L, unit=STD_UNIT)
base = Density.skew_normal(lat, loc=0.0, scale=1.0, a=0.0)  # symmetric base

# Inverse calibration from dividends -> abilities (physical units)
from thurstone import StatePricer
dividends = [3.2, 4.8, 12.0, 7.5, 20.0]
cal = AbilityCalibrator(base)
ability = cal.solve_from_dividends(dividends)     # abilities in same units as lattice grid
prices = cal.state_prices_from_ability(ability)   # forward map (prices sum to 1)

Design notes

  • Fractional shifts are performed on the CDF then differenced back to preserve mass and monotonicity.
  • The inverse loop builds per‑runner (price, offset) tables (holding others fixed), sorts them by price, uniques on the price key, clips, and uses np.interp.
  • ClusterSplitter splits at the largest gap near the center, evaluates both sides, and combines refined within‑group prices using coarse group shares from a dilated lattice. It exhibits:
    • Walkover: sufficiently better (left) runners take ~1, sufficiently worse (right) get ~0.
    • Equal‑share only when all runners hang on the same side and are indistinguishable at resolution (spread < support width).
  • Forward pricing and inverse calibration use multiplicity‑aware payoffs: win + draw/(1 + multiplicity_rest). This improves accuracy in dense/tie regimes.

Testing

  • Optional test extras: pip install -e ".[test]"
  • Run tests: pytest -q
  • Property tests (Hypothesis) are auto‑skipped if Hypothesis is not installed.
  • A performance benchmark (pytest‑benchmark) is included and auto‑skips if the plugin is missing.
  • Multiplicity tests ensure clone ties scale multiplicity correctly and that multiplicity‑aware payoffs differ from naive half‑point splits.

Examples

  • Plot offset densities for 150 runners:
    • Requires matplotlib: pip install matplotlib
    • Run: python examples/plot_offset_densities_150.py
  • 2D calibration with per‑runner scales (150 runners, scales 15→20):
    • Run: python examples/calibrate_with_scales_150.py

Interactive Visualizations

Explore Thurstone models interactively in your browser:

  • Diffeomorphism Explorer: Interactive visualization of cube-to-simplex mappings using racing dynamics with real-time parameter controls
  • All Interactive Demos: Collection of browser-based visualizations and educational tools

Run locally: python -m http.server 8000 --directory docs then visit http://localhost:8000

Cite

See

  • Cotton, Peter. “Inferring Relative Ability from Winning Probability in Multientrant Contests,” SIAM Journal on Financial Mathematics, 12(1), 295–317 (2021). DOI: https://doi.org/10.1137/19M1276261
  • Original reference implementation and additional context: https://github.com/microprediction/winning

BibTeX:

@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}
}

Contribute

The most obvious improvement would be a rust implementation.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thurstone-0.1.0.tar.gz (102.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

thurstone-0.1.0-py3-none-any.whl (127.3 kB view details)

Uploaded Python 3

File details

Details for the file thurstone-0.1.0.tar.gz.

File metadata

  • Download URL: thurstone-0.1.0.tar.gz
  • Upload date:
  • Size: 102.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for thurstone-0.1.0.tar.gz
Algorithm Hash digest
SHA256 11042a3b140b67c6d8e2dc766deed1484ba0e7bb507ea225a5940f48153ef9a9
MD5 2c52851c32f5b54a3bffc52c3746be7a
BLAKE2b-256 f13c1b4224048a98a86f086a8971996fcdab634909c49cd6487f49ddc7fbac19

See more details on using hashes here.

File details

Details for the file thurstone-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: thurstone-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 127.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for thurstone-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a268af2d6c15b4b90e9acc76c2414e5e652eb5bddb9796b1f783c45f44ebddd9
MD5 b2408dae57e80e3853b73afde19f8455
BLAKE2b-256 46ed52d86faece93ee87a22d70acb363a362011ce7985b99820d755bf78f52b3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page