Home row: count only that team's home fixtures. Away row: count only that team's away fixtures. Use last 6–12 games (venue-specific) for best results. More games = higher model confidence.
Goals scored in that team's venue-specific matches only (home team → goals scored at home; away team → goals scored away) across the MP window. Used to estimate the team's attack rating relative to the matching league average.
Goals conceded in that team's venue-specific matches only (home team → conceded at home; away team → conceded away) across the MP window. Used to estimate the team's defence rating. Lower = stronger defence.
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) / 400), capped ±20% on λ. 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.
| Team | MP | GF | GA | PTS | Form |
|---|---|---|---|---|---|
| HOME |
—
|
||||
| AWAY |
—
|
Enter team data on the Inputs tab and press Calculate.
Enter team data on the Inputs tab and press Calculate.
Calculate predictions first, then enter bookmaker odds to find value bets.
Step 1 — Full Match Stats: Enter both team names, then the venue-specific record for each: for the Home team, its games played, goals scored and goals conceded at home only (last 6–12 home games recommended); for the Away team, the same three numbers from its away matches only.
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 subtle ⊕ NEW button above the team statistics table to clear all fields and start fresh.
ScoreMatrix 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.
ScoreMatrix now wants venue-specific numbers: the Home team's record from its home fixtures only, and the Away team's record from its away fixtures only — not season-wide totals.
FBref.com — free, detailed squad & league stat pages for almost every top-tier league worldwide. Look for the "Home/Away" split table under "Squad Standard Stats".
Official league sites — e.g. premierleague.com/stats, laliga.com — many let you filter the standings/stats table by Home or Away.
WhoScored.com & FlashScore.com — filter a team's fixture list by venue, then manually tally the last 6–10 home (or away) games.
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.
Eloratings.net covers international/national teams. For club football, ClubElo.com publishes a full daily-updated table for most European leagues — free to browse.
Only know Matches Played? Hit Smart Fill on the Inputs tab and ScoreMatrix estimates GF/GA using the current league averages — handy for a quick gut-check calculation before you track down exact numbers.
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.
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.
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.
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.
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.
PPGScore = tanh(pts/mp − 1.35) — "are results better than a 1.35 PPG average lately?"
GFScore = tanh((recentGFRate − seasonGFRate) / seasonGFRate) — "are they scoring more than their season baseline?"
FormIndex = 65% × PPGScore + 35% × GFScore
FormMult = 1 + FormIndex × 0.12 → range (0.88, 1.12)
Defensive Form (separate channel) compares recent GA rate vs a season GA 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.
Venue-blended baseline (v4.0): the recent-form GA fields stay venue-agnostic (last N games regardless of home/away) by design, but the main season stats are now home/away-split. Comparing a blended recent number straight against a one-sided split baseline would be misleading — a home team's home-only baseline is naturally lower than its true average, an away team's away-only baseline naturally higher — so the comparison instead uses the average of that team's own split baseline and the league average for the venue it's missing, giving an apples-to-apples benchmark for the blended recent sample.
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 ~33% / 25% of face value respectively — consistent with the same pattern used for rho/tau calibration.
Combined cap — the attack FormMult and defensive multiplier are combined, then hard-clamped to ±20% of baseline (ADJ_CAP), so no single match's form can swing a lambda more than 20%.
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%.
Important with v4.0's home/away-split inputs: this toggle only cancels the home advantage baked into the league averages. It cannot remove home-turf bias already baked into the team stats themselves — since the Home/Away boxes now expect venue-specific splits, a "home" team's numbers already reflect its actual home-turf performance. For a genuinely neutral-venue match, enter each team's combined season stats (not filtered by venue) instead of a split — a banner will remind you of this when the toggle is checked.
Use for: cup finals, playoff legs at neutral venues, international tournaments.
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.
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. Decoupled form multiplier (v3) — FormMult is driven by L5 points only (range ×0.85–×1.15), keeping it structurally independent from the L5 GF/GA used in recency weighting. This eliminates double-counting of recent scoring. GD context is shown in the form index label but does not affect the multiplier.
4. Confidence bands — Model confidence is classified as LOW (<50%), MEDIUM (50–80%), or HIGH (>80%) based on matches played, so users know when to trust the output.
5. 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.
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.
Confidence curve — both parameters scale together from game 1 using: confidence = (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 roughly half that number — a team's typical home (or away) fixture count for the season, since v4.0's inputs are venue-split. Leagues without a verified season length fall back to the standard default of 15 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≈19; a 46-game season (24 teams) sets calibMax≈23. For a calibMax of 15: at 4 games confidence≈33%, at 6≈46%, at 8≈59%, at 10≈71%, at 12≈83%, at 15 games=100%. For cup matches (calibMax=8): at 2 games confidence≈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 confidence % are always shown in the top-right badge and Results context bar after you calculate.
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 confidence 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.
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.
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.
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.
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.
✉️ kipvic@yahoo.com WhatsApp: (+254) 794 755 670 📞 (+254) 794 755 670