Odds Generation — soccer · goal · regular · φ/σ tilt
A comparison candidate to the default page. Steps 1–3 are identical — strip the margins, back-solve the goal rates (λₕ, λₐ) from the hard Handicap and Total anchors — but step 4 swaps the default's common-shock λ₃ for a soft multiplicative 1X2 tilt: draw cells scale by (1 + φ), home-win cells by e^σ, away-win cells by e^(−σ), then one renormalization. A damped Gauss–Newton fits (φ, σ), re-solving (λₕ, λₐ) after every trial so the Handicap and Total still hold exactly.
Where the default's single λ₃ compromises, the tilt has two independently-identified knobs — φ a direct draw lever, σ a genuine home:away lever — so it generically hits both 1X2 legs exactly, in either direction. The tilt is also the minimum-KL reshape of the score grid matching the quoted 1X2 masses: within each block (home / draw / away) the conditional score distribution is preserved, so Correct Score and Exact Total inherit their shape from the Poisson baseline rather than from an imposed profile. On ±0.5-class handicap lines the home leg is already pinned by the anchor; a rank check detects the collapse and defers to a φ-only draw solve at σ = 0.

Compare Poisson / soft 1X2 on the grid to see what φ and σ move.
See also the sibling diagonal-inflated BP candidate, which extends the default's common shock with a diagonal-inflation lever instead.
Each period — full match, 1st half, 2nd half — is its own inversion. Timing and cross-half markets (HT/FT, First Goal, …) are out of scope; see the Markets reference.
↑/↓ steps a field, Shift steps bigger; on a Malay pair the partner moves the opposite way. Handicap/Total boards show your line ±0.50 in quarter steps; team-total, 3-way and which-team lines are illustrative — probabilities are exact given λ.
Valid inputs: Malay in [−1, +1] and never 0, 1X2 decimals above 1, and each book must carry margin (implied probabilities summing over 1).
| A=0 | A=1 | A=2 | A=3 | A=4 | A=5+ | |
|---|---|---|---|---|---|---|
| H=0 | 6.90 | 7.35 | 3.91 | 1.39 | 0.37 | 0.10 |
| H=1 | 11.10 | 11.82 | 6.29 | 2.23 | 0.60 | 0.15 |
| H=2 | 8.93 | 9.51 | 5.06 | 1.80 | 0.48 | 0.12 |
| H=3 | 4.79 | 5.10 | 2.72 | 0.96 | 0.26 | 0.07 |
| H=4 | 1.93 | 2.05 | 1.09 | 0.39 | 0.10 | 0.03 |
| H=5+ | 0.83 | 0.89 | 0.47 | 0.17 | 0.04 | 0.01 |
| A=0 | A=1 | A=2 | A=3 | A=4 | A=5+ | |
|---|---|---|---|---|---|---|
| H=0 | 8.01 | 5.87 | 2.98 | 1.01 | 0.26 | 0.06 |
| H=1 | 10.10 | 14.22 | 5.21 | 1.77 | 0.45 | 0.11 |
| H=2 | 8.83 | 8.97 | 6.32 | 1.54 | 0.39 | 0.10 |
| H=3 | 5.14 | 5.23 | 2.66 | 1.25 | 0.23 | 0.06 |
| H=4 | 2.25 | 2.28 | 1.16 | 0.39 | 0.14 | 0.02 |
| H=5+ | 1.09 | 1.11 | 0.56 | 0.19 | 0.05 | 0.02 |
| HDP | H | A |
|---|---|---|
| -1.0 | -0.60 | +0.52 |
| -0.5/1 | -0.82 | +0.74 |
| -0.5 | +0.96 | +0.96 |
| -0/0.5 | +0.66 | -0.74 |
| 0.0 | +0.37 | -0.45 |
| Goal | Over | Under |
|---|---|---|
| 2.0 | +0.45 | -0.53 |
| 2/2.5 | +0.70 | -0.78 |
| 2.5 | +0.96 | +0.96 |
| 2.5/3 | -0.84 | +0.76 |
| 3.0 | -0.64 | +0.56 |
| Outcome | Odds |
|---|---|
| Home | 1.928 |
| Draw | 3.167 |
| Away | 4.641 |
How these numbers are computed
Each quote implies a probability summing past 1 per book (the margin); Power (two-way) and Shin (1X2, step 4) deflate them to the fair numbers the solver must reproduce.
| Home | Away | |
|---|---|---|
| Malay quote | +0.96 | +0.96 |
| Decimal | 1.9600 | 1.9600 |
| Fair | 0.5000 | 0.5000 |
| Fair decimal | 2.0000 | 2.0000 |
| Over | Under | |
|---|---|---|
| Malay quote | +0.95 | +0.95 |
| Decimal | 1.9500 | 1.9500 |
| Fair | 0.5000 | 0.5000 |
| Fair decimal | 2.0000 | 2.0000 |
| Home | Draw | Away | |
|---|---|---|---|
| Decimal quote | 1.8900 | 3.1300 | 4.7000 |
| Fair (Shin) | 0.5060 | 0.2995 | 0.1945 |
| Fair decimal | 1.9762 | 3.3389 | 5.1420 |
Try the strips standalone — Margin — two-way (Power) · Margin — multi-way (Shin): the same math on any quotes, with the bisection narrated.
Step 1 left two hard fair targets — Handicap and Total — for the scoring rates . The optional 1X2 is a soft shape target for φ and σ in step 4, not a third hard rate constraint. Model each side’s goals as Poisson — — and independent. Independent Poissons add — — so the match total depends only on : the Total quote pins the match size on its own, before caring who scores (step 3’s job). Settling any line sorts that one total’s mass — point masses — into three buckets: win (over hits), mass ; lose, mass ; push (an exact tie, stake refunded), mass — so . A refund is a no-action bet, so the fair price conditions on the decided outcomes alone: . That makes size a one-dimensional root-find, laid out below in the order a solver runs it — target, search, then the evaluation every iteration repeats:
1 - exp(-x)*(1 + x + x^2/2) = 0.50000000A .5 line cannot push (), so this is the plain tail — the Poisson Calculator inverse-solves in one field.
Where the pasted expression comes from
Totals are whole numbers, so total carries mass . Each win tail runs on forever, so flip it to the complement — times the start of cut at the line (keep every term and , the whole distribution). For the 2.50 line:
Substitute (with the denominator is 1) into and write as exp(-x) — that is the pasted line, term for term; the calculator solves it for .
The evaluation the search repeats every iteration is that settlement rule under Poisson(λ). At the converged it reproduces the win mass , push mass , and the fair check back to the target — the figures a re-implementation should match:
(Additivity is exact only for the plain independent-Poisson grid, so this λ is the Poisson stage’s; step 4’s φ/σ pull perturbs it, so that stage re-solves size and split jointly against the same hard targets — both recovered λ pairs land in the per-stage table, step 4.)
The Handicap decides who scores them — and settling it needs the full scoreline distribution, the score grid: independence makes each cell a plain product of the two Poisson masses,
— exactly the grid the score-grid panel’s Poisson stage displays. Hold fixed and slide the home share (with ). Home covers ⟺ , an exact is a push — step 2’s one rule again, with the masses now read off the grid: and (½-weighted across a quarter line’s two components), fair cover probability — which rises with , so the same solver shape applies:
P(0, 2.674060-x)*Ptail(1, x) + P(1, 2.674060-x)*Ptail(2, x) + P(2, 2.674060-x)*Ptail(3, x) + P(3, 2.674060-x)*Ptail(4, x) + P(4, 2.674060-x)*Ptail(5, x) + P(5, 2.674060-x)*Ptail(6, x) = 0.50000000A .5 line cannot push (): each line is one away score — its Poisson mass times the home tail that covers it. Its search lands on — within of the grid solve above (why not exact: the away-corner fold, explained below).
Where the pasted expression comes from
Step 2's Total was a sum of the two goal counts (one rate, one Ptail); the Handicap turns on their difference — the goal margin (home goals minus away goals). A margin depends on both rates at once — its distribution is a Skellam, the difference of two Poissons — so no single Ptail in can express it. The trick is to condition on the away score : once is pinned, only the home goals still vary, and the cover collapses to one plain home tail (). Home covers (a half-line cannot push), so each away score contributes its Poisson mass times that tail:
Now substitute the search variable (with ) so the whole cover is one function of :
Truncating the away sum at N = 5 — the grid’s size — gives the pasted equation. At the solved the 6 terms evaluate and add straight up to the target ():
Why the pasted is only almost exactly the from the grid solve (): the grid is mass-complete, so almost all of the old truncation gap is gone — the home tail folds into the row, so for every away score the grid reproduces the closed-form home tail above exactly. The one remaining sliver is the away corner: the grid folds the mass onto the column as a cumulative bucket, while this closed-form paste keeps there as an exact point mass — and the margin mis-scores that folded corner. That corner is , and it shrinks with the away rate. The figure below shows the fold on the home side — its tail lands in the 5+ bucket, so no mass is lost; the away side folds the same way.
At the converged split the grid masses and the fair check are:
The recovered pair is the Poisson stage’s chips in the grid panel — and with it both quotes are reproduced exactly. That closes the fit, but not the model: the two quotes pinned just two numbers, size and split, while step 5 prices whole ladders off the grid’s shape — and that shape rests entirely on the independence assumption. The next step softly pulls that shape toward the 1X2 quote with φ (draw) and σ (home/away), then re-solves so the quotes still hold (step 4).
The 1X2 is a three-way book, so Shin stripped it in step 1: with implied and overround , Shin’s insider fraction deflates each side to
(sqrt(x^2 + 4*(1-x)*0.529101^2/1.061355) - x)/(2*(1-x)) + (sqrt(x^2 + 4*(1-x)*0.319489^2/1.061355) - x)/(2*(1-x)) + (sqrt(x^2 + 4*(1-x)*0.212766^2/1.061355) - x)/(2*(1-x)) = 1The sum starts at when and falls monotonically, so the sign flip is unique — scan and the bisection lands back on . At the root each of the three terms is its fair leg — read straight off them.
giving the fair vector . It does not become three more hard equations: at a −0.50 Handicap, home cover is already exactly — the same event the 1X2 home leg prices — and two books rarely quote it identically, so pinning both would make them fight over one number. Instead the whole 1X2 becomes a soft target: two shape knobs pull the grid toward it, and the nested λ re-solve restores the Handicap and Total exactly on every trial — the hard anchors are never sacrificed.
φ moves the diagonal level (the draw); σ tilts only the win/loss halves, leaving the diagonal — and every ratio within one side — untouched. Both weights apply before one renormalization. A damped Gauss–Newton search minimizes the residual, re-solving inside every evaluation; the tiny σ ridge picks σ = 0 whenever the Handicap leaves no independent home/away direction. What the pull did:
| 1X2 leg | two-input grid | pulled | 1X2 target | Δ |
|---|---|---|---|---|
| Home | 0.5000 | 0.5000 | 0.5060 | -6.0e-3 |
| Draw | 0.2486 | 0.2995 | 0.2995 | -1.9e-10 |
| Away | 0.2514 | 0.2005 | 0.1945 | +6.0e-3 |
landed with — Δ home and Δ draw are the minimized residuals; Δ away follows from and stays a cross-check.
exp(2*x)*0.54555696/0.21876438 = 2.49381075then φ from the draw at that σ (off-diagonal constant ), interval :
(1 + x)*0.23567866 / ((1 + x)*0.23567866 + 0.76432134) = 0.29950363They land on and — the fit’s and to calculator tolerance. Away from ±0.50 the achieved legs are the 1X2 targets, so the step-1 numbers work directly; at ±0.50 use the achieved legs above — home:away sits at the Handicap-implied split, and the σ paste returns 0.
Where the pasted expressions come from
The weighting multiplies three disjoint mass blocks by three constants, then renormalizes. On a base grid with the pulled legs are
Divide any two legs and cancels: pins σ on its own (the σ paste), and with σ known the draw share rises monotonically in φ from 0 toward 1 — one root, the φ paste. Both even invert in closed form, no bisection strictly needed:
At σ = 0 the constant is and the φ paste collapses to the old draw-only one-constant form — the soft pull strictly generalizes the old draw calibration. As in steps 2–3, the λ re-solve is the piece a one-variable calculator can’t reproduce, so the frozen masses enter as constants.
Unroll the (φ, σ) search — rank check, then the draw bisection
The fit first probes both residual directions at φ = σ = 0 and measures the shape Jacobian’s normalized rank, < 10⁻⁸ — the σ direction is dead: this Handicap line already fixes the home leg once the draw is set, so σ pins at 0 and the one live knob, φ, is bisected onto the draw — exactly the pre-σ engine:
| i | lo | hi | φ | λₕ | λₐ | Δ home | Δ draw |
|---|---|---|---|---|---|---|---|
| 1 | 0.000000 | 1.000000 | 0.50000000 | 1.786825 | 1.001787 | -6.0e-3 | +1.2e-2 |
| 2 | 0.000000 | 0.500000 | 0.25000000 | 1.700845 | 1.033459 | -6.0e-3 | -1.6e-2 |
| 3 | 0.250000 | 0.500000 | 0.37500000 | 1.744537 | 1.017575 | -6.0e-3 | -1.3e-3 |
| 4 | 0.375000 | 0.500000 | 0.43750000 | 1.765852 | 1.009664 | -6.0e-3 | +5.6e-3 |
| 5 | 0.375000 | 0.437500 | 0.40625000 | 1.755238 | 1.013616 | -6.0e-3 | +2.2e-3 |
| 6 | 0.375000 | 0.406250 | 0.39062500 | 1.749899 | 1.015595 | -6.0e-3 | +4.5e-4 |
| 7 | 0.375000 | 0.390625 | 0.38281250 | 1.747221 | 1.016585 | -6.0e-3 | -4.3e-4 |
| 8 | 0.382813 | 0.390625 | 0.38671875 | 1.748560 | 1.016089 | -6.0e-3 | +1.3e-5 |
| 9 | 0.382813 | 0.386719 | 0.38476563 | 1.747891 | 1.016337 | -6.0e-3 | -2.1e-4 |
| 10 | 0.384766 | 0.386719 | 0.38574219 | 1.748226 | 1.016213 | -6.0e-3 | -9.7e-5 |
| 11 | 0.385742 | 0.386719 | 0.38623047 | 1.748393 | 1.016151 | -6.0e-3 | -4.2e-5 |
| 12 | 0.386230 | 0.386719 | 0.38647461 | 1.748477 | 1.016120 | -6.0e-3 | -1.4e-5 |
| 13 | 0.386475 | 0.386719 | 0.38659668 | 1.748519 | 1.016105 | -6.0e-3 | -6.4e-7 |
| 14 | 0.386597 | 0.386719 | 0.38665771 | 1.748539 | 1.016097 | -6.0e-3 | +6.2e-6 |
| 15 | 0.386597 | 0.386658 | 0.38662720 | 1.748529 | 1.016101 | -6.0e-3 | +2.8e-6 |
| 16 | 0.386597 | 0.386627 | 0.38661194 | 1.748524 | 1.016103 | -6.0e-3 | +1.1e-6 |
| 17 | 0.386597 | 0.386612 | 0.38660431 | 1.748521 | 1.016104 | -6.0e-3 | +2.2e-7 |
| 18 | 0.386597 | 0.386604 | 0.38660049 | 1.748520 | 1.016104 | -6.0e-3 | -2.1e-7 |
| 19 | 0.386600 | 0.386604 | 0.38660240 | 1.748520 | 1.016104 | -6.0e-3 | +8.2e-9 |
| 20 | 0.386600 | 0.386602 | 0.38660145 | 1.748520 | 1.016104 | -6.0e-3 | -9.9e-8 |
| 21 | 0.386601 | 0.386602 | 0.38660192 | 1.748520 | 1.016104 | -6.0e-3 | -4.5e-8 |
| 22 | 0.386602 | 0.386602 | 0.38660216 | 1.748520 | 1.016104 | -6.0e-3 | -1.9e-8 |
| 23 | 0.386602 | 0.386602 | 0.38660228 | 1.748520 | 1.016104 | -6.0e-3 | -5.2e-9 |
| 24 | 0.386602 | 0.386602 | 0.38660234 | 1.748520 | 1.016104 | -6.0e-3 | +1.5e-9 |
| 25 | 0.386602 | 0.386602 | 0.38660231 | 1.748520 | 1.016104 | -6.0e-3 | -1.8e-9 |
| 26 | 0.386602 | 0.386602 | 0.38660233 | 1.748520 | 1.016104 | -6.0e-3 | -1.9e-10 |
Bisection moves: Δ draw < 0 keeps the upper half (lo = mid), > 0 the lower; it stops at |Δ draw| < 1e-9. Δ home never moves down the rows — that is the deferral made visible: no φ can change it, and σ was ruled out by the rank check.
The per-stage table — the baseline and the pulled solve side by side:
| Stage | λₕ | λₐ | λₕ+λₐ | φ | σ | Δ cover | Δ over | Δ home | Δ draw | Δ away |
|---|---|---|---|---|---|---|---|---|---|---|
| Poisson | 1.6089 | 1.0651 | 2.6741 | — | — | 3.8e-9 | 7.1e-9 | — | — | — |
| 1X2 soft pull | 1.7485 | 1.0161 | 2.7646 | 0.3866 | 0.0000 | 3.2e-11 | 3.9e-11 | -6.0e-3 | -1.9e-10 | +6.0e-3 |
Hard-anchor gaps: Handicap 3.2e-11, Total 3.9e-11 — the pull never trades them. This run deferred: at a ±0.50-class line the rank check found no independent home/away direction, so σ = 0 and Δ home above is simply the two books’ disagreement over the same event — reported, not fought. To watch σ engage, quote the same match at a deeper line: set the Handicap to −1.00 at −0.59 / +0.51 and Δ home collapses to solver tolerance with σ ≈ 0.18.
Shape caveats carry over from the draw-only fit: one draw number fixes the diagonal’s level, while the 2-2/3-3/4-4 shape rides on the flat — pin it with correct-score quotes; the flat scaling acts only on even totals, nudging Odd/Even and Exact-Total. σ is likewise flat across each win/loss half, so ratios within a side (2-1 : 3-1) never change.
With λₕ, λₐ, φ, and σ fixed, the last stage’s grid (step 4) is fully determined — the score-grid panel above — and every market probability is just a sum of its matching cells. Each outcome is one grid cell J[h][a]; scores beyond the board cap (4-4 full match, 3-3 halves) fold into “AOS”.
| Outcome | Σ from grid | Fair | Priced dec |
|---|---|---|---|
| 0-0 | 0.0801 | 0.0801 | 12.047 |
| 0-1 | 0.0587 | 0.0587 | 16.364 |
| 0-2 | 0.0298 | 0.0298 | 31.690 |
| 0-3 | 0.0101 | 0.0101 | 88.126 |
| 0-4 | 0.0026 | 0.0026 | 283.163 |
| 1-0 | 0.1010 | 0.1010 | 9.578 |
| 1-1 | 0.1422 | 0.1422 | 6.818 |
| 1-2 | 0.0521 | 0.0521 | 18.382 |
| … 18 more | |||
Raw masses are normalized to Σ = 1, then inflated by Shin to overround 1 + 0.05 — the insider model run forward: with and , bisecting until (this run: ).
anchors tH = powerStrip(HCP pair) # hard fair P(home covers L) — step 1
tT = powerStrip(Total pair) # hard fair P(over T) — step 1
target (t1,tX,t2) = shinStrip(1X2) # soft fair 1X2 vector — step 4
for damped Gauss–Newton trial (φ, σ) # skip φ = σ = 0 with no 1X2
bisect λ_total ∈ [0.02, 8] # re-anchor size
bisect λₕ ∈ (0, λ_total) # re-anchor split; λₐ = λ_total − λₕ
J₀ = Poisson(λₕ, λₐ) on 0…N
J = normalize(J₀ × (1+φ) on h=a × e^σ on h>a × e^−σ on h<a)
until fairHcp(J, L) = tH # Handicap is never softened
until fairTot(J, T) = tT # Total is never softened
r = (P(h>a)−t1, P(h=a)−tX) # away follows from ΣJ = 1
minimize r·r + 1e−10 σ² # σ ridge defers a rank collisionThe grid panel’s stages run this same nest with the shape pull off/on — Poisson: φ = σ = 0, soft 1X2: the fitted φ/σ. The λ bisections remain monotone and retain their usual solver tolerances; the outer least-squares loop uses finite-difference shape directions, damping, and the small σ ridge. If the 1X2 home direction duplicates a ±0.50 Handicap, the measured shape Jacobian loses rank and the ridge chooses σ = 0 rather than weakening the anchor. This page folds the ≥5 tail into the N = 5 boundary (the H=5/A=5 cells mean “5 or more”), so every stage’s grid is mass-complete (Σ = 1), so the discrete grid reproduces the closed-form inversion instead of drifting from it by a truncated tail (steps 2–3). Each market group still renormalizes its own outcome masses to Σ = 1 before its margin. The executable reference for all of the above is docs/src/lib/odds/core.ts + markets.ts; the underlying math is held to the original simulator by the golden-master test in docs/src/lib/odds/__tests__/ (which exercises the default truncated grid — this page opts into the mass-complete capTail variant).