Skip to main content

Keeks-Elote

License: MIT

A Python library integrating the elote rating system library and the keeks bankroll management library to facilitate backtesting and evaluation of combined ranking and betting strategies.

Purpose

The primary goal of keeks-elote is to provide a framework for simulating and analyzing the performance of different rating algorithms (like Elo, Glicko, etc.) when coupled with various bankroll management strategies (like Kelly Criterion, fixed betting, etc.). This allows users to explore how prediction accuracy from rating systems translates into profitability under different staking plans in competitive scenarios (e.g., sports betting, gaming).

Why is this interesting? (Features)

  • Integration: Seamlessly combines rating generation (elote) with betting strategy simulation (keeks).
  • Backtesting Framework: Provides tools to run historical simulations on outcome data.
  • Flexibility: Supports multiple rating systems and bankroll management techniques available in the underlying libraries.
  • Evaluation: Enables analysis of strategy performance based on metrics like profit/loss, ROI, etc.
  • Extensibility: Designed to be potentially extended with custom rating models or betting strategies.

Installation

pip install keeks-elote

Or from source:

git clone https://github.com/wdm0006/keeks-elote.git
cd keeks-elote
pip install -e .

For development, clone the repository and install in editable mode with development dependencies:

git clone https://github.com/wdm0006/keeks-elote.git
cd keeks-elote
pip install -e .[dev]

How to Use It

The core idea is to use elote to generate ratings and predictions based on historical match/game data and then use keeks to simulate betting on those predictions according to a chosen bankroll strategy.

You provide historical outcomes as a Dict[int, List[dict]] keyed by period (e.g. week). Each game dict needs winner and loser labels, plus optional winner_odds/loser_odds in American odds (bets are only placed on games that include odds):

from elote.arenas.lambda_arena import LambdaArena
from elote.competitors.glicko import GlickoCompetitor
from keeks.bankroll import BankRoll
from keeks.binary_strategies.kelly import KellyCriterion

from keeks_elote import Backtest

# Historical outcomes, keyed by period (e.g. week). Ratings update from the
# known winner/loser; odds drive the simulated bets in later periods.
data = {
    1: [{"winner": "Alabama", "loser": "Auburn", "winner_odds": -150, "loser_odds": 130}],
    2: [{"winner": "Georgia", "loser": "Florida", "winner_odds": -200, "loser_odds": 175}],
    # ... more periods ...
}

# The arena generates ratings and predictions from the game records. Every game's
# recorded winner is always forwarded to the ratings update, so the lambda is
# never asked to decide a result the data already knows.
arena = LambdaArena(lambda a, b: True, base_competitor=GlickoCompetitor)

# The bankroll and a betting strategy from keeks.
bankroll = BankRoll(initial_funds=10000, percent_bettable=0.5, max_draw_down=1.0)
strategy = KellyCriterion(payoff=1.0, loss=1.0, transaction_cost=0.0)

# Periods up to `period_to_start_betting` are dry runs that only build ratings;
# real bets begin after it. Returns the updated bankroll.
backtest = Backtest(arena)
result = backtest.run_explicit(data, strategy, bankroll, period_to_start_betting=1)
print(result.total_funds)

# Every wager the run settled is also recorded, so a comparison run can be read
# beyond its closing balance.
print(len(backtest.bet_history))

The closing total_funds conflates hit rate, stake sizing and how many bets were even placed, so run_explicit also fills Backtest.bet_history: one dict per wager the run considered, settled or not, carrying period, label, opponent, fraction, the stake actually placed (after the period's exposure scaling and any clamp against bettable funds), payoff, won, profit and bankroll_after. Candidates that moved no money are recorded too, flagged with skipped_zero_stake or error, so every bet the run considered is accounted for. The list is cleared at the start of each run_explicit call, so reusing a Backtest never mixes two runs. Aggregations such as ROI or hit rate are one line of caller code over it.

Failures are part of that accounting: a strategy that raises while pricing a candidate is recorded the moment it fails (fraction of None plus the error message), and Backtest.run_summary() condenses the ledger into counts -- placed, failed with their reasons, skipped, wins/losses and net profit -- so a systematically broken strategy reads as failed_bets: N, never as an empty, plausible-looking run.

Strategies that maintain state through keeks' record_result(won, return_pct) hook -- DynamicBankrollManagement's streak and volatility windows, for example -- are notified of every bet the run actually settles, so their sizing adapts as the backtest progresses. Strategies without the hook are unaffected, and stateful strategies are always notified on the instance you passed in, even when each bet is priced by a freshly constructed re-priced copy. The notification is skipped for candidates that moved no money (a zero stake or a failed settlement), since there is no settled result to record.

See examples/cfb.py for a complete end-to-end example using real college-football data.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Download files

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

Source Distribution

keeks_elote-0.2.0.tar.gz (434.9 kB view details)

Uploaded Source

Built Distribution

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

keeks_elote-0.2.0-py3-none-any.whl (19.3 kB view details)

Uploaded Python 3

File details

Details for the file keeks_elote-0.2.0.tar.gz.

File metadata

  • Download URL: keeks_elote-0.2.0.tar.gz
  • Upload date:
  • Size: 434.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for keeks_elote-0.2.0.tar.gz
Algorithm Hash digest
SHA256 199da72e1acf2ccee9886d75a8eee3b1bc825c029e73e27bb19fe0c21fb36e64
MD5 21820e465069119ba989c0f408714c6a
BLAKE2b-256 fed4902557c8805be8caada1b343d7063d7378e2e22a611e17727dfab45e2efb

See more details on using hashes here.

Provenance

The following attestation bundles were made for keeks_elote-0.2.0.tar.gz:

Publisher: publish-pypi.yml on wdm0006/keeks-elote

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file keeks_elote-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: keeks_elote-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 19.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for keeks_elote-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fe973a7c1464a60f2d0080b004a45bac4c9b6b81dfd97f166c845d1ff393e13e
MD5 51937dea5390bb4929070be4acb2757c
BLAKE2b-256 5cc6760909bdd9c05f5258184c0ce575b173131d8da7c4ee04a73eb2775a085e

See more details on using hashes here.

Provenance

The following attestation bundles were made for keeks_elote-0.2.0-py3-none-any.whl:

Publisher: publish-pypi.yml on wdm0006/keeks-elote

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.0

2 files

This release

0.2.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page