Turn Odds Into Probabilities in Python

Proportional, power and Shin margin removal in Python, tested on 2,660 Premier League matches. On average market odds, the method barely matters.

Algo Bet Editorial · · Data Pipelines · 3 min read

Betting odds are the strongest public benchmark for football forecasts, but they include a margin. Before you can compare a model with the market, you have to remove it. There are several methods, and the literature suggests the choice can matter. This tutorial implements three of them in Python and tests them on real data. The result is a little surprising.

It uses the test table and the brier function from Score Your Model With the Brier Score.

Method 1: proportional

Divide each implied probability by their sum:

import numpy as np

odds = test[["AvgH", "AvgD", "AvgA"]].to_numpy()
inv = 1 / odds
prop = inv / inv.sum(axis=1, keepdims=True)

Method 2: power

Find an exponent k so that the implied probabilities raised to k sum to 1. Bisection is enough:

def power(row):
    lo, hi = 1.0, 3.0
    for _ in range(60):
        k = (lo + hi) / 2
        if (row ** k).sum() > 1:
            lo = k
        else:
            hi = k
    return row ** k

Method 3: Shin

Shin's method assumes the bookmaker protects itself against informed bettors, which puts more margin on longshots. It solves for a parameter z:

def shin(row):
    S = row.sum()
    lo, hi = 0.0, 0.4
    for _ in range(60):
        z = (lo + hi) / 2
        p = (np.sqrt(z * z + 4 * (1 - z) * row * row / S) - z) / (2 * (1 - z))
        if p.sum() > 1:
            lo = z
        else:
            hi = z
    return p

pw = np.array([power(r) for r in inv])
sh = np.array([shin(r) for r in inv])

The test

We scored each method with the Brier score on the 2,660 Premier League matches from 2019-20 to 2025-26, using the average market odds in the data:

Method Brier score
Proportional 0.57447
Shin 0.57457
Power 0.57469

Our own results. The average overround in these odds was 4.46%. Lower Brier scores are better.

The three methods are practically identical: the differences appear in the fourth decimal place. On this data, the simplest method scored marginally best.

Why this differs from the research

Published research, such as Štrumbelj's 2014 study in the International Journal of Forecasting, has found that Shin's method produces more accurate probabilities than simple normalisation. There is no contradiction: the benefit of Shin and power depends on how much margin there is and how it is distributed. Our odds are averages across many bookmakers in the most liquid league in the world, with a low overround. When margins are small, every method gives nearly the same answer.

Key point: Methods matter most where margins are large and outcomes are lopsided: smaller leagues, longshots, single high-margin bookmakers. Test the choice on your own data rather than assuming.

Practical advice

  • Start with proportional removal; it is simple and, on liquid averaged odds, competitive.
  • Switch to Shin or power for single bookmakers or high-margin markets, and check whether it improves your scores.
  • Keep the method fixed once chosen, so comparisons over time stay valid.

Watch out: Margin-free probabilities are an estimate of the market's view, not the truth. They are a benchmark for your model, not a guarantee of anything.

To see the method in action on a single match, try the Poisson match predictor and compare its probabilities with margin-free odds.

  • Proportional, power and Shin margin removal take a few lines each in Python.
  • On 2,660 Premier League matches with averaged odds, all three scored almost identically.
  • Method choice matters more with large margins and lopsided markets; test it on your own data.

Sources

18+ only. Models do not guarantee results. See our Responsible Gambling page.