NBA Shot Strategy — The Random Walk of Mathematical Finance

Web Application for Optimal Shot Distribution Analysis
Research under Professor Hesam Oveys (NYU)

Python FastAPI React License

Overview

Interactive web application that applies probabilistic methods from financial mathematics to basketball analytics. Users can select NBA matchups, adjust shot strategies interactively, and run Monte Carlo simulations to find optimal 2PT/3PT ratios.

Key Features

Quick Start

Option 1: Docker (Recommended)

Local Development:

# Clone repository
        git clone <repo-url>
        cd predicrionai

        # Build and run
        docker compose up --build

        # Open browser
        open http://localhost:8000
        

Production Deployment (with Traefik + Let's Encrypt):

# Setup environment
        cp .env.example .env
        nano .env  # Add CF_API_EMAIL, CF_API_KEY, DOMAIN

        # Launch all services
        docker compose up -d --build

        # Access:
        # https://monte.kz-saas.com          → Web App
        # https://jupyter.monte.kz-saas.com  → Jupyter
        # https://research.monte.kz-saas.com → Research Paper
        # https://traefik.monte.kz-saas.com  → Traefik Dashboard
        

See docs/TRAEFIK_SETUP_RU.md for detailed production setup instructions.

Option 2: Local Development

# Backend
        python3 -m venv venv
        source venv/bin/activate
        pip install -r requirements.txt
        uvicorn webapp.main:app --reload

        # Frontend (in another terminal)
        cd frontend
        npm install
        npm run dev

        # Open http://localhost:5173 (dev) or http://localhost:8000 (production)
        

Usage

Web Interface

  1. Select Match — Choose two teams or pick from recent/historical matches
  2. View Current Strategy — See team shooting profiles and Four Factors
  3. Adjust Parameters:
  4. 3-Point shot ratio (0-95%)
  5. 3-Point FG% (20-50%)
  6. Hot hand effect (ON/OFF)
  7. Simulation iterations (1K-20K)
  8. Run Simulation — Get expected scores, win probability, optimal recommendations
  9. Analyze Results:
  10. Score distribution histograms
  11. Win probability visualization
  12. Strategy comparison table
  13. Optimal strategy recommendations

API Endpoints

# Get all teams
        GET /api/teams

        # Get team profile
        GET /api/teams/{team_id}

        # List matches (mode: synthetic | history | upcoming)
        GET /api/matches?mode=history&count=20

        # Run simulation
        POST /api/simulate
        {
          "home_team_id": 1610612747,
          "away_team_id": 1610612744,
          "home_three_ratio": 0.38,
          "away_three_ratio": 0.42,
          "home_fg3_pct": 0.36,
          "away_fg3_pct": 0.38,
          "hot_hand": false,
          "iterations": 5000
        }

        # Analyze optimal strategy
        GET /api/analysis/{team_id}?opponent_id={opp_id}&iterations=1500
        

Architecture

predicrionai/
        ├── webapp/              # FastAPI backend
        │   ├── main.py          # App entry point (+ cache warm-up on startup)
        │   ├── api.py           # REST routes
        │   ├── schemas.py       # Pydantic models (API contracts)
        │   ├── services.py      # Business logic (simulation orchestration)
        │   ├── providers.py     # Data sources: ESPN (primary) → nba_api → synthetic
        │   ├── cache.py         # Redis match cache (in-memory fallback)
        │   └── static/          # Built frontend (from Vite)
        ├── frontend/            # React + Vite
        │   ├── src/
        │   │   ├── App.jsx
        │   │   ├── pages/       # MatchSelect, Analysis
        │   │   ├── components/  # TeamCard, StrategyPanel, Charts
        │   │   ├── api.js       # Fetch wrapper
        │   │   └── styles.css   # Design tokens
        │   └── vite.config.js
        ├── src/                 # Core simulation engine
        │   ├── simulation/      # Monte Carlo, ShotModel, GameSimulator
        │   ├── analysis/        # FourFactors, HotHand, Statistics
        │   ├── data/            # NBAClient (with TLS bypass)
        │   └── utils/           # Config, Logger
        ├── tests/               # Pytest (34 tests, 100% pass)
        ├── notebooks/           # Jupyter analysis notebooks
        └── paper/               # Research paper
        

Testing

# Run all tests
        pytest tests/ -v

        # With coverage
        pytest tests/ --cov=src --cov=webapp --cov-report=html

        # Test API manually
        curl http://localhost:8000/api/health
        curl http://localhost:8000/api/teams
        

Research Foundation

Mathematical Concepts

  1. Expected Value: Average outcome over many trials (EV = P × Points)
  2. Central Limit Theorem: Distribution of means approaches normal as n increases
  3. Variance: Risk measure — 3PT shots have 2.1x higher variance than 2PT

Four Factors (Dean Oliver)

  1. Effective FG% (40% weight) — Shooting efficiency: (FGM + 0.5 × 3PM) / FGA
  2. Turnover Rate (25%) — Ball security: TOV / (FGA + 0.44 × FTA + TOV)
  3. Offensive Rebound Rate (20%) — Second chances: ORB / (ORB + Opp DRB)
  4. Free Throw Rate (15%) — Getting to the line: FTA / FGA

Results

Tech Stack

Component Technology Version
Backend FastAPI + Uvicorn 0.115+
Frontend React + Vite 18 / 5
Charts Chart.js 4.5
Data ESPN API (primary) + nba_api (fallback) + synthetic —
Cache Redis (in-memory fallback) 7.x
Simulation NumPy + SciPy 1.24+
Container Docker + Docker Compose —

Configuration

Environment variables (optional):

NBA_API_RATE_LIMIT=0.6        # Delay between NBA API calls (seconds)
        LOG_LEVEL=INFO                 # Logging level
        REDIS_URL=redis://redis:6379/0 # Redis connection (auto-set by docker-compose)
        MATCH_CACHE_TTL_SECONDS=43200  # Match cache TTL (default 12 hours)
        SIM_ITERATIONS=10000           # Default simulation iterations
        HOT_HAND_WINDOW=5              # Consecutive makes to trigger hot hand
        

Key Research Files

Known Issues / Limitations

  1. Real NBA data: ESPN is the primary source (profiles + matches). stats.nba.com (nba_api) is the fallback — it often blocks server IPs. Synthetic data is the last resort, so the app always works, even off-season (ESPN lookback is up to 180 days, lookahead up to 90)
  2. Simplified possession model — doesn't model full play-by-play complexity
  3. Hot hand evidence mixed — implemented for research exploration
  4. No defensive adjustments — assumes independent shot outcomes

Contributing

# Format code
        black src/ webapp/ tests/

        # Lint
        flake8 src/ webapp/ tests/

        # Type check
        mypy webapp/

        # Run tests before committing
        pytest tests/
        

License

MIT License — see LICENSE file

Authors

References

  1. Oliver, D. (2004). Basketball on Paper. Brassey's Inc.
  2. Miller, J. B., & Sanjurjo, A. (2018). Surprised by the hot hand fallacy? Econometrica, 86(6).
  3. Goldsberry, K. (2019). Sprawlball: A Visual Tour of the New Era of the NBA.
  4. NBA API: https://github.com/swar/nba_api

Academic Context

This project was developed as part of a research concentration under Professor Hesam Oveys at NYU, exploring the application of financial mathematics (random walk theory, Monte Carlo methods, portfolio optimization) to sports analytics.

Core Question: How should an NBA team optimally distribute 2-point vs 3-point shots to maximize expected points while managing variance?

Answer: At NBA-average shooting (52% 2PT, 36% 3PT), optimal strategy is approximately 45-50% three-point attempts. However, the optimal ratio depends on: - Team shooting ability (better 3PT shooters should shoot more 3s) - Risk tolerance (trailing teams should increase variance with more 3PT) - Opponent strategy (defensive adjustments not modeled)

The web application makes this research interactive and accessible.