Skip to main content

mlb-ml-lab

MLB prediction models — fetch player and team data, build feature matrices, train models, and evaluate hit over/under forecasts.

Features

  • Zero ML dependencies (no pybaseball, pybaseballstats, python-mlb-statsapi). A custom httpx-based client wraps statsapi.mlb.com and baseballsavant.mlb.com directly.
  • Typed schemas throughout — PlayerGameLog, TeamInfo, RosterPlayer, etc. are typed dataclasses.
  • Disk caching with per-key TTL — avoids hammering the MLB API during development.
  • Rate limiting — built-in token bucket (10 req/s).
  • Park factors scraped live from Baseball Savant with static fallbacks.
  • NWS weather forecasts — free, no API key, covers every MLB venue.
  • Feature engineering pipeline — plugin-based extractors with a registry pattern, designed to be extractable as its own package.
  • Walk-forward validation — no random train/test splits. Sports data is temporally dependent.

Installation

# Clone the repo
git clone https://github.com/timhollingsworth/mlb-ml-lab
cd mlb-ml-lab

# Install with Poetry
poetry install

Requires Python 3.12+.

Quick Start

Fetch player game logs

from mlb_ml_lab import MlbClient

client = MlbClient()

# Get all teams
teams = client.get_teams()

# Get roster for a team (Angels = 108)
roster = client.get_roster(108)

# Get game logs for a player (Shohei Ohtani = 660271)
logs = client.get_player_game_log(660271, season=2024)

# Each log has typed fields
for log in logs:
    print(log.date, log.hits, log.at_bats)

Fetch game context (venue, weather, datetime)

# Game feed gives you venue, weather, and game datetime
feed = client.get_game_context(778554)
# → {"venue_id": 4, "venue_name": "Rate Field",
#    "game_datetime": "2025-03-27T20:10:00Z",
#    "weather_condition": "Cloudy", "weather_temp": "68", ...}

Build a feature matrix

from mlb_ml_lab import MlbClient, build_feature_matrix, describe_features, make_targets

client = MlbClient()

# 1. Fetch data
teams = client.get_teams()
logs = client.get_player_game_log(660271, season=2024)
contexts = {778554: client.get_game_context(778554)}

# 2. Assemble features (runs all registered extractors)
matrix = build_feature_matrix(
    logs,
    season=2024,
    teams=teams,
    extra_kwargs={"game_contexts": contexts},
)

# 3. See what features are available
metas = describe_features()
for m in metas:
    print(f"{m.name:40s} {m.source:10s} {m.description}")

# 4. Create target labels
targets = make_targets(logs)

Weather forecast for an upcoming game

from datetime import datetime
from mlb_ml_lab import NwsWeather

nws = NwsWeather()

# Angel Stadium (venue_id=1) at game time
forecast = nws.forecast(1, target_time=datetime(2025, 7, 4, 19, 7))
# → {"temp": 75, "wind_speed": "8 mph", "wind_direction": "SW",
#    "precip_pct": 10, "conditions": "Partly Cloudy", "source": "forecast"}

Park factors

from mlb_ml_lab import ParkFactors

pf = ParkFactors()
# Coors Field (venue_id=19) 2024 wOBA factor
factor = pf.factor(19, "wOBA", season=2024)
print(factor)  # e.g. 1.11 (11% boost)

GPU-accelerated models (Apple Silicon)

A full neural model toolbox runs on Apple's MLX framework (Metal GPU):

Model Description File
MlxNNClassifier sklearn-compatible MLP models/mlx_nn.py
SequenceHitPredictor GRU over 15-game stat windows models/sequence.py
HybridHitPredictor GRU + context-feature MLP models/sequence.py
MultiTaskHybridPredictor Shared encoder + two heads (0.5/1.5 targets) models/sequence.py
DCNMultiTaskPredictor Deep & Cross Network on context features models/sequence.py
TransformerMultiTaskPredictor Transformer encoder replacing GRU models/sequence.py

All plug into the walk-forward training pipeline via --model mlx or as ensemble components. Benchmark: pipeline/benchmark_mlx.py.

Project Structure

mlb-ml-lab/
├── src/
│   └── mlb_ml_lab/
│       ├── data/               # Data layer (installable)
│       │   ├── client.py       # MlbClient — MLB Stats API + Baseball Savant
│       │   ├── schemas.py      # Typed dataclasses
│       │   ├── cache.py        # DiskCache (JSON, per-key TTL)
│       │   ├── rate_limiter.py # TokenBucket rate limiter
│       │   ├── parks.py        # ParkFactors (Savant scrape + fallback)
│       │   └── weather.py      # NwsWeather (NWS API, free, no key)
│       └── features/           # Feature engineering (installable)
│           ├── base.py         # FeatureExtractor ABC, registry
│           ├── rolling.py      # Rolling window stats (hits, PA, BABIP)
│           ├── context.py      # Home/away, rest days, park factors, weather
│           ├── matchup.py      # Opponent pitching stats
│           ├── statcast.py     # Statcast advanced metrics
│           ├── forecast.py     # NWS weather forecast features
│           ├── assemble.py     # build_feature_matrix(), describe_features()
│           └── targets.py      # make_targets() for hit thresholds
├── pipeline/                   # Modeling (training, prediction, evaluation)
├── tests/
│   ├── data/                   # Tests for data layer
│   ├── features/               # Tests for feature engineering
│   ├── models/                 # Tests for model training/evaluation
│   └── evaluation/             # Tests for backtesting/calibration
├── data/                       # Raw/processed datasets (gitignored)
│   └── betting/                # P&L tracking (pnl.json)
├── experiments/                # Analysis scripts (not notebooks)
├── pyproject.toml
├── README.md
├── LICENSE
├── AGENTS.md                   # Dev instructions (AI assistant)
└── ROADMAP.md                  # Build-out plan

CLI

A command-line interface is available after install:

# Fetch data and build feature matrix
mlb fetch --seasons 2024 2025 --max-players 20

# Walk-forward validation training
mlb train --use-cached

# Predict on a season with a saved model
mlb predict --season 2026

# Walk-forward backtest with betting simulation (single model)
mlb backtest --model lgb

# Ensemble backtest (uniform average of all four)
mlb backtest --model lr,xgb,rf,lgb

# Hyperparameter tuning
mlb tune --trials 20

# Quick end-to-end for one team
mlb e2e --team-id 108 --season 2024

Daily betting strategy

The mlb bet command generates player-prop bets from a uniform-average ensemble of LogisticRegression, XGBoost, RandomForest, and LightGBM:

# Generate today's bets (P(hit ≥ 1) > 0.55, $1 per bet)
mlb bet

# Settle yesterday's bets and update P&L
mlb bet --settle

# View running P&L
mlb bet --pnl

# Custom threshold and stake
mlb bet --threshold 0.60 --stake 5.00

# Use a trained single model instead of ensemble
mlb bet --model-dir data/models/final_0_5

# Specific date
mlb bet --date 2026-07-23

Backtest results (4-season walk-forward, 2021–2024)

Target: P(hit ≥ 1) — Ensemble: 96K bets at 0.55 threshold, +22.49% ROI. AUC 0.639 across 155K out-of-sample predictions.

Thresh    Bets  WinRate       ROI    MaxDD
 0.55    96632   0.6416    +22.49%    0.10%
 0.60    71112   0.6658    +27.11%    0.04%
 0.65    43105   0.6907    +31.84%    0.02%
 0.70    18000   0.7191    +37.27%    0.35%
 0.75     4403   0.7533    +43.81%    2.49%

Target: P(hit ≥ 2) — Not viable: 33 bets total with -36% ROI.

The system is self-calibrated (no market odds required). See the ROADMAP for full details.

Development

# Run fast tests (no live API calls)
poetry run pytest

# Run all tests including live API calls
poetry run pytest --runslow

# Run a single test
poetry run pytest tests/features/test_forecast.py::TestWeatherForecastFeatures::test_indoor_venue_returns_indoor -v

# Lint
poetry run ruff check .

# Format
poetry run ruff format .

Adding a new feature extractor

  1. Create a new module in src/mlb_ml_lab/features/ (e.g. src/mlb_ml_lab/features/schedule.py).
  2. Subclass FeatureExtractor, implement features and extract.
  3. Decorate with @register.
  4. Import it in src/mlb_ml_lab/features/__init__.py.
  5. It will automatically be discovered by build_feature_matrix().

Data Sources

Source Endpoint Key Required Notes
MLB Stats API statsapi.mlb.com/api/v1/ No Rate limit ~10 req/s
Baseball Savant baseballsavant.mlb.com/leaderboard/ No CSV download, BOM stripping required
NWS API api.weather.gov No (User-Agent required) Free, no key, hourly forecasts

License

MIT

Download files

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

Source Distribution

mlb_ml_lab-0.3.1.tar.gz (101.7 kB view details)

Uploaded Source

Built Distribution

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

mlb_ml_lab-0.3.1-py3-none-any.whl (125.0 kB view details)

Uploaded Python 3

File details

Details for the file mlb_ml_lab-0.3.1.tar.gz.

File metadata

  • Download URL: mlb_ml_lab-0.3.1.tar.gz
  • Upload date:
  • Size: 101.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for mlb_ml_lab-0.3.1.tar.gz
Algorithm Hash digest
SHA256 2ee6d134706af3aecf7c6182ee3d00b5641e044a007a5236b9c9d11d2a6139c3
MD5 cadba548a8aac803efc6e08a7a8a51b4
BLAKE2b-256 df7c5841165eeabaa4cfe0bb5cfcbdd3f71b113ca3bdf53158d2349e6471b95e

See more details on using hashes here.

Provenance

The following attestation bundles were made for mlb_ml_lab-0.3.1.tar.gz:

Publisher: python-publish.yml on SecuritahGuy/mlb-ml-lab

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

File details

Details for the file mlb_ml_lab-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: mlb_ml_lab-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 125.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for mlb_ml_lab-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 363002853ec53c7cba827f378c6c84575de756ecede0f206676dad2b1ab1cd5c
MD5 a070af75b19b8754aa3c5fd182051cb6
BLAKE2b-256 0b12cb0abb67778679c560ae0c07c88fe87b41bd452de74876e04c72a521cbd7

See more details on using hashes here.

Provenance

The following attestation bundles were made for mlb_ml_lab-0.3.1-py3-none-any.whl:

Publisher: python-publish.yml on SecuritahGuy/mlb-ml-lab

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

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 files

0.2.2

2 files

0.1.0

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