GOAL MATRIX GOAL MATRIX
Dixon-Coles × Bivariate Poisson Engine
Live
λ Home
λ Away
Calibration
Best Bet
Pure DC ρ=— · τ=—
λ Home
λ Away
Calibration
Best Bet
League Average Goals
Advanced — Select League or Override
Using defaults: Home 1.50  |  Away 1.20  (toggle Advanced to change)
Core Model Input · Combined Stats + League Home/Away Baseline
📋 Full Match — Team Statistics
📊Team Season Stats— combined, all matches (home + away) · home-field edge applied automatically via the League Home/Away Averages below
V S
Games Played iMatches Played
Total matches this season, home and away combined. This is the sole foundation for the attack/defence rating — home-field advantage is then applied automatically using the League Home/Away Averages below, not by entering venue-specific data. Must be ≥ 1 to calculate; 3+ recommended for a stable rating.
Goals Scored iGoals For (GF)
Total goals scored across all matches this season, home and away combined. Used to estimate the team's attack rating relative to the league combined average.
Goals Conceded iGoals Against (GA)
Total goals conceded across all matches this season, home and away combined. Used to estimate the team's defence rating. Lower = stronger defence.
Elo Rating iElo Rating (Optional)
Neutral, venue-independent team-strength rating. Leave blank to skip — the model only applies it when both Home and Away are filled in. eloFactor = 10^((HomeElo − AwayElo) / 2000), capped ±20% on λ. The divisor is 2000, not the textbook Elo constant of 400 — 400 is calibrated for win-probability ratios and would saturate the ±20% cap by ~30 rating points; 2000 keeps the response graduated across realistic mismatches (see FAQ for detail). Source: club-elo.com or eloratings.net. If your source already bakes in a home-field bump for this fixture, entering it here on top of the model's own home advantage will double-count it.
⚽ Combined, all matches
⚽ Combined, all matches
Rating Confidence — how far the rating has moved off a flat league-average default?Rating Confidence
combinedMP / (combinedMP + 8), computed separately per side. At 0 games it's 0% (rating rests entirely on the league average); by ~8 games it's ~50%; by 16+ it's mostly your own data talking. Uncapped, unlike the Data Calibration badge.
Home: Away:
Enter each team's season-to-date combined stats (home + away)  ·  MP must be ≥ 1, 3+ recommended for a stable rating  ·  Yellow border = key rating inputs  
⚠️ Home GF or GA ratio looks very high (>4 per game). Double-check your stats.
⚠️ Away GF or GA ratio looks very high (>4 per game). Double-check your stats.
📈Recency Adjustments— recent form adjustment, optional
Recent Form
PPG-scaled · FormMult 0.85×–1.15× · combined adj capped ±25%
Team MP GF GA PTS Form
HOME
AWAY
ℹ️ PTS & GF/GA over the selected window · GD = GF−GA · FormMult = PPG-based 0.85×→1.15× on λ
0 / 5 fields filled
Calculating...

Enter team data on the Inputs tab and press Calculate.

Enter team data on the Inputs tab and press Calculate.

📋 Match List · Today
0 matches
No matches added yet. Run the model and hit "Add to Match List".

Calculate predictions first, then enter bookmaker odds to find value bets.

💡 How To Use GoalMatrix

Step 1 — Full Match Stats: Enter both team names, then each team's combined season record: games played, goals scored, and goals conceded across all matches — home and away together, not filtered by venue. Home-field advantage is applied automatically afterward, via the league Home/Away Averages in Step 3, so there's no need to hunt down venue-specific splits.

Step 2 — Elo (Optional): The 5th column in the stats table is Elo rating — leave it blank to skip, or fill in both Home and Away to add a strength-based adjustment.

Step 3 — League Averages: By default, Home avg = 1.50 and Away avg = 1.20 goals/match. Toggle Advanced if you want to override these for a specific league (e.g. EPL, Serie A).

Step 4 — Calculate: Hit ⚡ Calculate Predictions. Your most likely score, confidence meter, and all market probabilities will be generated across all tabs. 1st/2nd Half splits are derived automatically by the model — there's no separate half-time entry step.

Step 5 — EV Finder: Navigate to the EV Finder tab and enter bookmaker odds to instantly identify positive expected value (+EV) bets.

New Match: Press the ⊕ NEW button above the team statistics table to clear all fields — including Cup Mode and Neutral Ground — and start fresh. Adding a match to your list no longer clears the form automatically; this button is now the one place that does it.

Where To Get Your Team Stats

GoalMatrix doesn't pull live data — you feed it the numbers, which keeps it fast, offline-friendly, and usable for any league on earth. Here's where seasoned users pull theirs from.

Full Match Stats — Games Played, GF, GA (Combined, all matches)

GoalMatrix wants each team's full-season numbers: games played, goals scored, and goals conceded across all competition matches — home and away combined, not split by venue.

FBref.com — free, detailed squad & league stat pages for almost every top-tier league worldwide. The season-total row under "Squad Standard Stats" is exactly what you want.

Official league sites — e.g. premierleague.com/stats, laliga.com — the standings table's MP/GF/GA columns are already combined totals.

WhoScored.com & FlashScore.com — a team's season stat summary page gives combined totals directly, no filtering needed.

1st/2nd Half Splits — fully automatic now

There's no manual 1st-half entry anymore — half-time splits were inconsistent to source and often stale by kickoff. The model now estimates each side's FH/SH goal share itself from the match context it already has: total expected goals (higher-scoring games skew slightly more toward the 2nd half as they open up) and the strength gap between the two teams (bigger mismatches also skew later, as the game state changes). See "What about Half Time & 2nd Half?" in the FAQ for the exact mechanism.

Elo Ratings (Optional Modifier)

Eloratings.net covers international/national teams. For club football, ClubElo.com publishes a full daily-updated table for most European leagues — free to browse.

Power User Tips
Smart Fill

Only know Matches Played? Hit Smart Fill on the Inputs tab and GoalMatrix estimates GF/GA using the current league averages — handy for a quick gut-check calculation before you track down exact numbers.

Custom League Averages

Analyzing a league that's not in the built-in database? Open Manage Leagues on the Inputs tab and tap + Add League to save your own Home/Away goal averages — they'll persist and appear in the dropdown alongside the built-in leagues from then on.

Exporting & Sharing Results

Add a match to your Match List, then open History to export everything as a JPG Share Card (great for socials or a group chat), or as plain text / CSV if you just need the raw numbers.

Methodology & FAQ
What model does GoalMatrix use?
GoalMatrix uses an adaptive combination of two models:

Dixon-Coles (DC) — the foundation. Models each team's goals as an independent Poisson process, then applies a τ (tau) correction to the four low-score cells (0–0, 1–0, 0–1, 1–1) which plain Poisson systematically underestimates.

Bivariate Poisson — an extension that adds a covariance term ρ (rho) to model the positive correlation between both teams' scoring. Open, high-scoring games tend to produce goals for both sides — Bivariate Poisson captures this structural dependency that independent Poisson misses.

Both models are blended adaptively: ρ and τ are calibrated together using league GPG and matches played via getCorrelationParams(leagueGPG, minMP). The top-right badge always shows the live values.
What is Bivariate Poisson and why does it matter?
Standard Poisson assumes the two teams' goal tallies are independent — Arsenal scoring has no bearing on Chelsea's goals. In reality, open games where one team scores often allow the other to score too (high-scoring leagues, attacking teams, tactical contexts).

Bivariate Poisson adds a covariance parameter ρ (rho):
P(h,a) = Σk [ Poisson(k,λ₃) × Poisson(h−k,λ₁) × Poisson(a−k,λ₂) ]
where λ₃ = ρ√(λH·λA) captures shared scoring momentum.

Effect on outputs: Bivariate raises BTTS Yes probability slightly, raises scorelines like 2–2 and 3–2, and marginally lowers clean-sheet probabilities — all in the correct direction for open attacking matches.

When it activates: ρ scales in smoothly from game 1 using the league GPG context. High-scoring leagues (Bundesliga, Eredivisie) get a lower ρ base since goals are already baked into the lambdas; low-scoring leagues (Serie A) get a higher ρ base to capture their tighter score correlation patterns.
How are λ (expected goals) calculated?
Team inputs are combined season totals — each team's GF/GA/MP across all matches, home and away together, not filtered by venue. Attack Rating = Goals Scored/MP (Bayesian-shrunk toward the league's combined average, i.e. (lgH+lgA)/2). Defence Rating = Goals Conceded/MP (shrunk the same way). Both are then projected into home/away context by scaling with the ratio between the relevant league average (lgH or lgA) and that combined average — this projection step is where home-field advantage actually enters the model. λH = HomeAttack(home-projected) × AwayDefence(away-projected) ÷ lgH, λA = AwayAttack(away-projected) × HomeDefence(home-projected) ÷ lgA. Because the venue tilt now comes entirely from the league baselines rather than from each team's own split record, home-field asymmetry is captured once, cleanly, instead of being blended from two different sources.
What is the Dixon-Coles τ (tau) correction?
The τ correction adjusts the four low-score cells (0–0, 1–0, 0–1, 1–1) which independent Poisson models systematically underestimate. τ=0.13 is the default — a higher value gives more weight to low-scoring outcomes. τ is always active regardless of which model mode is running.
What is the Elo adjustment and where do I get Elo ratings?
Elo ratings measure team strength on a single numerical scale. The formula is:
eloFactor = 10^((HomeElo − AwayElo) / 2000)

Capped at ±20% effect on lambdas. The divisor is 2000, not the textbook Elo constant of 400 — that constant is calibrated for win-probability ratios, and applied directly as a goals multiplier it would saturate the ±20% cap by just ~30 rating points, making any real mismatch (100+ points) produce an identical effect regardless of how lopsided it actually is. 2000 keeps the response graduated across the range most matchups fall into: a 20-point gap gives roughly ×1.02, a 100-point gap roughly ×1.12 / ×0.89, and the ±20% cap is reached around a 200-point gap — which is now where genuinely extreme mismatches sit, rather than an ordinary one.

Sources: club-elo.com (European clubs) · eloratings.net (international) · FIFA Ranking · Leave blank to skip.
What is recency weighting, and how does it interact with the form multiplier?
Form Multiplier (6-game Pts + GF) is a two-component signal applied to each team's attack lambda:

PPGScore = tanh(pts/mp − 1.35) — "are results better than a 1.35 PPG average lately?"
GFScore = tanh(gf/mp − 1.35) — the same style of check, applied to recent goals scored per game rather than points. GF is optional: if it's left blank, only PPGScore drives the index.
FormIndex = 65% × PPGScore + 35% × GFScore
FormMult = 1 + FormIndex × 0.12 → range (0.88, 1.12)

Points is required to activate this at all — if Points is blank, the multiplier stays neutral (×1.00) regardless of what's in Matches Played or GF, so filling in just a games-played count for the "last 6" convenience default doesn't accidentally apply a penalty.

Defensive Form (separate channel) compares recent GA rate vs a season-and-league-blended baseline and is applied to the opponent's lambda — not the team's own attack. This keeps attack and defense form signals on completely separate inputs with zero shared data, and unlike attack form, it only needs GA + Matches Played — no Points required.

Blended baseline: the recent-form GA fields stay venue-agnostic (last N games regardless of home/away) by design, but comparing that blended recent number straight against a single flat league average would ignore each team's own actual defensive record. So the comparison baseline instead averages two things: that team's own combined-stats defence rating (already venue-projected — see "How are λ calculated?" above) and the league average for the venue it's being compared against — giving an apples-to-apples benchmark for the blended recent sample without needing separate venue-specific form data.

Sample-size confidence ramps — both signals scale up gradually: attack form reaches full weight at 6 games, defensive form at 8 games (it's noisier). A 2-game sample contributes ≈39% / ≈31% of face value respectively — consistent with the same pattern used for rho/tau calibration.

Combined cap — Elo and the attack FormMult are combined and clamped to ±20% of baseline first; the defensive multiplier from the opponent is then applied on top of that and re-clamped to the same ±20% band, so no single match's form, or a lopsided Elo gap, can swing a lambda beyond that ceiling.
What happened to Head-to-Head (H2H)?
The H2H adjustment has been removed. Its directional-bias and goal-pattern signals didn't hold up consistently enough across matches to justify the added complexity and input burden, so the model no longer applies any same-fixture H2H correction — predictions now rest entirely on the combined team stats, league home/away baselines, Elo, and form described elsewhere in this FAQ.
How does the attack/defence rating work now?
Team Season Stats (each team's MP/GF/GA across all matches, home and away combined) is the entire foundation — there's no separate home-only or away-only data entry anymore. Each team's combined goals-per-game rate is first shrunk toward the league's combined average with an 8-match Bayesian prior (so a 2-game sample doesn't swing wildly), then projected into home or away context by scaling with the ratio between the League Home/Away Average and the league's combined average. That projection step is where home-field advantage actually comes from — a team's raw stats stay venue-neutral, and the League Home/Away Averages under Advanced (or the 1.50/1.20 default) do the tilting.

Rating Confidence, shown under Team Season Stats, is the honest number to watch: combinedMP / (combinedMP + 8) per side — how far the rating has moved off a flat league-average default. At 0 games it's 0%; by ~8 games it's ~50%; by 16+ it's mostly your own data talking.

Elo and Recent Form are the only other adjustments layered on top of this base rating — both described elsewhere in this FAQ.

This replaces the older venue-split system entirely (separate home-only / away-only entry, plus a Last Season Data blend). Splitting by venue demanded more data entry for a home-advantage effect the league averages already capture more reliably at low sample sizes — the combined-stats approach reaches a stable rating faster with half the typing.
Why isn't there a Home-only / Away-only stats entry anymore?
Splitting a team's stats by venue sounds more precise, but early in a season it usually means estimating attack/defence from 3–5 home games and 3–5 away games separately — a noisy sample either way. Combined stats double the effective sample size immediately (all matches count), and home-field advantage is applied afterward via the League Home/Away Averages, which are themselves built from thousands of matches league-wide and are a far more stable source of that specific effect than any one team's small home/away split. Net effect: fewer fields to fill in, and a rating that stabilizes faster.
What is the Neutral Ground toggle?
When checked, the model removes the structural home advantage encoded in lgH vs lgA. It does this by scaling λH's baseline toward the midpoint of both league averages:

lgNeutral = (lgH + lgA) / 2
homeAdv = lgNeutral / lgH

For symmetric leagues (lgH = lgA), homeAdv = 1.0 — no change. For asymmetric leagues (lgH=1.50, lgA=1.20), homeAdv ≈ 0.90 — the home team's lambda is reduced by ~10%.

Since Team Season Stats are always combined (not venue-specific), this toggle is now the entire neutral-venue adjustment — there's no separate split to worry about undoing. Just check it and the League Home/Away Averages' pull is halved accordingly.

Use for: cup finals, playoff legs at neutral venues, international tournaments.
What is Cup Mode?
Cup Mode sets the calibration ceiling (calibMax) to a fixed 8 games instead of the league default — 30 games, or whatever value the selected league's Games/Season field derives. The idea: cup competitions don't give you a full domestic season's worth of matches to calibrate confidence against, so full calibration should arrive faster.

Auto-detection: selecting one of the built-in cup competitions from the League dropdown (UEFA Champions League, Europa League, Conference League, CONMEBOL Libertadores, CONCACAF Champions Cup, CAF Champions League, AFC Champions League, Copa do Nordeste) checks Cup Mode automatically. You can also check it manually for any other knockout competition.

Cup Mode always overrides — if checked, it takes priority over any Games/Season value entered or saved for that league, whether from the database or your own custom entry.
What statistical refinements does GoalMatrix use?
GoalMatrix applies six statistical refinements beyond the base Dixon-Coles model:

1. Bayesian Shrinkage — Attack and defence ratings are shrunk toward the league average using an 8-game prior. A team with 4 games and 12 goals is rated closer to 2.0 goals/game (not 3.0) — preventing extreme early-season overreaction.

2. League-average fallback — If inputs produce an invalid lambda, the model falls back to lgH/lgA (league average) rather than 0.5, giving a sensible neutral estimate.

3. Recent form multiplier — FormMult blends recent Points (65% weight) with recent Goals For (35% weight, only if entered) into a single tanh-based index, ramped in via a 6-game calibration window and capped at ×0.88–×1.12. Points drives it because it's the steadier signal — GF only refines it, never drives it alone. Leaving Points blank while filling in other Recent Form fields correctly leaves this multiplier neutral (×1.00) rather than applying a false penalty.

4. Recent defensive form — A separate multiplier, driven purely by recent Goals Against (no Points needed), ramped over an 8-game window and capped at ×0.92–×1.08. It's cross-applied to the opponent's lambda: a team that's been leaking goals lately boosts the other side's expected goals, and a team defending well suppresses it.

5. Calibration bands — Model calibration is classified as LOW (<50%), MEDIUM (50–80%), or HIGH (>80%) based on matches played, so users know when to trust the output.

6. Dynamic matrix size — The score matrix expands automatically for high-scoring teams: maxGoals = max(10, ceil(λH + λA + 5)), capturing more tail probability instead of clipping at a fixed ceiling.
How does the Adaptive Model work?
GoalMatrix uses a fully league-aware, sample-size-scaled calibration for both ρ (rho) and τ (tau) simultaneously — no hard thresholds or cliffs.

leagueGPG = lgH + lgA — the total goals per game context of the league. Higher GPG (Bundesliga, Eredivisie) → lower rho and tau base values, because open high-scoring leagues have less low-score clustering. Lower GPG (Serie A, Ligue 1) → higher base values.

Calibration curve — both parameters scale together from game 1 using: calibration = (min(homeMP, awayMP) / calibMax) ^ 0.85. calibMax now adapts per league: selecting a league with a verified season length (Games/Season field, under Advanced) sets calibMax to that number directly — MP is now each team's combined season total (home + away), so calibMax lines up with a full season rather than half of one. Leagues without a verified season length fall back to the standard default of 30 games (8 for Cup Mode, which always overrides). You can edit the Games/Season field manually for any league — including ones not yet in the database — and save it via "Save Values" so it's remembered next time you pick that league. Example: a 38-game season (20 teams) sets calibMax=38; a 46-game season (24 teams) sets calibMax=46. For a calibMax of 30: at 8 games calibration≈33%, at 15≈56%, at 20≈71%, at 25≈86%, at 30 games=100%. For cup matches (calibMax=8): at 2 games calibration≈31%, at 4≈55%, at 6≈78%, at 8 games=100%.

Why both parameters together? — A high-scoring league not only needs less bivariate covariance (ρ) but also less DC low-score correction (τ), because 0-0 and 1-0 results are genuinely rarer. Calibrating them independently would be inconsistent.

The live ρ, τ, and calibration % are always shown in the top-right badge and Results context bar after you calculate.
What are the default league averages?
Home = 1.50, Away = 1.20 goals/match. Toggle Advanced on the Inputs tab to enter custom league averages for your specific league.
How do I manage custom leagues?
Under Advanced, pick a Country and League to load its stored Home/Away averages (and Games/Season, if known). Edit the values and hit Save Values to store your own numbers for that league — this works both for overriding a built-in league and for leagues you've added yourself via + Add New League.

Games/Season is saved alongside Home/Away when present (4+ games) — this is what feeds the calibMax calculation described above, so a saved override affects both the goal-rate baseline and the calibration curve for that league going forward.

Custom leagues can be exported to a JSON file and re-imported later (or shared to another device/browser) via the Manage Leagues controls. A league with a saved override shows a "custom" tag next to its name; built-in leagues with an override can be reset back to the default via the reset button next to the dropdown.
Ideal Dixon-Coles τ (Tau)?
τ = 0.13 is recommended for multi-league use. Provides balanced correction for low-scoring scorelines without over-weighting them.
What about Half Time & 2nd Half?
There's no manual 1st-half input anymore — FH/SH is now fully estimated from the full-match prediction the model has already built, using two adjustments on top of a baseline share:

1. Baseline — starts from a 45% FH / 55% SH split of total expected goals (λH + λA), reflecting the general pattern that slightly more goals arrive in the second half across professional football (fatigue, substitutions, chasing the game).

2. Tempo adjustment — higher-scoring matches skew a bit further toward the 2nd half (games open up as they progress); lower-scoring matches sit closer to even. Scaled around a 2.5-total-goals pivot, capped at ±2%.

3. Mismatch adjustment — the bigger the gap between the two teams' expected goals, the more the split skews toward the 2nd half, since blowouts tend to open up as the game state changes (leading side eases off, trailing side commits forward). Scaled by the λ gap as a share of total λ.

4. Home/away tilt — a small fixed ±0.6% adjustment (home skews slightly earlier) is applied on top, reflecting a mild tendency for home sides to start on the front foot.

The combined share is clamped to a 40–47% range and applied separately to each side's full-match lambda to produce FH lambda; 2nd half lambda is the remainder. This is a heuristic based on match context, not a per-team measured split — the HT Score shown in Results is always labelled "(est.)" accordingly.
What is the EV Finder?
EV% = (Model Prob × Bookie Odds − 1) × 100. Positive EV = bookmaker offering above fair value. Margin-adjusted EV corrects for bookmaker overround — a more realistic measure of true edge.

The EV Finder covers 15 markets: 1X2 (Home/Draw/Away), Over/Under 1.5, Over/Under 2.5, Over/Under 3.5, BTTS Yes/No, plus 1st Half Over/Under 0.5 and 1st Half Over/Under 1.5. The 1st Half rows use the model's estimated FH/SH goal-timing split (see "What about Half Time & 2nd Half?" below) — there's no manual 1st-half entry, so these rows are always populated. Enter the bookmaker's decimal odds for any market to see EV instantly. Rows highlighted in blue indicate >3% edge; 🔥 badge indicates >7% edge.

The Combo Market in the probability bars shows BTTS Yes × Over 2.5 as a joint probability — a popular accumulator leg that isn't directly priced by most bookmakers but can be derived by multiplying the individual prices.
What do the EV row highlight colours mean?
After entering bookmaker odds in the EV Finder tab, rows are highlighted by edge strength:

No highlight — edge between 0–3%. Marginal value, within typical model variance.
Blue highlight — edge >3%. Meaningful value worth considering.
🔥 Strong badge — edge >7%. Strong value signal — the model sees a significant mispricing.

These thresholds are guides, not guarantees. Always consider sample size and context.
What do Match List, History and Calibration tracking do?
Match List (Bet Summary tab) logs each calculated prediction — score, best bet, calibration — when you hit "Add to Match List." It rolls over into History automatically at the start of a new day, archived by date.

Once you record a match's actual score in the list or in History, it's marked ✅ HIT or ❌ MISS against your best-bet pick, and the History modal shows day-by-day and all-time HIT/MISS totals.

Calibration (📊 button) tracks a running Brier score — lower is better — per market (1X2, Over/Under 2.5, BTTS) across all resolved matches with stored probabilities, comparing your most recent results against the all-time average to show whether calibration is trending better or worse. Use "Reset Calibration" after any model/formula change to start a clean baseline.

Bet-type Signal (shown on the Bet Summary tab once you have history) uses a Wilson lower-bound confidence interval on your own HIT/MISS record for each bet category (Home Win, Over 2.5, BTTS Yes, etc.) — requiring at least 5 resolved picks — to flag it 🟢 STRONG, 🟡 CAUTION, or 🔴 WEAK, so you can see which bet types have actually paid off for you historically, not just what the model currently favours.

Share Card exports your current Match List as a downloadable JPG summary image (via the Canvas API) — handy for sharing picks on socials or in a group chat. Plain-text and CSV export are also available for the raw data.
What is the Results context bar?
The thin bar at the top of the Results tab shows exactly which settings produced the current output — model mode (Pure DC or DC+Bivariate), τ and ρ values, and both teams' form adjustments. If you changed form or model inputs, it updates on the next Calculate press so you always know what generated the numbers you're looking at.
Disclaimer
GoalMatrix is a research and statistical tool. Predictions are probabilistic — not guarantees. Please bet responsibly. — by Victor Korir
📬 Contact the Developer
Questions about the model, licensing, or custom builds? Reach out directly:

✉️ kipvic@yahoo.com WhatsApp: (+254) 794 755 670 📞 (+254) 794 755 670
Reach Out
Victor Korir
GoalMatrix Developer