r/algobetting

Prediction Market vs Sportsbook Pricing Inefficiencies

I have recently been working on an algorithm that identifies pricing inefficiencies between prediction markets like Kalshi and Sportsbooks (specifically sharps like Pinnacle). I have gathered a lot of really interesting data and I am starting to spot some profitable trends. For example, treating Sportsbook odds (after taking out vig etc.) as a baseline for true probability, we can effectively create closing live value via taking advantage of prediction markets inability to accurately price in new data flow. I would love to work with some like minded individuals on this project so please reach out if you are interested. (Not advertising, just want to share my interest with people like you guys).

reddit.com
u/ClosingEdge — 23 hours ago
▲ 0 r/algobetting+1 crossposts

From Crypto Bots to Football: I applied my 400+ model "Quant" system to sports betting

https://preview.redd.it/3d3n5qc6ha1h1.png?width=1920&format=png&auto=webp&s=3d4008b8b6d332acb5a9286dca0c2bd8222501d5

(This is a repost, because for some reason Reddit didn't like the language I used on my previous post)(This is a repost, because for some reason Reddit didn't like the language I used on my previous post)

Hey everyone,

I’m an IT student currently refining a quantitative framework I’ve been developing over the last two years. Initially, my focus was on high-volatility assets like crypto, where I spent time building models to account for market sentiment and volume. Recently, I decided to take on a much more complex challenge: the football (soccer) market.

For the last 6 months, I’ve been migrating my "Quant" architecture to handle sports metrics. My goal shifted from managing capital to building a purely statistical "second brain"—a research tool designed to strip away the "gut feeling" and narratives that usually cloud this space.

  • The Architecture: A pipeline of 400+ ensemble models processing 60+ variables per fixture.
  • Data Inputs: I focus strictly on market movement (odds) and team-level performance metrics (xG, possession, etc.). I’ve deliberately excluded individual player data to reduce noise and maintain model scalability.
  • Markets: Currently modelling HDA, Over/Under, Goals and BTTS. I’ve recently added Corners, and Double Chance is currently in testing.
  • Coverage: Wide-scale coverage including the big 5 European leagues, Championship, MLS, and several Scandinavian and South American divisions.

The approach is 100% mathematical. I’m looking at this as a probability problem rather than a sports problem. In early testing with a small group of users, the model has shown a consistent ability to identify value in high-variance markets (specifically the MLS and lower European divisions).

I’ve reached a point where my own backtesting and limited forward-testing show a steady statistical edge (maintaining a 60%+ hit rate on primary markets during the last cycle), but I need more "stress testing" from people who understand algorithmic modelling.

I’ve built a dashboard to host these daily statistical projections to keep the project organised. It’s a completely free research tool—I’m not looking to sell anything.

I’m looking for "power users" and fellow quants/developers to help me refine the logic. I want to confirm these data points are useful to other researchers before I look into scaling the infrastructure or approaching potential investors.

I’m happy to share the data or the link for the dashboard in the comments if anyone wants to look at the projections for this weekend’s fixtures.

I'm keen to hear your critiques on the methodology:

  • Are there specific high-signal variables I might be missing?
  • Should I expand into player-specific props, or does that introduce too much variance for a quant model?
  • What other niche leagues tend to follow statistical trends better than the "top-heavy" ones like the Premier League?

Looking forward to some technical feedback! I have also shared some pictures of my system, how the process is going and also my own picks for the day based on what the system suggested

https://preview.redd.it/on9g2xp4ha1h1.jpg?width=800&format=pjpg&auto=webp&s=be4521807ecdf26e0ed979a10480102d97cffc1a

https://preview.redd.it/6zyq0oc6ha1h1.png?width=1038&format=png&auto=webp&s=7d6f09c1cf6c727a33c4c7ed420fb7ef38e7eac7

https://preview.redd.it/bw732pc6ha1h1.png?width=1201&format=png&auto=webp&s=0551841ec420cdf9ec4e893bdb1406b861a32b5b

reddit.com
u/Internal-Cover-339 — 1 day ago

E-sports API

Does anyone know of an API that provides E-sports odds? Ideally for UK Bookmakers, but US will do. For the life of me I can't find one. I don't just want match winners, but submarkets as well, such as handicaps and over/under maps. I'm happy to pay, but a free tier to test would be helpful.

reddit.com
u/Alexz54231 — 1 day ago

Stop modeling rebounds as rebounds. Start modeling missed-shot environments and you will have better WR%.

I’ve been building NBA prop models for a while and rebound props have always been one of the more interesting ones to break down.

You can’t just model player averages, minutes, opponent rebounding rank, recent form, line value, etc.
I used to and hit the same roadblock for Rebounds every season, that’s when I found it’s the wrong starting point.

A guy can be an elite rebounder, but if the matchup pulls him away from the rim, the opponent does not miss much, or he is sharing the floor with another rebound vacuum, the average starts lying pretty fast.

I started testing rebound props less like:
“is this player a good rebounder?”
and more like:
“is this game going to create the right kind of rebound chances for his role?”
⚠️ The first filter that stood out was rest advantage for bigs.

Filter:
Centers / PFs
24+ min per game
2+ days rest
opponent on second night of a back-to-back
REB props only

2023-24 season:
104 qualifying games
Over hit 56.8%
Average line: 9.2
Average actual: 10.1
Delta: +0.9 rebounds
2024-25 season:
98 qualifying games
Over hit 58.1%
Average line: 9.4
Average actual: 10.4
Delta: +1.0 rebounds

Not some insane “retire tomorrow” edge, but it held across both seasons and the mechanism makes sense. The rested big isn’t always the better rebounder it’s just the environment is just better. (Not including Wembanyama)

That is the part I think people miss with rebound props.
They look at the player average, but the better question is where the available rebounds are coming from.

A missed rim attempt is not the same as a missed above-the-break three. A corner three does not rebound the same as a pull-up middy. A center guarding a stretch 5 is not in the same rebounding position as a center sitting near the rim all night. Or a forward playing next to a weak rebounding small-ball lineup is not the same as a forward sharing minutes with two glass cleaners.

Same player. Same line. Completely different rebound environment.

Player projects for 32 minutes, opponent creates above-average missed shot volume, matchup keeps him near the rim, no second rebounder is stealing boards, and the line is still priced near his season average.
That is a very edge opened bet.

Curious if anyone on reddit models rebounds this way?
I’m happy to share the SQL filters / schema if anyone wants to replicate it or poke holes in it.

reddit.com

How do you determine your ideal max drawdown?

I'm trying to choose my bankroll sizing (1%, 3%, 5%), finding the right balance between my max drawdown and final P/L.

Am I thinking about this the right way?

Are there any good "rules of thumb" here? or is it just whichever max drawdown you are comfortable with for the max reward?

reddit.com

How do you validate on a simulation based model?

I've been working on a model for the past few months and I have it set up to simulate a match up between two opponents thousands of times to give the outcome.

I collected historical closing line betting data as I'm working on trying to validate its performance. My issue is that backtesting takes a ton of time to run simulations over thousands of matches across multiple years.

I have tried using a surrogate model as a cheap approximation of the simulation, but I am skeptical of this being the best approach.

I am curious how other people handle this issue, or in general what people's thoughts are on this approach to modeling.

reddit.com
u/1ce_berg — 2 days ago
▲ 18 r/algobetting+12 crossposts

I built a sports analytics app for player prop research — would love feedback

Hey everyone! I just launched the iOS version of AlgoSwish, a sports analytics app I’ve been working on for a while.

The app is built for bettors who want to research smarter without having to jump between a bunch of different sites. Right now, it’s focused on NBA analytics and includes things like:

  • Player prop research
  • Player analysis and stat breakdowns
  • Market movement
  • Bet tracking
  • Model picks
  • Parlay builder

A big thing I want to mention: most of the app is free to use, and you don’t even need an account to try some of the free research tools. The main Pro feature right now is the Picks screen.

iOS is live now, and Android should be coming sometime next week.

Current roadmap:

  • WNBA next
  • MLB after that
  • NFL after that
  • More sportsbooks, exchanges, and DFS-style books planned too, including platforms like Kalshi, PrizePicks, Novig, and more
  • Currently launching in the US and Canada first, with UK, EU, and Australia planned later

Since I’m launching late into the NBA season during the playoffs, I also want to be transparent: the model picks and parlay builder have tested really well during the previous seasons, but playoff rotations and matchups can get weird, so I’d be more cautious/selective with picks during this stretch. I’m going to keep improving the app as more data comes in and more sports are added.

I’m also offering a welcome deal for early users:

50% off the 1-month Pro subscription for the first 100 people who redeem it. Code expires May 31, 2026.

Redeem promo code:
https://apps.apple.com/redeem?ctx=offercodes&id=6764715128&code=WELCOME

App Store Download link:
https://apps.apple.com/us/app/algoswish-sports-picks/id6764715128

I’d genuinely appreciate any feedback, good or bad. I’m trying to build this into a high-quality sports analytics app with fair pricing and useful tools, not just another hard-paywalled betting research app.

Thanks for checking it out.

u/dubuckets — 3 days ago

Does Pinnacle price tennis underdogs efficiently enough to use as an EV benchmark?

I’m looking into tennis betting models and wanted opinions from people who have worked with Pinnacle closing/opening prices.

For favorites, Pinnacle is usually treated as one of the sharpest reference markets. But I’m less sure about underdogs in tennis, especially lower-liquidity matches, smaller tours, qualifiers, Challenger/ITF, retirements risk, injury/news lag, and matchups where public bias may push favorite prices.

My question is:

Can Pinnacle underdog prices be trusted as a reliable “true probability” baseline for finding EV elsewhere, or do tennis underdogs need extra adjustment before using Pinnacle as the reference?

For example, if Pinnacle implies an underdog is 35% after removing vig, and another book offers odds implying 31%, is that usually enough to treat it as +EV, or are there known distortions in tennis underdog pricing that make this unsafe?

Interested in any experience with closing line value, underdog calibration, sport-specific bias, or differences between ATP/WTA/Challenger markets.

reddit.com
u/IllustriousGrade7691 — 4 days ago
▲ 1 r/algobetting+2 crossposts

Per-bucket Platt scaling on a 425-bet sports model: global per-sport fit was making it worse

Working on a sports prediction model in my spare time and ran into a calibration issue that surprised me. Sharing in case it's useful, or anyone has thoughts.

Setup: my journal has ~425 graded singles across NBA, MLB, and MMA. I was applying per-sport Platt scaling (one A/B sigmoid fit per sport) as a final residual correction after the Elo + form + market-anchor blend. Standard pattern from the binary-classifier literature.

Worked fine until I started bucketing the journal by verdict tier (STRONG BET vs GOOD BET) and noticed the two tiers were miscalibrated in opposite directions:

NBA STRONG (eff_n=28, 30d half-life):   A = -6.83, B = +4.23
NBA GOOD   (eff_n=22):                  A = +2.65, B = -1.77
MLB STRONG (eff_n=46):                  A = +3.57, B = -2.52
MLB GOOD   (eff_n=127):                 A = +2.10, B = -1.12

The NBA STRONG and GOOD slopes disagree on sign. The single per-sport NBA fit (A=-1.36) was averaging those two errors and correcting both buckets wrong.

Fixed by switching to per-(sport, verdict_tier) Platt with a fallback chain: per-bucket when eff_n ≥ 12, else per-sport, else global, else identity. Verdict tier at inference is inferred from the probability band (p ≥ 0.68 = STRONG, 0.55-0.68 = GOOD) since the actual verdict label isn't known until edge is computed downstream.

Delta on synthetic predictions:

NBA STRONG @ p=0.78:  per-sport -> 0.358,  per-bucket -> 0.251  (-10.7pt)
MLB GOOD   @ p=0.62:  per-sport -> 0.516,  per-bucket -> 0.546  (+3.0pt)

Calibration audit is live at lakeshore-edge.com/model if anyone wants the raw data. Per-bucket coefficients update on the journal reflect loop.

Caveats I'm aware of:

  • 425 bets is still tiny for a 2-parameter sigmoid per bucket
  • Verdict-tier inference from p-band has its own selection bias (high-p picks become STRONG more often, so the bucket fit is fitting on a non-random subset)
  • Time-decay weighting (30d half-life) is plausible but not validated against a held-out window

Question for the sub: anyone done per-bucket calibration in this kind of small-sample regime? Specifically deciding between hierarchical Bayes (pool partial information across buckets) and the simpler fallback chain I'm running now.

u/mangoman40114 — 3 days ago

Historical Odds API

Looking to scrape historical in-game NBA spreads/moneyline/totals, currently use Odds API which has every 5 minutes ... wondering if there's anything more granular than that (like every 1 min) without having to spend thousands

reddit.com
u/Superb_Sand8384 — 3 days ago
▲ 0 r/algobetting+1 crossposts

Most bettors focus on wins and losses. I think CLV is more interesting.

The more I read about closing line value, the more it feels like one of the few metrics that actually says something meaningful about long-term betting performance.

Example:

- You bet a team at +120
- Market closes at +105

Even if the bet loses, you still beat the market price.

Over a large sample, that seems more important than whether a single bet won or lost.

What I find interesting is that CLV can reveal patterns like:

- whether early bets outperform late bets
- whether certain sportsbooks consistently offer softer lines
- whether “high confidence” bets actually beat the market
- whether positive CLV really correlates with long-term ROI

At the same time, I don’t think CLV is some magic stat either. You can have positive CLV and still lose money for long stretches because of variance.

Curious how people here think about it:

- Do you actively track CLV?
- Does it matter for recreational bettors?
- What’s considered “good” CLV over a season?

reddit.com
u/betfolyo — 4 days ago

+EV betting system - what are the best sharp books?

Right now, I use Pinnacle as my source of truth with most of the weight, plus FanDuel and DraftKings for retail volume at a very small weight, and BetOnline as the offshore piece. I bet EV mainly on gamelines.

A few questions:

  1. Should I drop FD/DK/BetOnline entirely and just lean on Pinnacle as a single source of truth? Or does the small weight on the others actually add real value?
  2. Am I missing another genuinely sharp book worth pulling into the consensus? I tried Circa for a while, but the feed is buggy, and I can't get a clean, stable odds stream for my needs. Is there a "circa" substitute out there worth trying?

Curious what setups other EV bettors are running.

reddit.com
u/Shaharzuaretz — 5 days ago

Built a bot that follows sharp money on Pinnacle and Betfair. 83 bets later, here's what I found.

Bot performance

So I got into this whole steam betting thing properly about a year ago and it kind of took over my life a bit. For context I built a little scanner that watches Pinnacle and Betfair and fires an alert whenever both books move on the same outcome at the same time. The dual confirmation thing was something I added after noticing that single book moves were way noisier.

Anyway I wanted to share some of what I've learned about filtering because I think this is where most people get it wrong including me at the start.

For football the move has to be at least 4 to 8 percent depending on how close we are to kickoff. The closer to the game the smaller the threshold because sharp money tends to come in late and even a 4 percent move an hour before kickoff is meaningful. Early in the week a 4 percent move on a football line means almost nothing, you need something bigger to cut through the noise.

NBA is interesting because the lines move constantly and you get a lot of garbage movement. What I found is that NBA alerts are actually more reliable than football ones when they do trigger, probably because the market is so efficient that anything getting through the filter is real. We're seeing around 80 percent win rate on NBA signals which I honestly did not expect.

Ice hockey is the smallest sample but the signals that do come through tend to be pretty clean. Fewer leagues tracked so less noise overall.

One thing I'm still not sure about is timing. I alert in real time the moment both books confirm the move but I keep wondering if waiting two or three minutes to see if the line holds would improve results or just cost value. My gut says you want to be in as early as possible but I genuinely don't know.

Also curious how people here handle staking. I'm using proportional sizing, bigger stake on stronger signals, smaller on standard ones. Seems to work but would love to know if anyone has tested something different.

Happy to share the full public results if anyone wants to look at the actual data.

Crosspost to more communities

reddit.com
u/Impressive_Couple_19 — 5 days ago

How would you feel about using the following model on prediction markets

MARKET: MLB MONEYLINE
ODDS SOURCE: FANDUEL

Games 2413
Accuracy 0.5570
Brier score 0.2440
Brier skill score 0.0168
Log loss 0.6807
A/E ratio (all) 0.9564
───────────────────────────
Market brier 0.2423
Model vs mkt brier 1.0071
───────────────────────────
CLV (opening line bets vs closing line)
Games w/ both odds 2411
CLV mean +0.0031
Beat closing line % 50.00%
Edge vs close mean +0.0678
───────────────────────────
── Bets Against Opening Line ──
EV bets 1780
EV ROI +0.0150
EV p-value 0.2854
EV significant False
All-bets ROI +0.0151
Sharpe 0.0134
Max DD (units) 53.37
A/E ratio 0.9198
Kelly profit $-273.57
Kelly ROI -0.0297
Kelly Sharpe 0.0239
Bootstrap ROI +0.0143
95% CI [-0.0353, +0.0677]
Prob of profit 0.7010
───────────────────────────
── Bets Against Closing Line ──
EV bets 1796
EV ROI +0.0145
EV p-value 0.2954
EV significant False
All-bets ROI +0.0185
Sharpe 0.0127
Max DD (units) 54.57
A/E ratio 0.9063
Kelly profit $-144.46
Kelly ROI -0.0097
Kelly Sharpe 0.0466
Bootstrap ROI +0.0137
95% CI [-0.0371, +0.0664]
Prob of profit 0.6970
───────────────────────────
── Bets Against Closing line @ 1% vig (prediction market proxy) ──
EV bets 2263
EV ROI +0.0558
EV p-value 0.0106
EV significant True
All-bets ROI +0.0546
Sharpe 0.0485
Max DD (units) 44.73
A/E ratio 0.9370
Kelly profit $+1,264.20
Kelly ROI +0.0226
Kelly Sharpe 0.1086
Bootstrap ROI +0.0552
95% CI [+0.0017, +0.1029]
Prob of profit 0.9770
───────────────────────────
── Bets Against Opening line @ 1% vig (prediction market proxy) ──
EV bets 2263
EV ROI +0.0508
EV p-value 0.0161
EV significant True
All-bets ROI +0.0505
Sharpe 0.0451
Max DD (units) 44.91
A/E ratio 0.9424
Kelly profit $+1,366.19
Kelly ROI +0.0306
Kelly Sharpe 0.1112
Bootstrap ROI +0.0514
95% CI [+0.0064, +0.0973]
Prob of profit 0.9880

reddit.com
u/Alarmed-Error529 — 5 days ago

How can I get the results of games so I can track my bets?

Hey everyone. So when I track a bet in a spreadsheet, I want a simple way I can track the result of the bet without scrolling through the internet and manually finding the result for each one. Sometimes, I track hundreds a day and manually tagging them is genuinely time wasting.

Does anyone know any API, or any product that enables you to find the result of a game so I can do the tracking efficiently?

reddit.com
u/WasabiPrestigious533 — 5 days ago

Looking for partner with Betfair Api account

I have an existing betting model that has been backtested on 2 years of historical data and currently shows a small edge of around 3-5%. I am using fast data providers such as Genius Sports and Opta.

I am looking for a partner who can provide a Betfair account with Api access enabled, along with a small testing bankroll, and who would be able to pass Source of Wealth verification if required.

The plan is to start with low-risk testing - mainly small-stake value betting and some market making. Initially, I want to run the model with very small stakes (around $1 per bet) for approximately 1 month before scaling further. The goal is to confirm that the edge exists not only in backtesting but also in real live trading conditions.

The partner’s role would mainly be:

  • Providing a Betfair account with API access
  • Handling deposits and withdrawals
  • Working on a revenue share basis

We can start with a very small bankroll, around $500, and scale gradually if results are positive.

Betfair is not available in my country, and I do not want to open an account using a drop or someone else’s identity because I eventually plan to scale the bankroll significantly, and that would be too risky long term.

That is why I am looking for a partner from a jurisdiction where Betfair is officially supported who can provided funded account.

I expect to be ready for production within 2-3 weeks once I get access to an account and finish the integration.

Please DM me if you are interested.

reddit.com
u/Glittering-Canary516 — 6 days ago

Predicting World Cup winner?

I’m wanting to do a side project to predict the winner of the World Cup, but I’m unsure of the best route to take. This is not meant to inform any betting. It’s just something I want to do for fun :)

In short, if you were to predict the winner of the World Cup, how would you go about it?

I’ve done modeling in the past of soccer, but everything I’ve done doesn’t seem applicable to the World Cup. Using historical data of previous games seems inaccurate, given four years have passed and teams change wildly. Elo ratings also seem impossible to calibrate for a similar reason. Using individual stats from the players that were invited to each national team sounds like an insane workload.

I basically don’t have any ideas that are solid to model this kind of event. Again, given this is meant to be a side project, I just want to come up with an informed guess, but I’m having a hard time thinking of something substantially better than a coin flip.

Any thoughts are appreciated!

reddit.com
u/New_Educator_4364 — 5 days ago

Built a profitable live in-game probability engine for football across 25 european leagues

Been lurking for a while and finally ready to share my results.
I've always bet live on football matches. If you understand football and you're actually watching, you can read things in real time, whether momentum is shifting, whether the team in possession is actually doing anything with it, whether the other side is dangerous on the counter. But the watching is the catch. You can only really watch one or two games at a time on any given matchday, most of the in-play market is happening without you. That's the gap I wanted to close so i build a live in-game probability engine that runs across 25 European football leagues, updates every 15 seconds, and compares its number to the live book. Bottom-up, built on top of a third-party live stats feed.

Pre-match first. You can't build a live model without a pre-match prior. Otherwise every in-play probability is just whatever the last 90-300 seconds of stats say, with no anchor. So I started with: pre-match WDL(1X2), BTTS, and Over/Under 2.5. Those probabilities become the prior the in-play engine starts each match with.

My Live engine, updated every 15 seconds. The live engine wakes up every fifteen seconds for every fixture in play and recomputes the probability using current match state, score, minute, attacking pressure, shot quality, dangerous events, ball coordinates, ball posession etc. All of those combines gives a probablity for each market. The prior (prematch prob.) fades as in-play evidence accumulates. Architecturally: one upstream poller pulls the stats feed (a single third-party provider)

How i deal with the actual betting. Betting on every positive edge from a live in-game model is very difficult. Odds change every minute of the game, and even after calibrating a million times, not every edge that shows up is an honest one compare to the bookmaker. So I ran audits on when the edge actually was honest, and tuned my way to the sweet spot. That sweet spot is what fires a "Featured Signal" and that's what I bet on.

Results:
And to be honest I dont get why more people aren't doing this. I know it takes time, but im sure I founds some honest holes.

My main in-game comparison is bet365 - meaning you're probably looking at an even more profitable version of this if you're doing in-game line shopping across multiple sharper books. I'm open to discussing models as long as it doesn't directly expose the live engine because there is a lot to cover and I dont want to turn this into a long read.

There was a thread in this sub a while back asking why people don't share their winning models. I didn't fully get it at the time. I do now. It takes a ton of months & hours building, adjusting, backtesting, forward-testing, re-adjusting again and again. It never stops.

Anyways - here are the results last 54 days: 2026-03-20 → 2026-05-12 inclusive.
40 distinct match-days with at least one featured signal (the other 14 days had no qualifying signals)

326 total signals
Won - Lost: 172 - 77
Hit rate - 69%
P&L:+75.75u
ROI:+30.42%
Avg odds: 1.91
Longest win streak: 15
Longest loss streak: 8

By market:

Market n Hit ROI Avg odds
HOME WIN 108 80.6% +15.1% 1.22
OVER 2.5 84 64.3% +23.7% 1.92
OVER 1.5 22 86.4% +136.9% 1.45
UNDER 1.5 20 30.0% +34.9% 5.24
UNDER 2.5 15 40.0% +16.5% 3.06

Happy to share much more, but not sure what is allowed and how to share the underlying data without exposing my models to much. Let me know.

u/iph0ngaa — 8 days ago

Tennis odds + live scores API

Does anyone have a source of historical + upcoming tennis odds and live scores? Ideally through an API, not scraping.

For the odds data I need
- moneylines
- game spread
- set spread
- total games (nice to have)

I also need point-by-point live scores - not historical scores, have that covered.

A big caveat - I need challenger data, not just ATP/WTA. ITF or UTR is just nice to have.

I can't find a single source that has this - everything seems to be missing Challenger or doesn't have game spread, etc.

reddit.com
u/Remarkable-Bowler-60 — 6 days ago
▲ 71 r/algobetting+2 crossposts

I built a predictive model for football match stats (shots, corners, fouls) across 20,000 matches. The strongest predictor ended up being ELO from chess. [OC]

For the past few months I've been working on a personal project: a predictive model for per-match football statistics. Not the final score, but the behaviors: how many shots each team will take, corners, fouls, cards. The dataset covers around 20,000 matches across five seasons and the top 5 European leagues.

I started with hundreds of variables: rolling shot averages, foul rates, corner frequencies, home/away splits, opponent profiles. Everything you'd expect. The first results were decent, but the model was essentially regressing toward each team's historical mean without any real understanding of match context. It could see that Team A averages 14 shots and Team B averages 11, but it had no concept of the gap between the two sides. It didn't know that tonight Team A is so much stronger they'll pin Team B in their own half for 70 minutes and probably end up with 19 shots while Team B scrapes together 6.

Historical averages are built against opponents of all quality levels. They encode nothing about the specific match being played, and that contextual read is exactly what every football fan processes automatically before kick-off. The hard part is giving a model a number for something so intuitive.

I ended up turning to chess. ELO ratings were invented in the 1960s by Arpad Elo to classify players more precisely than tournament standings alone. Beat someone stronger and your score rises significantly; lose to someone weaker and it drops. It updates after every game, with the only inputs being the result and the relative strength of the two players — no performance quality, no expected goals, just who won and against whom.

I built an ELO system for all clubs across the top 5 leagues, initialized from external sources and updated match by match through five seasons. When I added the ELO gap between the two teams as a predictor, things shifted immediately.

Bivariate Spearman correlation with shots:

Predictor Correlation
ELO gap 0.377
Rolling shot average 0.273

The chess number outperformed every football-specific variable in the model. And when you break it down by bucket, it's obvious why:

ELO gap Avg shots
< −200 (much weaker) 9.2
−200 to −100 10.5
−100 to −50 11.0
±50 (balanced) 12.8
+50 to +100 13.0
+100 to +200 14.4
&gt; +200 (much stronger) 17.4

Global average: 12.7 shots

From 9.2 to 17.4 driven entirely by the strength gap — and no rolling average captures it, because rolling averages don't know who those shots were taken against. A team that faced three weak sides in a row will have inflated numbers; the ELO gap adjusts for that automatically.

200 variables, five years of data, six leagues, and the most important feature had nothing to do with football.

Happy to get into the methodology or the initialization choices in the comments.

u/Agalex97 — 9 days ago