A complete League of Legends esports match prediction system integrated with Polymarket for edge detection. Built on Oracle's Elixir match data (2014–2026) with a dual ELO rating system and XGBoost probability model.
🏗 Architecture
┌────────────────────────────────────────────────────────────┐
│ DATA LAYER │
│ Oracle's Elixir CSV (165 columns, 1.1M+ rows) │
│ Google Drive auto-sync (daily updates) │
└──────────────┬─────────────────────────────────────────────┘
│
┌──────────────▼─────────────────────────────────────────────┐
│ FEATURE ENGINEERING │
│ • Rolling team stats (15-game window, exp. weighted) │
│ • Gold/XP/CS diffs at 10, 15, 20, 25 min │
│ • Objective control (dragons, barons, towers, heralds) │
│ • Vision metrics (wards, vision score) │
│ • Win/loss streaks │
│ Total: 115 pre-game features per matchup │
└──────────────┬─────────────────────────────────────────────┘
│
┌──────────────▼─────────────────────────────────────────────┐
│ DUAL ELO RATING SYSTEM │
│ Regional Rating: Updated from domestic league games │
│ Meta Rating: Updated from international events only │
│ μ_total = μ_regional + μ_meta │
│ → Solves cross-region comparison (LCK vs LPL vs LEC) │
│ • Margin of victory scaling (gold diff / game length) │
│ • Time-based σ inflation (off-season uncertainty) │
│ • Roster change detection → σ increase │
└──────────────┬─────────────────────────────────────────────┘
│
┌──────────────▼─────────────────────────────────────────────┐
│ PREDICTION MODEL │
│ XGBoost + Isotonic Regression Calibration │
│ • 63% accuracy, 0.67 AUC-ROC, 0.225 Brier Score │
│ • Time-series cross-validation (no data leakage) │
│ • Bo3/Bo5 series probability extension │
│ • Ensemble: 70% model + 30% ELO │
└──────────────┬─────────────────────────────────────────────┘
│
┌──────────────▼─────────────────────────────────────────────┐
│ POLYMARKET INTEGRATION │
│ Gamma API → Market discovery (tag_slug: esports) │
│ CLOB API → Live bid/ask/mid prices │
│ Edge = Model_prob - Market_mid │
│ Kelly criterion for position sizing │
│ 248+ active LoL markets detected │
└────────────────────────────────────────────────────────────┘
📊 Model Performance
Validation Results (7,763 train / 1,941 val)
Metric
Value
Accuracy
63.0%
AUC-ROC
0.672
Brier Score
0.224 (calibrated)
Log Loss
0.639 (calibrated)
5-Fold Time-Series Backtest (2022–2026)
League
Accuracy
Brier Score
Games
LCK
65.8%
0.227
1,853
LCP
63.8%
0.227
376
LTA N
67.6%
0.225
213
MSI
62.4%
0.234
234
LEC
61.8%
0.257
1,077
LPL
59.9%
0.250
2,796
Worlds
59.2%
0.251
520
Overall
61.5%
0.245
8,085
Top Features (by XGBoost importance)
elo_diff — ELO rating difference (4.7%)
diff_opp_towers_mean — Opponent tower diff (3.7%)
diff_earned_gpm_mean — Gold per minute diff (2.2%)
diff_towers_mean — Tower control diff (1.9%)
diff_result_mean — Win rate diff (1.7%)
🏆 League Strength Rankings (auto-updated from international results)
Rank
League
Strength
Method
1
LCK
2.621
MSI/Worlds results
2
LPL
1.827
MSI/Worlds results
3
LEC
0.960
MSI/Worlds results
4
LTA
0.850
Prior (limited intl)
5
CBLOL
0.319
MSI/Worlds results
6
LCP
0.283
MSI/Worlds results
How it works: League strengths start from priors based on historical international performance. They are then updated via a Bayesian ELO-style system every time teams from different leagues meet at MSI, Worlds, FST, or EWC. The system uses K=0.02 for conservative updates.
🎯 Current Top Teams (ELO Ratings)
Rank
Team
League
μ
Games
1
Gen.G
LCK
70.4
906
2
T1
LCK
64.4
910
3
Bilibili Gaming
LPL
55.5
899
4
Dplus Kia
LCK
52.5
903
5
Top Esports
LPL
52.4
896
6
JD Gaming
LPL
50.8
845
7
G2 Esports
LEC
49.4
698
⚡ Quick Start
bash
1# Install dependencies2pip install -r requirements.txt
34# Download data from Google Drive5python -c "
6import gdown
7gdown.download_folder('https://drive.google.com/drive/folders/1gLSw0RLjBbtaNy0dgnGQDAZOHIgCe-HH',
8 output='data/raw', quiet=False)
9"1011# Train the model (uses 2022-2026 data)12python -m lol_predictor.main train --backtest
1314# Predict a specific match15python -m lol_predictor.main predict --team-a "T1" --team-b "Gen.G" --league LCK --format bo5
1617# Compare against market odds18python -m lol_predictor.main edge --team-a "T1" --team-b "Gen.G" --market-odds 0.40 --format bo5
1920# Scan Polymarket for live LoL markets21python -m lol_predictor.main scan
2223# Show team ratings24python -m lol_predictor.main ratings --top 302526# Run full scheduler (daily retrain + 5-min scanning)27python -m lol_predictor.main run
📐 How League Strength is Computed
The system uses a dual rating architecture (inspired by PandaSkill):
1. Regional Rating (μ_regional)
Updated after every domestic league game
Uses Glicko-style update with margin of victory scaling
Decays with inactivity (σ inflates 0.8 per month)
Inflates σ on roster changes (1.5 per position changed)
2. Meta Rating (μ_meta)
Updated only from international events (MSI, Worlds, FST, EWC)
Higher K-factor (48 vs 32) because international games are rarer and more informative
Cross-region games update both team meta-ratings AND league strength scores
Current season: Full weight, 0.95 per-week exponential decay
Previous season: 30% of current weight
2+ seasons ago: 9% weight (0.3²)
🔄 Scheduling Architecture
Schedule 1: Daily Model Retraining (06:00 UTC)
1. Download latest CSVs from Google Drive (updated daily)
2. Rebuild ELO ratings from scratch (warm-up: 2019-2021, train: 2022-2026)
3. Recompute all rolling features
4. Retrain XGBoost with early stopping
5. Calibrate with isotonic regression
6. Save model artifacts
Schedule 2: Market Scanning (every 5 minutes)
1. Query Polymarket Gamma API for active LoL esports events
2. Parse market questions to extract team names + match format
3. Fetch live CLOB prices (mid, bid, ask, spread)
4. Generate model predictions for each detected matchup
5. Compute edges: model_prob - market_mid
6. Flag edges > 5% with Kelly criterion sizing
7. Log results to data/processed/scan_logs/
📁 Project Structure
lol_predictor/
├── __init__.py
├── config.py # All configuration (leagues, params, API URLs)
├── main.py # CLI entry point
├── train.py # Training pipeline orchestrator
├── predict.py # Match prediction + market edge analysis
├── data/
│ └── loader.py # CSV loading, cleaning, game pairing
├── features/
│ ├── engineering.py # Rolling stats, H2H, league strength
│ └── elo_system.py # Dual ELO (regional + meta) rating system
├── model/
│ └── predictor.py # XGBoost model + calibration + backtesting
├── polymarket/
│ └── scanner.py # Gamma API + CLOB price fetcher + edge detection
└── scheduler/
└── runner.py # Cron-like scheduler for retrain + scan