I asked for it to give me a poisson model for the match

1) Inputs & assumptions
Season-to-date scoring rates (after 12 games):

Norwich City: 12 scored (1.00 p/g), 18 conceded (1.50 p/g)
Hull City: 20 scored (1.67 p/g), 20 conceded (1.67 p/g)
These numbers are reported in current previews/data roundups ahead of this fixture. [squawka.com]

How we turn that into expected goals (λ) for a Poisson model

For each team, take the mean of its attack rate and the opponent’s concede rate.
Apply a modest home‑advantage multiplier: +5% to Norwich’s λ, –5% to Hull’s λ. (A small, conservative HA given Carrow Road form has been poor, but we’ll also run sensitivities.) Recent previews and odds still price Norwich marginally higher at home despite form, which is consistent with including some HA. [squawka.com], [cappertek.com]

Baseline λ values (calculated):

Norwich λ (goals) = ((1.00 + 1.67)/2) × 1.05 = 1.40
Hull λ (goals) = ((1.67 + 1.50)/2) × 0.95 ≈ 1.504
Total goals expectation: 2.904


2) Poisson outputs (baseline model)
From these λ’s, we compute the full scoreline distribution (0–7 each side) and derive 1X2, BTTS, and totals.
Results (baseline):

Win/Draw/Win: Norwich 35.3% | Draw 24.7% | Hull 39.9%
BTTS (Yes): 58.6%
Over 2.5 Goals: 55.5% (Under 44.5%)
Most likely scorelines:
1–1 (11.5%), 1–2 (8.7%), 0–1 (8.2%), 2–1 (8.1%), 1–0 (7.7%), 0–2 (6.2%)


Read: The data-only baseline ever so slightly prefers Hull (≈40%) over Norwich (≈35%), with a decent chance of goals and BTTS. That squares with form previews tipping a narrow Hull win, even if the ground H2H favors Norwich. [sportskeeda.com], [sportsmole.co.uk]


3) Sensitivity to home advantage
Let’s see what happens if we tweak the HA scaling:

HA = +10%/−10% → λ(NOR)=1.47, λ(HUL)=1.43 → Norwich 38.5% | Draw 24.8% | Hull 36.7%
HA = 0% → λ(NOR)=1.33, λ(HUL)=1.58 → Norwich 32.2% | Draw 24.5% | Hull 43.3%

Takeaway: Reasonable HA choices shift ~3–4 percentage points between the sides, but BTTS ~58% and Over 2.5 ~55–56% are very stable.

4) Market‑calibrated Poisson (optional)
Bookmakers currently price this closer to Norwich ~45% / Draw ~25% / Hull ~30% once you remove margin.
To reconcile the model with market priors (while preserving the same total goals ≈ 2.90), we can adjust λ’s to best match those 1X2 targets: [squawka.com], [cappertek.com]

Calibrated λ: Norwich 1.62, Hull 1.284 (Total still 2.904)
Outputs: Norwich 45.2% | Draw 24.4% | Hull 30.3%
BTTS: 58.0% | Over 2.5: 55.5%
Top scores: 1–1 (11.4%), 2–1 (9.2%), 1–0 (8.9%), 1–2 (7.3%), 2–0 (7.2%), 0–1 (7.0%)


This version lines up with the odds consensus (which leans Norwich at home), while still agreeing with goals markets that BTTS and Over 2.5 are slightly favored. [squawka.com], [cappertek.com]


5) The code I used
Python# Poisson model for Norwich vs Hullimport math# --- Inputs from current previews/data ---# Norwich: 12 GF, 18 GA in 12 games -> 1.00 GFpg, 1.50 GApg# Hull: 20 GF, 20 GA in 12 games -> 1.67 GFpg, 1.67 GApgnor_gf_pg, nor_ga_pg = 1.00, 1.50hul_gf_pg, hul_ga_pg = 1.67, 1.67# --- Baseline lambdas with modest home advantage (+5% / -5%) ---home_adv = 0.05nor_lambda = ((nor_gf_pg + hul_ga_pg)/2) * (1 + home_adv) # 1.40hul_lambda = ((hul_gf_pg + nor_ga_pg)/2) * (1 - home_adv) # ~1.504def poisson_summary(nor_lam, hul_lam, max_goals=7): Pn = [math.exp(-nor_lam)*nor_lam**k/math.factorial(k) for k in range(max_goals+1)] Ph = [math.exp(-hul_lam)*hul_lam**k/math.factorial(k) for k in range(max_goals+1)] P_home = P_draw = P_away = 0.0 P_BTTS = P_O25 = 0.0 score_probs = {} for i in range(max_goals+1): for j in range(max_goals+1): p = Pn[i]*Ph[j] score_probs[(i,j)] = p if i > j: P_home += p elif i == j: P_draw += p else: P_away += p if i > 0 and j > 0: P_BTTS += p if i + j >= 3: P_O25 += p top = sorted(score_probs.items(), key=lambda kv: kv[1], reverse=True)[:6] pct = lambda x: round(100*x,1) return { 'lambdas': (round(nor_lam,3), round(hul_lam,3), round(nor_lam+hul_lam,3)), '1X2_%': (pct(P_home), pct(P_draw), pct(P_away)), 'BTTS_Yes_%': pct(P_BTTS), 'Over_2.5_%': pct(P_O25), 'Under_2.5_%': pct(1-P_O25), 'Top_Scores_%': [(f'{a}-{b}', pct(p)) for (a,b), p in top] }baseline = poisson_summary(nor_lambda, hul_lambda)# --- Market-calibrated variant ---# Target 1X2 ≈ (0.45, 0.25, 0.30), keep total goals ~ 2.904target = (0.45, 0.25, 0.30)G_total = nor_lambda + hul_lambda # 2.904...def outcomes(n_lam, h_lam, max_goals=7): Pn = [math.exp(-n_lam)*n_lam**k/math.factorial(k) for k in range(max_goals+1)] Ph = [math.exp(-h_lam)*h_lam**k/math.factorial(k) for k in range(max_goals+1)] P_home = P_draw = P_away = 0.0 for i in range(max_goals+1): for j in range(max_goals+1): p = Pn[i]*Ph[j] if i > j: P_home += p elif i == j: P_draw += p else: P_away += p return P_home, P_draw, P_awaybest, best_params = None, Nonefor n_lam in [x/100 for x in range(100, 201)]: # search Norwich λ from 1.00 to 2.00 h_lam = max(0.2, G_total - n_lam) ph, pd, pa = outcomes(n_lam, h_lam) err = (ph-target[0])**2 + (pd-target[1])**2 + (pa-target[2])**2 if best is None or err < best: best, best_params = err, (n_lam, h_lam)calib = poisson_summary(best_params[0], best_params[1])print('Baseline:', baseline)print('Calibrated:', calib)Show more lines

6) What this means (quick read)

Baseline (data-only) slightly prefers Hull (≈40%) vs Norwich (≈35%).
Market-calibrated (aligning to odds) flips that to Norwich ≈45% and Hull ≈30%.
Either way: BTTS ≈58% and Over 2.5 ≈55–56% look like sensible leans given both teams’ season scoring profiles and recent trend pieces highlighting goals at both ends.

Posted By: SimonOTBC on October 31st 2025 at 10:21:08


Message Thread


Reply to Message

In order to add a post to the WotB Message Board you must be a registered WotB user.

If you are not yet registered then please visit the registration page. You should ensure that their browser is setup to accept cookies.

Log in