Skip to content

texasbe2trill/hooplytics

Repository files navigation

🏀 Hooplytics

An NBA player intelligence workbench.

Project the next game · Study any line · Pull live odds — straight from your terminal, notebook, or browser.


CI License: MIT Python 3.11+ Powered by The Odds API Open in Colab Streamlit App


Quick Start · First 5 Minutes · Live Lines · Dashboard · CLI · Use from Claude (MCP) · Modeling · Roadmap


Hooplytics turns NBA game logs into a modern analytics workflow. Model projections, recent-form trends, historical threshold studies, and live market context — designed to help you explore, explain, and challenge the numbers, not hand you a magic prediction.


🎛️ Streamlit dashboard

Click-driven analytics for the modern fan. Eight purpose-built pages, an AI scout (OpenAI or Claude), and printable PDF reports.

hooplytics-web

⚡ Typer CLI

Rich-rendered tables, scriptable end to end, --json friendly.

hooplytics --help

📓 Jupyter notebook

Reproducible, narrative-first exploration with charts inline.

jupyter lab hooplytics.ipynb

Lines from The Odds API are treated as analytical thresholds — comparison points for projections, distributions, and historical outcomes. Hooplytics is analytics-first.


🚀 TL;DR

Already know what you want? Here is the fast path.

git clone https://github.com/texasbe2trill/hooplytics.git && cd hooplytics
python3 -m venv .venv && source .venv/bin/activate && pip install -e .
I want to… Command
🎛️   Open the dashboard hooplytics-web
🎯   Project a player's next game hooplytics project "Jalen Brunson"
🔄   Detect a role / usage shift hooplytics role-shift "Jalen Brunson"
📈   Compare a projection vs. a live line hooplytics prop "Shai Gilgeous-Alexander" points
📊   See the live line board hooplytics lines --refresh
📑   Generate a printable scouting report Open the dashboard → Roster ReportGenerate PDF
🏋️   Generate a coaching performance report Open the dashboard → Roster ReportPlayer Performance Analytics
🤖   Ask the AI scout a question Open the dashboard → Hooplytics Scout
📰   Read tonight's AI slate brief Open the dashboard → Home (needs an AI key)
🔍   Explain why a specific edge exists Open the dashboard → Analytics DashboardEdge Explainer
❓   See all CLI commands hooplytics --help
📓   Open the notebook jupyter lab hooplytics.ipynb

💡 Tip: set ODDS_API_KEY in .env and prop will auto-fetch the line for you — no --line needed.


🏀 Your First 5 Minutes With Hooplytics

New here? This is the smoothest path to "oh, that's actually useful" — and you don't even have to install anything.

1️⃣

Open the live app — no install required
Go to hooplytics.streamlit.app. The hosted Streamlit app loads instantly with a pre-shipped roster of stars and a high-accuracy RACE model bundle already in memory — zero training, zero waiting. Multiple bundles ship in bundles/ and you can switch between them in the sidebar (see Choosing a model bundle).

Prefer to run it locally? pip install -e . && hooplytics-web opens the same app at http://localhost:8501.

2️⃣

Land on Home — see today's slate at a glance
You’ll see roster coverage, model-quality medians, and a roll-up of strong edges. This is your control tower.

3️⃣

(Optional) Paste your Odds API key in the sidebar
Get a free key at the-odds-api.com, paste it into the sidebar password field, and the entire app lights up with live market lines and a real edge board. The key stays in session memory — never written to disk or sent anywhere except The Odds API.

4️⃣

Open Analytics Dashboard → read the slate
This is the fastest way to find tonight’s biggest projection-vs-line gaps. Sort by signed edge, filter by call (MORE / LESS), and use the Strong badge to surface the highest-conviction rows.

5️⃣

Drill into a player on Player Projection
Pick a player from the sidebar to see their next-game projection across all 8 models, recent form trend, distribution context, and the model’s read versus the live line.

6️⃣

Generate a printable scouting PDF
Go to Roster Report → click Generate PDF. You get a branded, multi-page report with KPI tiles, a signal spotlight, R² lollipops, diverging edge charts, and per-player hero blocks — ready to share.

7️⃣

(Optional) Talk to Hooplytics Scout
Pick your AI provider in the sidebar (OpenAI or Anthropic Claude), paste a key, click Connect, and ask things like “Give me a MORE/LESS read on the largest edge tonight, with confidence and risk factors.” The Scout is grounded in your local data and structured for confidence + risk, not hot takes.

🎯 In a hurry? The first three steps are the bare minimum. Steps 4–7 are where the real fun lives.


✨ What Makes Hooplytics Different

Most NBA tools either dump descriptive stats or hand you a single prediction with no context. Hooplytics sits in the middle.

🎯 Projections, not promises

Eight model families, side-by-side, with held-out diagnostics in plain view.

📡 Lines as analytical thresholds

The Odds API tells you what the market thinks; Hooplytics shows you how that compares to recent form, distributions, and history.

🧭 Three surfaces, one mental model

Streamlit for visuals, CLI for speed, notebook for reproducibility.

🔍 No black boxes

Feature importance, residuals, calibration plots, and per-stat health summaries are first-class citizens.

🔄 Role shift detection, built in

The RoleShiftDetector watches for sudden changes in assists, scoring, usage, and minutes across every player projection. When a signal fires, it surfaces a WARN or SUPPRESS flag — and the model respects it automatically.

🛡️ Pregame-safe by design

Rolling features are computed from prior games only — no leakage, no surprises.

🧪 Honest about noise

Lower-signal categories (steals + blocks, turnovers) are framed as such — always.


📡 Live Lines, Made Analytical

Drop an ODDS_API_KEY in .env and the entire CLI lights up with live market data.

# Live line board for the tracked roster, sorted by projection gap
hooplytics lines --refresh

# Single-stat: projection vs. auto-fetched live line
hooplytics prop "Shai Gilgeous-Alexander" points

# Full 8-stat decision view with live lines folded in
hooplytics decisions "Victor Wembanyama"

What you see in your terminal:

Column Meaning
model prediction The model's expected value for the next game
posted line The market line pulled live from The Odds API
5-game avg The player's recent-form baseline
adj. threshold Vig-adjusted line used for the gap calculation
edge Signed gap between the projection and the threshold
call Directional signal (MORE / LESS) for analytical comparison

🔓 No key? No problem. Every command still works — you just lose the live-line column.


🎬 See It In Motion

Streamlit walkthrough

If Hooplytics is useful to you, a ⭐ goes a long way — it helps others find the project.


🖼️ App Preview

The Streamlit app ships with eight purpose-built pages, each focused on a different analytics workflow.

Home

🏠 Home

Portfolio-style overview of roster coverage, model outputs, and high-level telemetry. With an AI key configured, an AI Slate Brief panel renders a one-paragraph daily read on the loudest mispricings — cached for the day so it costs one API call.

Analytics Dashboard

📊 Analytics Dashboard

Command center for projection gaps, signal quality, coverage, and live line telemetry. Pick any signal in the Edge Explainer dropdown for a 2–3 sentence AI breakdown of why that edge exists — line, projection, recent form, and matchup context, all from local data.

Player Projection

🎯 Player Projection

Next-game projection with recent form, distribution context, and supporting visuals.

Player Line Lab

🧪 Player Line Lab

Historical outcome study around a selected player, metric, and current threshold.

Compare Players

⚖️ Compare Players

Side-by-side form, distributions, profile shape, and game logs.

Model Diagnostics

🔬 Model Diagnostics

Held-out model quality, ranking, residuals, and feature drivers.

🤖 Hooplytics Scout

Bring-your-own-key chatbot grounded in your local roster, projections, model metrics, and live edge rows. Toggle OpenAI or Anthropic Claude in the sidebar — both providers run the same prompts and grounding payload, so picks read identically regardless of which one you bring. Hybrid mode by default lets the model layer in general NBA reasoning (explicitly labeled); flip Strict grounded to force local-only answers. Pick suggestions always include structured Confidence and Risk factors, never a guarantee.

🔑 Key setup: Paste an OpenAI or Claude key in the sidebar, or set OPENAI_API_KEY / ANTHROPIC_API_KEY in .env or Streamlit secrets.

🤝 Connect: Click Connect — available chat models are fetched from your key and the best GPT- or Claude-family model is auto-selected.

💬 Ask anything: "Give me a MORE/LESS read on the largest edge tonight, with confidence and risk factors."

🔒 Grounding modes: Hybrid (default) allows labeled general NBA reasoning · Strict only cites local data.

🛡️ Privacy: Your key stays in session memory only — never written to disk or printed in logs.

📑 Roster Report (PDF)

One-click, print-ready editorial scouting report built with ReportLab — no headless browser required. Pulls directly from the live model bundle, edge board, and (optional) AI scout context (OpenAI or Claude — provider swap is invisible to the report). Designed to read like a magazine: serif display type, cream paper, hairline rules, and color-coded OVER / UNDER signals throughout. Every per-player page tags the active player in the page chrome so a reader can never get lost.

📰 Tonight's Slate (cover): Headline call-out for the loudest mispricing, divergent edge skyline of every live signal, and KPI rail (players, live signals, median R²).

🎯 Tonight's Setup: Anchor / Differentiator / Secondary cards with confidence chips, recent-form sparkline, and the ranked Top-4 signal cards.

📊 Signal Board: Full ranked board of every live edge with side, projection vs. line, hit %, confidence, and book counts.

🧭 Conviction Map: Numbered scatter (|edge| vs. book depth) with quadrant labels (SLEEPER / HEADLINE / SKIP / CROWD PLAY), a polished Signal Index legend mapping each marker to player · market · edge, and two AI Scout Picks with full untruncated rationale.

🔬 Model Quality: Composite trust meter on the left and per-target reliability lollipops on the right.

👤 Per-player profiles: Hero block with tonight's call · recent-form pills · last-4 resolved lines · sparklines · model projection vs. line table · full latest context and analyst notes from the AI scout.

Open the Roster Report page, click Generate PDF, and download.

🏋️ Player Performance Analytics (PDF)

A second printable report on the same Roster Report page — strictly performance-oriented (no betting edges, no projection-vs-line content). Designed for coaching staffs, player development, and anyone who wants the same magazine chrome focused on how a player is actually playing. Two pages per player; every page chrome tags the active player.

📰 Cover: Roster headline scoreboard with PTS / REB / AST / TS% per player, deep-linked names that jump straight to that player's profile page.

📋 Roster overview: Per-player snapshot table showing season + L10 stacked for PTS / REB / AST / PRA / MIN / FAN, plus a roster skill overlay radar so you can see every player's skill shape on a single chart.

📈 Per-player profile · Page A: Dark hero band with headline averages · KPI scorecard strip with L10 deltas · Garmin-style activity rings (SCORING / PLAYMAKING / EFFICIENCY vs. roster leader) · ML next-game projection panel (linear-regression forecast with 80% prediction interval and trend arrows) · trend sparklines for 6 primary stats over the last 20 games with rolling-5 overlay · Points by Game · Last 10 tile strip (date, opponent, PTS color-coded vs season average, mini bar, REB / AST footer).

📊 Per-player profile · Page B: Shooting & efficiency bars (FG% / 3P% / FT% / TS%) with roster-median markers · skill-axis radar · floor / median / ceiling consistency strip · role & usage trends · hot/cold streak detection (z-scored vs. season baseline) · three accent-topped coaching cards (Strengths / Growth / Focus) with optional AI-augmented narrative (OpenAI or Claude).

Open the Roster Report page, switch the report-type toggle to Player Performance Analytics, and click Generate performance report.

📓 Notebook gallery  — earlier-era visualizations from the Jupyter workflow

Roster builder Roster setup with searchable player selection

Rolling form chart Recent-form view with hoverable game detail

Predicted vs actual Held-out predicted-vs-actual diagnostics

Feature importance Feature importance across model types


🤔 Questions Hooplytics Helps You Answer

A player intelligence workbench is built to make data easier to explore, explain, and challenge — not to hand you a magic number.

  • 🔮 What does this player's recent form actually look like?
  • 📐 How does the model projection compare with tonight's posted line?
  • 📈 Is the player trending above or below their season baseline?
  • 🎚️ Which signals are stable, and which are noisy?
  • 🗓️ How often has the player finished above similar thresholds historically?
  • 🧭 Where do diagnostics suggest confidence — and where do they suggest caution?

🧠 Under the Hood

  • 🏀 Builds player-level datasets from NBA game logs via nba_api
  • 🛡️ Engineers rolling and per-36 features for pregame-safe modeling
  • 🤖 Trains eight projection models across core counting stats and fantasy score
  • 📡 Pulls live line context from The Odds API for projection-vs-line comparison
  • 📊 Visualizes recent form, distributions, profiles, residuals, and importance
  • 🧪 Supports historical outcome studies and threshold sensitivity analysis
  • 🧭 Same workflow through a notebook, a CLI, and a Streamlit dashboard
  • 🔁 Reproducible end-to-end with cached datasets and pipelines

🌟 Feature Highlights

Area Highlights
🎛️ Streamlit dashboard Eight purpose-built pages: Home, Player Projection, Analytics Dashboard, Compare Players, Player Line Lab, Model Diagnostics, Hooplytics Scout, Roster Report
📑 PDF Roster Report Editorial, magazine-style ReportLab PDF — Tonight's Slate cover, Tonight's Setup card stack, ranked Signal Board, Conviction Map with Signal Index legend and AI Scout Picks, Model Quality trust meter, and per-player profiles with latest context, sparklines, last-4 resolved lines, and active-player tag in the page chrome
🏋️ PDF Player Performance Analytics Second coach-focused PDF on the same page — 2 pages per player. KPI scorecards, Garmin-style activity rings, ML next-game projection with 80% prediction interval, trend sparklines, Points by Game · Last 10 tile strip, shooting & efficiency bars, skill-axis radar, floor/median/ceiling consistency, role & usage trends, hot/cold streak z-scores, and three accent-topped coaching cards (Strengths / Growth / Focus)
🤖 Hooplytics Scout (AI) BYO-key chatbot — pick OpenAI or Anthropic Claude in the sidebar; both providers run the same grounded prompts. Hybrid or Strict grounded modes, structured Confidence + Risk factors
📰 AI Slate Brief One-paragraph daily read of tonight's loudest mispricings on the Home page. Cached per-day so it costs a single API call, regardless of how many times you refresh.
🔍 AI Edge Explainer Pick any signal in the Analytics Dashboard dropdown and get a 2–3 sentence breakdown grounded in line, projection, recent form, and matchup context.
📡 Live line context Auto-fetched lines from The Odds API across CLI and dashboard, with session-only BYO-key support in the web app
🎯 Edge board Slate-wide projection-vs-line gap analysis, signed edges, MORE/LESS calls, and book counts — feeds the dashboard, the AI scout, and the PDF report
👤 Player analysis Recent form, rolling trends, distributions, player profiles, season averages, and recent-window comparisons
🔄 Role Shift Detection RoleShiftDetector monitors 4 signals (assists σ, scoring σ, usage FGA%, minutes%) against per-signal thresholds. WARN flags add a confidence note; SUPPRESS flags flip projections to NO_CALL for the affected stats. Suppression map is empirically validated via a full backtest attribution cross-table (403 games, +0.064 overall directional-accuracy lift). Visible in the sidebar Role Alerts widget, the role-shift CLI command, and the check_role_shift MCP tool.
🧠 Modeling stack RACE blend (Ridge + kNN + Random Forest pipelines) across eight target stats, role and context features
🎚️ Market-anchored calibration Two-layer calibration applied at inference (Huber per-market actual ≈ a + b·line + per-player residual mean clipped to ±20%) blended with the model via per-market weights — corrects systematic bias without retraining. Built with hooplytics-build-calibration and shipped as bundles/calibration_v1.json
📦 Prebuilt RACE bundles Multiple ready-to-use bundles ship in bundles/ (e.g. race_fast.joblib, race_playoffs.joblib). The Streamlit app auto-loads one on launch and lets you switch between them from the sidebar — zero cold-start training required
🔬 Diagnostics RMSE / MAE / R², predicted-vs-actual panels, residual views, feature importance, and per-stat health summaries
CLI workflows Single-player projection, prop comparison, scenario inputs, live line board, roster persistence, and prebuilt-bundle training
🤖 MCP server Use the full Hooplytics engine directly from Claude Desktop. Ten tools cover projections, prop analysis, role shift detection, scenario scoring, live line boards, scout reports, slate briefs, and roster management — see HOOPLYTICS_MCP_SETUP.md
📓 Notebook workflow Rich exploratory narrative with tables, charts, code, and reproducible analysis in one place

⚖️ Analytics first

Lines from The Odds API are treated as analytical inputs — thresholds to compare against projections, recent form, and historical outcomes. Hooplytics uses them to ask better questions:

  • How far is the model projection from the current line?
  • Is recent form above or below the season baseline?
  • How volatile is the player around this threshold?
  • How often has the player finished above similar thresholds?
  • Does the model signal agree with historical performance?

Hooplytics is a statistical analysis project for learning, exploration, and visualization.


⚡ CLI Walkthrough

Hooplytics ships with a Typer-based CLI that renders to Rich tables and panels in your terminal. Reproducible, scriptable, and --json friendly.

Available commands

Command Purpose
hooplytics project Project a player's next game across all 8 models
hooplytics role-shift Detect assist / scoring / usage / minutes role shifts with WARN / SUPPRESS severity
hooplytics prop Compare a player projection against a posted line for a single stat
hooplytics decisions 8-stat projection summary with model-vs-line gap analysis
hooplytics scenario Score a hypothetical box-score JSON payload
hooplytics lines Live line board for the tracked roster, sorted by projection gap
hooplytics train Pre-warm and cache the model bundle
hooplytics-train-bundle Interactive prebuilt bundle trainer with progress bars and R2 validation gates
hooplytics-build-calibration Fit the market-anchored calibration artifact (bundles/calibration_v1.json) from cached odds + game logs
hooplytics roster list Show the tracked roster
hooplytics roster add Add a player to the tracked roster
hooplytics roster remove Remove a player from the tracked roster

Example CLI usage

# Next-game projection across all 8 models
hooplytics project "Victor Wembanyama"

# Role shift check — prints WARN/SUPPRESS panel; exits 0 (NONE), 1 (WARN), 2 (SUPPRESS)
hooplytics role-shift "Jalen Brunson"
hooplytics role-shift "Donovan Mitchell" --json   # machine-readable output

# Single-stat comparison — line auto-fetched from The Odds API
hooplytics prop "Shai Gilgeous-Alexander" points

# Same comparison with an explicit line override
hooplytics prop "Shai Gilgeous-Alexander" points --line 31.5

# 8-stat decision view, no live lines (offline mode)
hooplytics decisions "LeBron James" --no-live

# Live line board, freshly fetched
hooplytics lines --refresh

# Score a what-if box-score row
hooplytics scenario '{"fgm":8,"fga":15,"fg3m":3,"ftm":4,"min":34,"fg_pct":0.53,"ft_pct":1.0,"oreb":1,"dreb":5}'

# Roster + cache management
hooplytics roster add "Anthony Edwards"
hooplytics train

# Build and ship a prebuilt Streamlit bundle (defaults to bundles/race_fast.joblib)
hooplytics-train-bundle --mode exhaustive --players-source postseason-plus-anchors

# Fit the market-anchored calibration artifact from cached odds (used automatically by predict)
hooplytics-build-calibration build --season 2024-25 --season 2025-26 --verbose

🔑 hooplytics lines and live-enabled prop / decisions need ODDS_API_KEY (from .env or your shell). All commands support --help, and most reporting commands support --json for scripting.


🤖 Use from Claude (MCP)

Hooplytics ships a Model Context Protocol server that exposes the full projection + analytics engine to Claude Desktop (and any MCP-compatible client). Once connected, Claude can answer questions like "project Anthony Edwards' next game and tell me which stat has the biggest edge" or "give me tonight's slate brief — which players have the loudest mispricings?" by calling Hooplytics tools directly.

What you get inside Claude:

  • Next-game projections across all 8 RACE models, plus single-stat MORE/LESS calls vs sportsbook lines.
  • Role shift detection (check_role_shift) — ask Claude "is there a role shift concern for Jalen Brunson?" and get a full signal breakdown with WARN / SUPPRESS severity and per-stat NO_CALL flags.
  • Live line board sorted by projection gap, with book counts and consensus medians.
  • Scenario scoring for hypothetical box scores ("what if he plays 36 minutes and shoots 55%?").
  • AI Scout reports and AI Slate Briefs — the same prose engine the Streamlit dashboard uses, grounded in projection data.
  • Player analytics (game logs, season vs recent averages, volatility, trend deltas) and roster management (add / remove / list / reset).

Setup: see HOOPLYTICS_MCP_SETUP.md for the Claude Desktop config block, prerequisites, and example prompts. Local stdio mode works out of the box; SSE mode is supported for remote clients.

ℹ️ Roster sharing. The MCP server reads and writes the same ~/.hooplytics/roster.json the CLI uses, so adding a player via Claude shows up in hooplytics roster list and vice versa. The Streamlit dashboard keeps its own session-only roster and does not sync with either.


📦 Installation

Base install

git clone https://github.com/texasbe2trill/hooplytics.git
cd hooplytics

python3 -m venv .venv
source .venv/bin/activate
pip install -e .

With notebook extras

pip install -e .[notebook]

Adds Jupyter, ipywidgets, and notebook-only visualization helpers.

Web / Streamlit only

pip install -r requirements.txt

Minimal install for Streamlit Cloud or web-only deploys. Does not include notebook deps.

Requires Python 3.11 or later.


🔐 Configuration

Three optional API keys — none of them are required to launch the app.

Variable What it powers
ODDS_API_KEY Live line context, edge board, prop comparisons (The Odds API)
OPENAI_API_KEY Hooplytics Scout, AI Slate Brief, AI Edge Explainer, AI prose in both PDFs
ANTHROPIC_API_KEY Same as above, but routed through Anthropic Claude when the sidebar provider is set to Claude

Three safe ways to supply any of them:

Method How
📄 Local .env Copy .env.example.env, set ODDS_API_KEY=…, OPENAI_API_KEY=…, ANTHROPIC_API_KEY=…
🐚 Shell session export ODDS_API_KEY=… (etc.)
🌐 Streamlit sidebar Paste your key into the sidebar password field — session-only, never stored
cp .env.example .env
# then edit .env and set the keys you want to use

🔓 If no AI key is configured, the AI features (Scout, Slate Brief, Edge Explainer, PDF prose) cleanly disable and the rest of the app keeps working. If no Odds API key is set, you just lose the live-line column.


🛠️ Usage

🎛️ Streamlit dashboard — the recommended starting point

hooplytics-web

This launches the full multi-page dashboard at http://localhost:8501. A pre-trained RACE model bundle ships with the repo at bundles/race_fast.joblib and is auto-loaded — you get production-quality projections instantly, no training step required.

🔑 Sidebar setup (optional)
• Paste your Odds API key to enable live lines and the edge board.
• Under Hooplytics Scout, pick OpenAI or Anthropic Claude and paste the matching key.
• Keys are session-only — never written to disk.
📍 Where to go first
Home for the slate overview.
Analytics Dashboard for the live edge board.
Player Projection for a single-player deep dive.
Roster Report to export a branded PDF.
Hooplytics Scout to chat with your data.
👥 Roster management
The sidebar lets you add or remove tracked players. Changes are persisted locally between sessions, so your roster is ready to go next time you launch the app.

⚡ CLI

hooplytics --help                        # browse all commands
hooplytics roster list                   # see who's tracked
hooplytics project "Jalen Brunson" --last-n 10
hooplytics lines --refresh               # fresh live line board

🎚️ Choosing a model bundle

Hooplytics ships multiple pretrained bundles in bundles/ so you can switch model behavior without retraining. The default app launch uses race_fast.joblib.

In the Streamlit sidebar:

  1. Make sure Use prebuilt model bundle is checked (it is by default).
  2. A Bundle dropdown appears right below it listing every .joblib file found in bundles/.
  3. Pick a bundle — the app reloads automatically. All projections, the edge board, the AI scout, and the PDF report immediately reflect the new bundle.
Bundle Best for
🏃 race_fast.joblib Default. Broad regular-season coverage trained on a large rolling window. Fast to load, balanced across all 8 stat targets.
🏆 race_playoffs.joblib Playoff-tuned variant. Weighted toward higher-stakes, lower-pace games — useful for postseason slates.

💡 Power users: drop any additional *.joblib you trained with hooplytics-train-bundle into bundles/ and it appears in the dropdown on next reload. To pin a non-default bundle headlessly, set HOOPLYTICS_PRETRAINED_BUNDLE=/abs/path/to/your.joblib in .env or your Streamlit secrets.

📓 Jupyter workflow

jupyter lab hooplytics.ipynb

Follow the notebook top-to-bottom for the full narrative analysis, or jump to a section.


📚 Data Sources

Source Used for
🏀 nba_api NBA player game logs and player metadata
📡 The Odds API Optional live line and book-count context
💾 Local cache Parquet/JSON caching for faster repeated workflows

Hooplytics does not redistribute NBA game data. All data is fetched at runtime.


🧪 Analytics Approach

Hooplytics emphasizes transparent, pregame-safe modeling rather than black-box outputs.

Targets

Model name Target
points pts
rebounds reb
assists ast
pra pts + reb + ast
threepm fg3m
stl_blk stl + blk
turnovers tov
fantasy_score fantasy_score

Modeling principles

🛡️ Pregame-safe. Rolling windows are computed from prior games only — no leakage.

🧱 Pipelines, not magic. Scaling and feature handling stay inside scikit-learn pipelines, train/test boundaries intact.

⚖️ Compare, don't hide. Multiple model families are shown side by side instead of collapsing to one number.

🔬 Diagnostics are first-class. Calibration, residuals, and feature importance are surfaced everywhere, not buried.

🧪 Honest about noise. Steals + blocks and turnovers are framed as lower-signal categories — always.


📁 Project Structure

hooplytics/
├── hooplytics.ipynb              # Narrative notebook workflow
├── README.md
├── pyproject.toml
├── requirements.txt
├── docs/
│   ├── index.html
│   ├── assets/                   # Notebook-era visualizations
│   └── screenshots/              # Streamlit dashboard captures
├── bundles/
│   ├── race_fast.joblib          # Default RACE bundle auto-loaded by the app
│   ├── race_playoffs.joblib      # Playoff-tuned RACE bundle (selectable in sidebar)
│   └── calibration_v1.json       # Market-anchored calibration artifact (auto-applied by predict)
├── hooplytics/
│   ├── cli.py                    # Typer CLI entry point (includes `role-shift` command)
│   ├── constants.py
│   ├── data.py                   # Game log ingestion + caching
│   ├── fantasy.py
│   ├── features_context.py       # Pace / matchup / opponent context
│   ├── features_market.py        # Market-aware features
│   ├── features_role.py          # Role / usage features
│   ├── models.py                 # 8-stat RACE model training
│   ├── odds.py                   # The Odds API client
│   ├── backtest.py               # Retro-projection accuracy backtest (pregame-safe)
│   ├── role_shift_detector.py    # RoleShiftDetector: 4-signal WARN/SUPPRESS engine
│   ├── role_shift_validate.py    # Empirical backtest validator (directional accuracy by severity)
│   ├── role_shift_attribute.py   # Attribution cross-table: (signal × stat) directional-accuracy lift
│   ├── role_shift_sweep.py       # Threshold sweep utility for signal calibration
│   ├── ai_agent.py               # Provider-agnostic AI dispatcher (OpenAI ↔ Claude)
│   ├── openai_agent.py           # OpenAI transport: chat, slate brief, edge explainer, PDF prose
│   ├── anthropic_agent.py        # Anthropic Claude transport (mirrors openai_agent's API)
│   ├── predict.py                # Projection + line comparison (auto-applies calibration)
│   ├── calibration.py            # Two-layer market-anchored calibration
│   ├── calibration_cli.py        # `hooplytics-build-calibration` entry point
│   ├── report.py                 # PDF Roster Report builder (ReportLab)
│   ├── report_performance.py     # PDF Player Performance Analytics builder (ReportLab)
│   ├── train_bundle.py           # Interactive prebuilt-bundle trainer
│   └── web/
│       ├── app.py                # Streamlit multi-page app
│       ├── charts.py
│       ├── launcher.py           # `hooplytics-web` entry point
│       ├── role_shift_widget.py  # Role Alerts sidebar widget (WARN/SUPPRESS chips + signal cards)
│       └── styles.py
└── tests/

🗺️ Roadmap

🤖 AI & chat

  • 🌊 Streaming Scout responses — render tokens as they arrive in Hooplytics Scout for a snappier read on long replies. Both the OpenAI and Anthropic SDKs already support stream=True; wire it through the dispatcher and surface via st.write_stream.
  • 🔀 Side-by-side provider comparison — send the same prompt to OpenAI and Claude in parallel and diff the picks. The provider abstraction already supports this; just needs a UI toggle for second-opinion mode.
  • 🗣️ Conversational Line Lab — natural-language "what-ifs" on the scenario explorer ("what changes if pace drops 4?", "show me a back-to-back scenario"). Mutates the scenario dict and re-projects in place.
  • 📝 Post-game recap memo — daily auto-generated readout pairing yesterday's model calls with actual outcomes ("model said 24.3 PRA on a 21.5 line, player went 28; the OVER lean held"). Closes the trust loop and makes the model's tracking visible.
  • 🧑‍🎨 Custom system prompts — power-user override for Scout / PDF prose (per-roster voice, risk tolerance, format preferences) without forking the codebase.

📦 Data & analytics

  • 🏷️ Player archetype clustering — auto-tag players ("primary creator", "stretch big", "off-ball wing") from role + shooting embeddings, surfaced in the grounding payload so AI prose can reason about role-shape directly.
  • 👥 Multi-roster profiles — save and switch between named rosters from the sidebar (DFS lineup, season-long fantasy, futures slate) without losing each one's bundle / model state.
  • 📡 Richer book-level line telemetry inside the Streamlit app — per-book vig, line movement, and fastest-mover attribution.
  • 🔄 Retrain RACE bundles on enriched odds data — role shift detection lifts directional accuracy by +0.064 overall; the next step is retraining the core RACE models with cached sportsbook lines as features so the base projection absorbs market information before the suppression layer runs.

🎨 UX & polish

  • 🎬 Fresh Streamlit dashboard screenshots and rendered demos for the Roster Report, Performance Analytics, and Hooplytics Scout pages.
  • 🎨 Saveable / shareable PDF report templates with custom branding (team colors, logo, footer).
  • 📦 Reproducible demo datasets plus broader player and season presets for faster onboarding.

⚠️ Disclaimer

Hooplytics is for statistical analysis, education, and entertainment.

Line values are used as contextual inputs for comparing model projections, recent form, and historical outcomes. The project is not an execution system and not a guarantee of future results.


🤝 Contributing

Issues and pull requests are welcome, especially around:

  • 🤖 model quality and calibration
  • 🎨 UX improvements for the dashboard or CLI
  • 📊 additional visualization layers
  • 📚 documentation and reproducibility

📜 License & Acknowledgements

MIT © 2026 Chris Campbell

Hooplytics is the Python evolution of hooplyticsR, with additional dashboarding, modeling, and CLI tooling.

Built on the shoulders of:


If Hooplytics helps you think more clearly about player performance, consider giving the repo a ⭐.

About

Hooplytics turns NBA box-score data into player intelligence through machine learning, interactive analytics, and visual workflows for exploring trends, projections, and performance signals.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors