Serious football bettors have one thing in common: they have their own model.
Not the bookmaker's model. Not a tipster's. Theirs.
This guide walks you through building one in Excel in 90 minutes, using Poisson distribution and xG - the statistical foundation many football models are built on. No coding, no maths degree, no jargon.
By the end you'll have a working model that:
- Predicts goal probabilities for both teams.
- Generates 1X2, Over/Under, BTTS, and Correct Score probabilities.
- Calculates Expected Value (EV) vs bookmaker odds.
- Tells you when to bet and when to skip.
Build it from scratch, step by step. You'll understand every number the model produces.
Before we start - what you'll need
- Excel (or Google Sheets - every formula works in both).
- xG data for at least 8-10 recent matches per team. Free sources: Understat (big five leagues) or FotMob. FBref no longer publishes xG since January 2026, but it still has historical results. StatPair doesn't provide xG, but it gives you shots, shots on target and home/away splits for 35,000+ players (free trial here).
- 30-90 minutes depending on your comfort with Excel.
- A bookmaker odds reference (Pinnacle is the cleanest - closest to true odds).
Why xG is the foundation of any model →
The big picture - what we're modelling
A football match goal count follows a Poisson distribution reasonably well. If we know each team's expected goals (their attack rate × opponent's defensive weakness × home/away factor), we can compute the probability of any score.
The 8 steps below build this up cleanly:
Step 1 - Build the team strength database
Open a new sheet called TeamStats. Columns:
| Team | Home xG For | Home xG Against | Away xG For | Away xG Against | Matches |
| Team A | 2.10 | 0.95 | 1.65 | 1.20 | 10 |
| Team B | 1.80 | 1.10 | 1.40 | 1.50 | 10 |
| ... | ... | ... | ... | ... | ... |
(The numbers above are hypothetical.)
How to fill it: take each team's last 8-10 league matches at home and away. Average xG for and xG against by venue.
Why split home vs away? Because home advantage exists (across the big five European leagues in 2025/26, home teams scored 1.53 goals per match vs 1.23 for away teams), and team styles change by venue.
Why home/away splits matter → · The 10-match form rule →
Step 2 - Calculate league averages
In another sheet called LeagueRefs, compute the league-wide averages:
- League Avg Home xG: Average of "Home xG For" across all teams. (Typically ~1.50.)
- League Avg Away xG: Average of "Away xG For" across all teams. (Typically ~1.20.)
- League Avg Home xGA: Average of "Home xG Against" (typically ~1.20).
- League Avg Away xGA: Average of "Away xG Against" (typically ~1.50).
Excel formula:
=AVERAGE(TeamStats!B2:B21)
Why we need them: to convert each team's raw numbers into strength multipliers.
Step 3 - Compute Attack and Defence Strengths
Add four columns to your TeamStats sheet:
- HomeAtkStrength = HomeXGFor ÷ LeagueAvgHomeXG
- HomeDefStrength = HomeXGAgainst ÷ LeagueAvgHomeXGA
- AwayAtkStrength = AwayXGFor ÷ LeagueAvgAwayXG
- AwayDefStrength = AwayXGAgainst ÷ LeagueAvgAwayXGA
Excel formula example:
=B2 / LeagueRefs!$B$2
A value > 1 means above-average; < 1 means below-average. Now Team A's Home Attack of 2.10 ÷ 1.50 = 1.40 means they create 40% more chances at home than the average team.
Step 4 - Predict expected goals for a specific match
Open a new sheet called MatchPredictor. Inputs:
- Cell B2: Home team
- Cell B3: Away team
Use VLOOKUP to grab their strength values and compute:
HomeExpGoals = HomeAtkStrength × AwayDefStrength × LeagueAvgHomeXG
AwayExpGoals = AwayAtkStrength × HomeDefStrength × LeagueAvgAwayXG
Example: Team A (home) vs Team B (away), using the table above:
- Team A HomeAtkStrength = 2.10 ÷ 1.50 = 1.40; Team B AwayDefStrength = 1.50 ÷ 1.50 = 1.00
- Team B AwayAtkStrength = 1.40 ÷ 1.20 = 1.17; Team A HomeDefStrength = 0.95 ÷ 1.20 = 0.79
- HomeExpGoals = 1.40 × 1.00 × 1.50 = 2.10
- AwayExpGoals = 1.17 × 0.79 × 1.20 = 1.11
This means our model expects Team A to score ~2.1 and Team B ~1.1. Already useful - but the magic happens in the next step.
Now we calculate the probability of each goal count. Excel has a built-in Poisson function:
P(team scores X goals) = POISSON.DIST(X, ExpGoals, FALSE)
Build a table with goal counts 0-6 for both teams:
| Goals | P(Home scores X) | P(Away scores X) |
| 0 | =POISSON.DIST(0, B5, FALSE) | =POISSON.DIST(0, B6, FALSE) |
| 1 | =POISSON.DIST(1, B5, FALSE) | =POISSON.DIST(1, B6, FALSE) |
| 2 | =POISSON.DIST(2, B5, FALSE) | =POISSON.DIST(2, B6, FALSE) |
| 3 | =POISSON.DIST(3, B5, FALSE) | =POISSON.DIST(3, B6, FALSE) |
| 4 | =POISSON.DIST(4, B5, FALSE) | =POISSON.DIST(4, B6, FALSE) |
| 5 | =POISSON.DIST(5, B5, FALSE) | =POISSON.DIST(5, B6, FALSE) |
| 6+ | =1 - SUM(above 6 rows) | =1 - SUM(above 6 rows) |
Each cell now has the probability of each team scoring exactly that many goals.
Step 6 - Build the score probability matrix
Create a 7×7 grid: rows = Home goals 0-6, columns = Away goals 0-6. Each cell is P(Home goals) × P(Away goals) (assuming independence - we'll fix this in Step 8).
Excel formula:
=$B7 * C$5
(where $B7 is the home probability column and C$5 is the away probability row)
Sum the entire grid - it should equal ~1.0 (100%). If it doesn't, your formulas have errors.
This grid is gold. From here you derive every market.
Step 7 - Derive market probabilities
From the score grid:
- Home Win = Sum of all cells where Home goals > Away goals.
- Draw = Sum of diagonal (0-0, 1-1, 2-2, ...).
- Away Win = Sum of cells where Away goals > Home goals.
- Over 2.5 = Sum of cells where Home + Away goals > 2.5.
- Under 2.5 = 1 - Over 2.5.
- BTTS Yes = Sum of cells where Home goals ≥ 1 AND Away goals ≥ 1.
- BTTS No = 1 - BTTS Yes.
- Correct Score 1-1 = Single cell value (Home=1, Away=1).
Excel SUMIF / array formulas handle these. Example for Over 2.5:
=SUMPRODUCT((HomeGoals + AwayGoals > 2.5) * ScoreGrid)
You now have a probability for every market in football betting. Compare against bookmaker odds for each market →
Step 8 - Apply Dixon-Coles correction (optional but recommended)
Pure Poisson tends to under-predict low-scoring draws (0-0, 1-1) because real-world football has more "tight" defensive games than independent Poisson assumes.
The Dixon-Coles tau correction adjusts these specific cells, using a dependence parameter ρ (rho) and the two expected goals values λ (home) and μ (away):
- 0-0: multiply by (1 - λ × μ × ρ)
- 0-1: multiply by (1 + λ × ρ)
- 1-0: multiply by (1 + μ × ρ)
- 1-1: multiply by (1 - ρ)
ρ is estimated from historical results and is usually a small negative number, which raises 0-0 and 1-1 and lowers 1-0 and 0-1. Then renormalise the grid so it still sums to 1.0.
The correction matters most in correct-score and tight-game markets.
Step 9 - Calculate Expected Value vs bookmaker odds
This is where models become bets. For any market:
True Probability = your model's number
Implied Probability = 1 / Bookmaker Decimal Odds
Bookmaker Margin = (Sum of all implied probabilities for the event) - 1
Fair Odds = 1 / True Probability
Edge = (True Probability × Decimal Odds) − 1
If Edge > +3%, it's a real bet candidate. Below that, the variance and margin error eat your edge. Use our EV calculator to verify →
Step 10 - Stake size with Kelly Criterion
Don't bet flat. Use Kelly:
Kelly Fraction = (Decimal Odds × True Probability − 1) / (Decimal Odds − 1)
Most pros use half-Kelly (multiply Kelly by 0.5) to reduce variance.
Example: Your model says Over 2.5 has 58% probability. Bookmaker offers 2.00 odds.
- Edge = (0.58 × 2.00) − 1 = +16% (huge - be sceptical, recheck inputs)
- Kelly = (2.00 × 0.58 − 1) / (2.00 − 1) = 0.16 → 16% of bankroll.
- Half-Kelly = 8% of bankroll.
Use our Kelly calculator → · Master variance and Kelly →
Step 11 - Validate before betting real money
Before risking a cent:
- Run the model on 100 past matches (whose results you already know).
- Calculate ROI and CLV versus closing odds.
- If ROI < 2% over 100 bets, your model has bugs or weak inputs.
- If CLV < 0%, your model is worse than the market - refine before risking real money.
Aim for +3% CLV minimum before betting real money. Why CLV is the only real test →
Common mistakes I've seen people make
- Using too few games: 4-5 matches isn't a sample. Use 8-10 minimum.
- Forgetting venue split: Lumping home and away xG hides real differences in how teams play by venue.
- Ignoring squad changes: Big injuries (key striker out) make recent xG misleading. Inputs from absences analysis →
- Betting before validating: The biggest, most expensive mistake.
- Over-staking: Even a genuine +5% edge goes through long drawdowns. Read variance & Kelly →
When Excel becomes the bottleneck
Excel is fantastic for learning. It's slow for operating.
Once you understand what's happening under the hood, you'll hit a ceiling:
- Updating xG manually for 20 teams every week takes real time.
- Recalculating after team news adds more for every match.
- Cross-referencing several matches per matchday can take hours.
If building and maintaining a model sounds like too much work, StatPair gives you the inputs (goals, shots, home/away splits) instantly, plus AI projections for player props.
But seriously: build the Excel version first. You'll bet smarter forever.
Q: Do I need to know advanced statistics to build this?
A: No. Excel has the Poisson distribution built in (the POISSON.DIST function). If you can copy a formula, you can build this model.
Q: How accurate is the Excel model vs professional models?
A: A basic Poisson model won't match professional models, which use far more data sources, player-level inputs and constant recalibration. Treat yours as a way to understand prices and spot obvious mispricing. Test it honestly: record its fair odds before kick-off and compare them with the closing odds over a few hundred matches.
Q: How often should I update the inputs?
A: After every matchweek (8-10 game window rolls forward). Re-update when there's a manager change or major injury.
Q: Can I use this model for any league?
A: Yes - any league with reliable xG data. Smaller leagues need extra caution because xG is noisier with fewer matches. See small-league analysis →
Q: Should I bet on every match the model flags as positive EV?
A: No. Bet only matches with a +3% edge or larger AND where you've verified inputs are clean.
Q: What if my Edge calculation says +20% on a match?
A: Be very suspicious. Either the bookmaker offered a soft line (rare, possible), or your inputs are wrong (much more likely). Re-check team strengths, venue, and recent injuries before staking.
Bottom line
The model in this tutorial isn't theoretical - Poisson + xG is the framework many professional models started from. A basic version won't beat sharp markets on its own, but with clean data, honest validation and disciplined staking, it shows you exactly where your view differs from the bookmaker's.
The catch: most bettors give up before they've tested their model properly. Don't be them.
Next steps:
- Open a blank Excel file. Right now.
- Follow Steps 1-3 with one league (start small - Bundesliga is great because of clean xG).
- Validate against 100 past matches before betting real money.
- When Excel becomes the bottleneck, scale with StatPair →.
P.S. Profitable bettors rarely work from gut feeling. And over a small sample, luck looks exactly like skill. Build the math first.