Understand the available library surfaces
mainThe library provides three primary surfaces for interaction. Note that the GUI has been deprecated/deleted.
| Surface | Reach | Tested |
|---|---|---|
| Python API | everything | yes |
| CLI | everything | yes |
| MCP server | everything | yes |
repository·main·Indexed 20 days ago
https://github.com/georgedouzas/sports-bettingA toolkit for building, testing, and executing sports betting models. It provides dataloaders for gathering statistics and odds, and bettors that wrap scikit-learn estimators to backtest strategies and identify value bets. The library is accessible via a Python API, a CLI (sportsbet command), and an MCP server for AI agents. Key features include the ClassifierBettor, OddsComparisonBettor, and BettorGridSearchCV for hyperparameter tuning.
The library provides three primary surfaces for interaction. Note that the GUI has been deprecated/deleted.
| Surface | Reach | Tested |
|---|---|---|
| Python API | everything | yes |
| CLI | everything | yes |
| MCP server | everything | yes |
The sports-betting library provides three distinct ways to interact with its data, models, and betting logic. Choose the interface based on your workflow:
sportsbet command for shell-based operations. This allows you to extract data, run backtests, fit models, and place bets without writing any Python code.Regardless of the interface chosen, all sports, data sources, and models remain consistent across all three methods.
The sportsbet.datasets module provides the user-facing data interface for loading and extracting sports betting datasets. It follows a scikit-learn-style interface for data loading and feature extraction.
The following symbols are exported by sportsbet.datasets.__all__:
BaseDataLoader (Base class)SoccerDataLoader (Concrete implementation)DummySoccerDataLoader (Offline implementation using sample data)load_dataloader (Utility to reload a saved loader)BaseStatsSchema, BaseOddsSchema (Data schemas)required_col, optional_col (Column validation utilities)The system operates under a strict 'no-evasion' policy. It is designed to automate accounts that the user already holds, rather than attempting to defeat venue-level security controls.
When using different providers for statistics and odds, the library performs a reconciliation (join) process to match matches across sources (e.g., mapping "Man United" to "Manchester United").
Reconciliation Features:
The project uses a hybrid storage strategy to balance performance, schema stability, and data retention:
pyarrow with zstd compression). These are partitioned by source/sport/league/season to allow efficient slicing. Parquet is used specifically to preserve strict data types (e.g., preventing empty columns from being cast to objects).RawItem. Raw data is retained indefinitely to allow for rebuilding derived tables without re-fetching (and re-paying for) the data.To create a new data source, you must subclass BaseSource (located in src/sportsbet/datasets/_sources/_base.py) and implement several abstract methods. A source is responsible for defining what parameters it supports and how to transform raw payloads into long-format snapshots.
index_items(): Return a list of RawItem objects needed to discover available data. This must be a 'free' operation (no network/file access).catalogue(payloads): A pure function that parses index payloads into a list of Param objects (combinations of league/division/year).required_items(params): A pure, deterministic function that returns the RawItem list needed to satisfy a specific list of Param objects.to_snapshots(payloads): A pure function that transforms RawPayload objects into a pd.DataFrame in a long format (e.g., the stats table or odds table).index_items, catalogue, required_items, and to_snapshots must be pure. They must not open sockets, access the filesystem, or perform network requests. This ensures that prepare(dry_run=True) remains free and side-effect-free.available_params is an instance method, not a class method, because availability depends on the specific instance configuration (e.g., API keys or subscription tiers).RawItem. Credentials should be stored on the source instance and injected into request headers at fetch time.BaseStatsSource or BaseOddsSource as marker subclasses to allow the dataloader to type-check that the correct source type is provided for stats= or odds= arguments.class BaseSource(ABC):
name: ClassVar[str]
kind: ClassVar[str] # 'stats' or 'odds'
def available_params(self, store: BaseStore | None = None) -> list[Param]: ...
@abstractmethod
def index_items(self) -> list[RawItem]: ...
@abstractmethod
def catalogue(self, payloads: list[RawPayload]) -> list[Param]: ...
@abstractmethod
def required_items(self, params: list[Param]) -> list[RawItem]: ...
@abstractmethod
def to_snapshots(self, payloads: list[RawPayload]) -> pd.DataFrame: ...
def estimate(self, items: list[RawItem]) -> int: ...To ensure clean dependency management and avoid circularity, adhere to the following import rules:
import statement, with the sole exception of deferred optional extras.To ensure reliability, all documentation examples are verified through two automated processes during the build:
docs/examples is executed during the documentation build.doctest.Constraints for examples:
The NBA data model follows the same structure as the EuroLeague model, consisting of three primary hierarchical entities: Season, Game, and Snapshot.
2026).The library uses a Configuration object to define what the user wants to extract.
A single-event execution follows a linear progression for both the event status and the execution unit's internal state.
The event status advances in a single direction:
preplay $\rightarrow$ kickoff $\rightarrow$ inplay $\rightarrow$ final whistle $\rightarrow$ postplay
The unit moves through these stages:
bound (timeout) is hit.