Skip to content
Methodology

How the model works

We don't hide the math. The sections below explain exactly how each probability on a match page was produced, and why we think this approach beats the "AI picks" apps people complain about on Reddit.

The core idea

We estimate a probability distribution for every outcome of every match — then compare those probabilities to the market. When our number is higher than the vig-removed book price, that's a +EV edge. When it's lower, the book is right and we say so.

Football — Elo + logistic + Poisson grid

Match-winner probabilities start from per-sport Elo (K=20, home advantage +65). A logistic regression on top takes features like rolling form, head-to-head, rest-day diff, and injury impact, then blends 55% Elo + 45% logistic for the final 1X2.

For goals-based markets we estimate team-level expected goals (λ) from the last 8 matches, then build a bivariate-Poisson scoreline grid. Every goals / BTTS / correct-score / Asian-handicap / HT-FT / first-half / team-totals / corners / cards market is derived from the same grid — mathematically consistent with every other market.

NBA — Normal-distribution scoring

NBA team points are well-modelled as Normal(μ, σ) distributions. Per-team means come from recent scored / conceded rates; per-player stat lines (points, rebounds, assists, 3PM, PRA) come from the last 30 game logs via balldontlie with outliers kept. Game totals, team totals, and ~100 player-prop predictions per match flow from those moments.

Tennis — best-of-N set math

Given a match-win probability P, we invert the q²(3−2q) (Bo3) or q³(10−15q+6q²) (Bo5) mapping via bisection to recover the per-set win prob q. Every set-based market — set betting (2-0 / 2-1 / 1-2 / 0-2), total sets, to-win-a-set — is then computed exactly. Surface-specific Elo (hard / clay / grass) blends in at 70%.

News context — as a feature, not the predictor

Gemini 2.5 Flash with Google Search grounding runs exactly one call per match. It returns structured JSON of injuries, suspensions, lineup notes, and a sentiment score. This feeds the model as features— never as the prediction. LLMs are bad at numbers and good at reading news; we use each for what they're good at. News is cached per-match with a kickoff-aware TTL so most analysis regenerations don't re-spend LLM quota.

Self-correction: Platt calibrators

Every night, a job reads all graded analyses + outcomes and fits a Platt sigmoidper sport (2 params: a, b). The predictor picks up the fitted calibrator and re-squishes probabilities so that "the model's 70%" actually means "matches like this win 70% of the time." This is the self-improvement loop that pure Elo-only systems lack.

The accountability we promise

  • Every prediction we ever serve is persisted and graded when the match ends. You can browse the ledger on /accuracy.
  • Rolling 30-match Brier + calibration charts are public. Bad stretches show up as clearly as good ones.
  • Win / loss streaks on /accuracy/[sport]. No cherry-picked highlight reels.
  • Calibrator history at /accuracy/history — every nightly fit is one row with before/after log-loss.
  • Every +EV edge we emit can be saved to /picks with real stake + P/L + ROI + bankroll curve + max drawdown.

What this app doesn't do

  • It is not live betting — no in-play odds, no second-by-second updates.
  • It does not guarantee a winning strategy. +EV over a small sample still loses frequently.
  • It does not replace bankroll management — always size stakes you're willing to lose.
  • It is not legal in every jurisdiction. Check your local laws before acting on any output.
Not financial advice. 18+ where legal.