Better xG, Worse Bets: Why Shot-Level Accuracy Doesn't Help
A/B tested FotMob shot-level xG (82.1% regression) vs FootyStats match-level (75.6%) for non-Big-5 variance filter. Shot xG removed 524 profitable bets (entry-adj ROI +9.9%) and added 219 bad ones (ROI -9.5%). Net: -0.2pp ROI, -17u P&L. Better regression accuracy doesn't equal better bet selection.
Better xG, Worse Bets: Why Shot-Level Accuracy Doesn't Help
We had a clean hypothesis: FotMob shot-level xG achieves 82.1% regression accuracy for non-Big-5 leagues vs FootyStats's 75.6%. Swap the variance filter's data source, get 6.5pp better regression detection, make more money.
It didn't work. Shot-level xG produces slightly *worse* betting results.
The Question
Our variance filter identifies teams overperforming their xG and skips bets backing them (they'll regress). The xG source determines who gets flagged. FootyStats provides match-level aggregates; FotMob provides per-shot coordinates we can run through our XGBoost model. The shot-level approach should be more precise — it captures shot *quality* independent of finishing outcomes.
Does better regression accuracy translate to better bets?
What We Found
| Metric | FootyStats (production) | FotMob Shots | Delta |
|---|---|---|---|
| Bets | 12,522 | 12,217 | -305 |
| CLV | +11.8% | +11.8% | 0.0pp |
| Closing ROI | -3.1% | -3.4% | -0.2pp |
| Entry-adj ROI | +7.3% | +7.1% | -0.2pp |
| P&L | -393.7u | -410.7u | -17.0u |
The bet pools overlap 96%. The 4% difference is where it matters — and it favors FootyStats.
The Nuance
The critical finding is *which* bets change:
- Shot xG removed 524 bets that were profitable (entry-adj ROI +9.9%, hit rate 57.4%)
- Shot xG added 219 bets that were bad (ROI -9.5%, entry-adj ROI +0.1%)
The "more accurate" xG source is removing our best bets and replacing them with mediocre ones.
By league, no consistent pattern: League One -1.7pp, Championship -1.1pp, Eredivisie -0.5pp. Small positives in Brazil +0.4pp and Portuguese Liga +0.3pp don't offset.
Walk-forward: shot xG wins 8 of 17 seasons, loses 9. Pure noise.
Why Better Regression Accuracy Didn't Help
The 82.1% vs 75.6% regression rate was measured offline: "what fraction of teams flagged as overperforming actually regressed?" But the variance filter's job isn't just to identify regression — it's to identify regression *that the betting market hasn't already priced in*.
FootyStats's "noisier" xG creates a different set of regression candidates than the shot-level model. Some of those candidates are teams the market has already adjusted for (the regression is priced in). The production system's calibration — thresholds, lookback windows, interaction with other filters — has been tuned around FootyStats's characteristics. Swapping the data source breaks that calibration without providing a compensating improvement.
The deeper lesson: xG precision and betting edge are different metrics. A noisier signal that's been well-calibrated can outperform a precise signal that hasn't been.
What This Means
Keep production as-is. FootyStats match-level xG stays as the non-Big-5 variance filter source. The shot-level infrastructure remains useful for other purposes (player finishing multipliers, advanced metrics) but doesn't improve bet selection.
What's Next
Nothing further on this path. Tested twice (1 season, then 3-4 seasons), same result both times. The variance filter is well-calibrated at its current data resolution. Future improvements should focus on *what to do* with regression candidates (sizing, conditional filters) rather than *how to identify* them.