Skip to content

SecuritahGuy/StatSpace-Nine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StatSpace Nine

StatSpace Nine is a public sports-modeling portfolio repo. The first flagship project inside it is a clean-room MLB Elo engine that tracks both team strength and starting-pitcher strength, supports walk-forward backtesting, and exposes a small CLI for building snapshots and daily predictions.

This public v1 is intentionally narrower than the internal research system it is based on. The goal here is to ship a runnable, inspectable, well-tested artifact with clean interfaces rather than a direct dump of private production code.

Why MLB Elo

Elo is a strong baseline for baseball because it gives you a simple, interpretable rating system that updates one game at a time and remains useful even before you layer in richer features. For a public portfolio repo, that matters:

  • the model logic is easy to audit
  • the walk-forward workflow is explicit
  • each design choice can be documented and tested
  • advanced modules can be added later without breaking the core engine

What Ships In Public V1

  • Team Elo ratings
  • Starter Elo ratings
  • Home-field advantage
  • Margin-of-victory scaling
  • Starter confidence shrinkage for small samples
  • Season-to-season mean reversion toward baseline
  • Walk-forward processing in chronological order
  • Snapshot save/load support
  • MLB Stats API-backed live schedule ingestion
  • Cached public advanced-signal artifacts
  • Rolling Statcast-backed xwOBA team batting signals
  • Rolling Statcast-backed starter SIERA signals
  • Static park-factor context signals
  • MLB Stats API venue metadata for roof, dimensions, elevation, and timezone
  • Walk-forward rest-day and time-zone travel signals
  • Walk-forward bullpen fatigue signals
  • CLI commands for snapshot, backtest, and predict
  • Pytest coverage, mypy, ruff, and GitHub Actions CI

Intentionally Deferred

These are explicit roadmap items, not hidden gaps:

  • Market odds and season-target priors
  • Probability calibration and classifier layers
  • Scheduled production jobs and artifact publishing

Architecture

flowchart LR
    A["MLB Stats API"] --> B["Game Source<br/>normalize schedules + starters"]
    A --> H["Advanced Signal Provider<br/>cached raw + derived artifacts"]
    B --> C["MLBEloEngine<br/>team + starter ratings"]
    H --> C
    C --> D["Snapshot Artifacts<br/>JSON ratings + metadata"]
    C --> E["Backtest Summary"]
    C --> F["Predictions"]
    G["CLI"] --> B
    G --> H
    G --> C
    G --> D
    G --> E
    G --> F
Loading

Repo Layout

src/statspace_nine/mlb_elo/
├── advanced.py      # Advanced signal types and protocol
├── advanced_provider.py   # Cached Statcast-backed advanced signal provider
├── advanced_repository.py # Raw + derived artifact repository
├── backtest.py      # Aggregate metrics for walk-forward evaluation
├── cli.py           # statspace-nine entrypoint
├── engine.py        # EloConfig, MLBEloEngine, snapshot serialization
├── sources.py       # GameSource protocol + MLB Stats API adapter
├── team_codes.py    # Stable MLB team-code normalization
└── types.py         # MLBGame, PredictionResult, BacktestSummary

Model Rules In V1

The public engine currently uses these rules:

  • All teams start at 1500
  • All starters start at 1500
  • Home field advantage is +24 Elo
  • Team K-factor is 6
  • Starter K-factor is 12
  • Starter adjustment is scaled by 0.35
  • Starter confidence ramps from 0.0 to 1.0 over the first 10 starts
  • Team ratings revert 50% toward 1500 across seasons
  • Starter ratings revert 30% toward 1500 across seasons
  • Margin of victory uses a capped power formula with exponent 0.5

Phase 2 also computes additive public advanced signals:

  • team xwOBA from cached Statcast plate-appearance-ending events
  • starter SIERA from cached Statcast terminal plate appearances
  • home-park run and home-run factor context from static public tables
  • venue roof, dimensions, elevation, and timezone from cached MLB Stats API venue payloads
  • team rest days and time zones crossed before each game
  • bullpen fatigue from rolling bullpen innings over the trailing 3 days
  • strict walk-forward rolling averages from prior completed games only
  • explicit fallback flags when advanced signals are unavailable

The distinction matters: MLB Stats API venue payloads expose geometry and venue metadata, but not run or HR park factors. Those factor tables remain explicit manual inputs in the public repo.

These signals are exposed in predictions and artifacts but do not yet alter the headline Elo win probability.

The effective pregame gap is:

home_team_elo + home_field_advantage + home_starter_adjustment
- away_team_elo - away_starter_adjustment

The win probability is a standard Elo logistic transform:

P(home win) = 1 / (1 + 10^(-elo_gap / 400))

Quickstart

1. Install

python3 -m pip install -e ".[dev]"

2. Run Tests

python3 -m ruff check .
python3 -m mypy src
python3 -m pytest

3. Build a Snapshot

statspace-nine snapshot \
  --start-date 2025-03-18 \
  --end-date 2025-09-30

Advanced signals are enabled by default. To opt out:

statspace-nine snapshot \
  --start-date 2025-03-18 \
  --end-date 2025-09-30 \
  --no-advanced-signals

Default artifact output:

artifacts/snapshots/2025-09-30/
├── metadata.json
├── starter_ratings.json
├── summary.json
└── team_ratings.json

Advanced cache layout:

artifacts/advanced/
├── derived/
│   └── <cache-key>.json
└── raw/
    ├── game_feeds/
    │   └── <game-id>.json
    ├── statcast_games/
        └── <game-id>.json
    └── venues/
        └── <venue-id>.json

4. Run a Walk-Forward Backtest

statspace-nine backtest --season 2025

This writes:

artifacts/backtests/2025/
├── predictions.json
└── summary.json

5. Predict Today’s Slate

statspace-nine predict --date 2026-04-11

If you do not provide --snapshot-dir, the CLI bootstraps by replaying completed games starting from January 1 of the prior season. If a snapshot includes advanced metadata, predict reuses the cached derived advanced state automatically.

Example Outputs

Example prediction table:

Date       Matchup        Home Win %  Elo Gap  xwOBA Diff  SIERA Diff
2026-04-10  CHW@KCR          53.412%    23.72    fallback    fallback
2026-04-10  NYY@LAD          57.901%    40.28       0.041       0.82

Example backtest summary:

{
  "seasons": [2025],
  "games": 2430,
  "accuracy": 0.538,
  "brier_score": 0.246,
  "average_home_win_prob": 0.534,
  "home_win_rate": 0.529
}

Public Python API

from statspace_nine.mlb_elo import EloConfig, MLBGame, MLBEloEngine

engine = MLBEloEngine(EloConfig())
prediction = engine.predict_game(
    MLBGame(
        date="2026-04-11",
        away_team="NYY",
        home_team="LAD",
        season=2026,
        away_starter_id="12345",
        home_starter_id="67890",
    )
)

print(prediction.home_win_prob)

Design Choices

  • The rating engine is pure model logic. It does not know how to call APIs.
  • Live schedule ingestion is isolated behind a GameSource interface.
  • Advanced metrics are isolated behind a separate provider and repository so raw fetch, cache reuse, and rolling computation are not embedded in the engine.
  • Snapshot files are plain JSON so artifacts are easy to inspect and reuse.
  • The CLI is intentionally thin: it orchestrates fetching, walk-forward processing, and artifact output without hiding the model flow.
  • Tests use recorded fixtures for deterministic schedule normalization and smoke coverage.

Acceptance Criteria For This Version

A clean clone of the repo should be able to:

  • install the package with dev tooling
  • run lint, type checks, and tests
  • build a ratings snapshot from live schedule data
  • run a season backtest
  • produce predictions for a given date

Roadmap

Near-term upgrades that fit the current interfaces:

  1. Add calibration and optional classifier promotion on top of raw Elo probabilities and advanced signals.
  2. Add market odds and season-target priors on top of the same artifact pipeline.
  3. Add richer reporting artifacts and eventually a lightweight public dashboard.

Notes

  • Runtime data is live-fetch only in public v1.
  • Generated artifacts live under artifacts/ and are intentionally ignored by git.
  • The package targets Python 3.11+.

License

MIT

About

MLB ELO system

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages