back to research
ai/mlweb3

Building an Autonomous WC2026 Trading Bot: ELO, Monte Carlo, and Kelly Criterion on Polymarket

How we built an autonomous prediction market trading system using ELO ratings, Monte Carlo simulation, and Kelly criterion sizing on Polymarket for FIFA World Cup 2026.

Chaitanya·June 20, 2025

We built a system that watches FIFA World Cup 2026 prediction markets on Polymarket, identifies mispriced outcomes using an ELO rating model and Monte Carlo tournament simulation, sizes positions using the Kelly criterion, and executes trades autonomously from users' self-custodied wallets. This article walks through the math and engineering behind each layer.

System Overview

The system has three components:

  1. Prediction engine: ELO ratings calibrated on live match results, fed into a 10,000-iteration Monte Carlo simulation to produce probabilities for every tournament outcome (match wins, group qualification, bracket advancement, tournament winner).
  2. Risk engine: Compares model probabilities against Polymarket prices, computes edge, sizes positions using fractional Kelly criterion, and selects a diversified portfolio subject to category and correlation constraints.
  3. Execution engine: Places orders on Polymarket's CLOB through users' Gnosis Safe wallets via delegated server signing, monitors settlement, and collects performance fees on winning bets.

The prediction engine runs every 30 minutes, execution every 15 minutes, and settlement checks every 5 minutes.

1. ELO Rating System

The Core Formula

We use the standard ELO expected score formula. Given two teams with ratings RA and RB: EA = 1 / (1 + 10^((RB - RA)/400))

This is a logistic function with base 10 and a scale factor of 400. A 400-point rating difference corresponds to a 10:1 expected score ratio. Two equally rated teams yield EA = 0.5.

Rating Updates

After each match, ratings are updated using: R'A = RA + K × G × (SA − EA)

Where K=32 (sensitivity factor, standard for international football), SA is the actual result (1 for a win, 0.5 for a draw, 0 for a loss), EA is the expected score, and G is the goal difference multiplier.

Goal Difference Multiplier

A 1-0 win and a 7-1 win shouldn't produce the same rating change. The multiplier G accounts for this: G = 1 + 0.5 × ln(1 + d) where d is the goal difference. A 3-goal margin yields G=1.75; Germany's 7-1 over Curacao yields G=2.25.

From Match ELO to Three-Way Probabilities

Binary ELO gives you P(home wins or draws)=EA. Football needs three outcomes, so we decompose EA into home win, draw, and away win.

The draw probability is: Pdraw = base_draw × (1 − |EA − 0.5| × 2)

The base rate of 0.26 reflects international football's historical draw frequency (~26% across World Cup matches). As the rating gap widens, draws become less likely.

Confidence

Model confidence is a linear function of the rating gap: confidence = min(0.5 + |RA − RB| / 900, 0.95). Two equally-rated teams yield 50% confidence. A 450-point gap yields 95% confidence.

2. Monte Carlo Tournament Simulation

Match-level probabilities give us P(Spain beats Saudi Arabia). But Polymarket also has markets for "Spain to win the World Cup" and "Spain to reach the semi-final." These require simulating the entire tournament structure.

We run 10,000 independent tournament simulations. Each simulation: simulates all 6 round-robin matches per group stage, draws each match outcome from the three-way probability distribution, ranks teams by (points, goal difference), advances top 2 plus 8 best third-place teams, then runs single elimination for knockout rounds.

After 10,000 iterations, we count how often each team reaches each stage to produce probabilities for every Polymarket market type: TOURNAMENT, BRACKET, GROUP, and MATCH.

The simulation captures path dependencies that simple multiplication misses. Argentina's probability of winning the tournament isn't just P(win QF) × P(win SF) × P(win F) — it depends on who they face, which depends on other group outcomes.

3. Edge Detection

For each Polymarket market: edge = Pmodel − Pmarket

Where Pmodel is our probability estimate and Pmarket is the current Polymarket price (which represents the market's implied probability).

A positive edge means the market underprices probability — a buying opportunity. We require a minimum edge threshold of 3% to account for model uncertainty and transaction costs.

Example: If our model gives Spain a 72% chance of winning Group H, and Polymarket prices it at 64%, the edge is 8%.

4. Kelly Criterion Position Sizing

The Math

The Kelly criterion maximizes the long-run growth rate of a bankroll. For a binary outcome with model probability p and decimal odds b: f* = (p × b − q) / b where q = 1 − p.

This is the fraction of your bankroll that maximizes E[log(wealth)].

Fractional Kelly

Full Kelly is volatile. We use quarter Kelly (0.25 × f*), which sacrifices ~44% of the theoretical growth rate but reduces variance by ~75%.

Guardrails

The raw Kelly fraction is further constrained: minimum bet $50, maximum bet min(user's max bet setting, $500), and bets under $50 are skipped.

Worked Example

Spain to win Group H: p=0.72, market price = 0.64.

f* = (0.72 × (1/0.64 − 1) − 0.28) / (1/0.64 − 1) = 0.287

f_actual = 0.25 × 0.287 = 0.072

With a $1,000 balance: bet $72. With a $5,000 balance: bet $360, capped to min(360, max user bet).

5. Portfolio Construction

Individual bets might have edge, but a portfolio of 50 correlated bets on Argentina can blow up if Argentina has a bad tournament. We apply a 5-factor scoring system and diversification constraints.

Each market is scored on edge, model confidence, liquidity, team independence, and expected value. Opportunities are sorted by score and selected greedily, subject to constraints: maximum 5 bets per team, portfolio capped at 50 total bets.

6. Data Pipeline

ESPN Scraper

Every 2 hours, we fetch the FIFA World Cup 2026 scoreboard from ESPN's API. This returns structured JSON with match results, scores, dates, and fixture schedules.

Group compositions come from Wikipedia's structured templates as a fallback (ESPN doesn't expose group assignments in its scoreboard API).

After scraping, we re-apply all match results to the ELO model and regenerate tournament probabilities. This means the model adapts in near real-time as the tournament progresses.

Polymarket Market Discovery

We query Polymarket's Gamma API for World Cup markets. Each event contains multiple markets (e.g., "Spain vs Saudi Arabia" has YES/NO markets for each team). We classify markets by event slug patterns:

  • world-cup-winner-*: TOURNAMENT
  • world-cup-*-reach-*: BRACKET
  • -win-group-*: GROUP
  • fifwc-*: MATCH

Prop markets (exact scores, number of goals) are filtered out.

7. Execution Architecture

Wallet Model

Each user gets a Gnosis Safe (smart contract wallet) on Polygon. The user delegates signing authority to Privy's server wallet infrastructure. This means the bot can sign transactions on behalf of the user without holding any private keys — Privy's TEE (Trusted Execution Environment) handles the actual ECDSA signing.

The flow:

  1. Bot decides to place a bet (model says there's edge)
  2. Bot calls POST /api/bot/place-order on the web app
  3. Web app constructs the order, signs it using Privy's server signer
  4. Signed order is submitted to Polymarket's CLOB
  5. Bot records the bet in Supabase

The user's funds never leave their Safe. The bot can place trades from the Safe but cannot transfer funds out of it.

Settlement and Fee Collection

Every 5 minutes, the settlement loop checks each market's resolution status on Polymarket. For winning bets: fee = profit × 0.12. The 12% fee is collected via a gasless USDC.e transfer from the user's Safe to the revenue wallet. Losing bets incur zero fees — the incentive structure is fully aligned.

8. Scale and Performance

As of matchday 3 of the WC2026 group stage:

  • 48 teams across 12 groups
  • 40 match results processed through ELO
  • 32 upcoming fixtures in the pipeline
  • 254 predictions written to Supabase across all market categories
  • 50 opportunities in the active portfolio with positive edge
  • 10,000 Monte Carlo iterations per prediction cycle

The entire prediction cycle runs in under 30 seconds on a single Railway container.

Technical Stack

  • Web app: Next.js 14, Privy (auth + server wallet signing), Supabase (PostgreSQL + RLS), deployed on Vercel
  • Bot service: Python, FastAPI, async scheduler loops, deployed on Railway
  • On-chain: Gnosis Safe on Polygon, Polymarket CLOB + relayer, USDC.e
  • Data sources: ESPN API (match results), Polymarket Gamma API (market prices), Wikipedia API (group compositions)

The system is live and trading the FIFA World Cup 2026. The platform is at https://pop.zerith.studio/.