footix.implied_odds package

Submodules

footix.implied_odds.implied module

footix.implied_odds.implied.multiplicative_method(odds, axis=-1)[source]

Multiplicative way to normalize the odds. Work for multidimensionnal array.

Parameters:
  • odds (list or np.array) – list of odds

  • axis (int) – axis where compute the probabilities

Return type:

tuple[ndarray, float | ndarray]

footix.implied_odds.implied.power_method(odds, *, max_iter=50, tol=1e-06)[source]

Compute implied probabilities using the power–margin method.

This function takes a collection of decimal (European) odds and returns a vector of implied probabilities that sum to one, while also computing the bookmaker’s margin. The power–margin approach raises each inverse-odds entry to a common exponent (k) that exactly normalizes them. Numerically, we solve for k via a Newton iteration in log-space.

Parameters

oddsArrayLike

A one-dimensional array-like of positive decimal odds. Each entry must be strictly greater than zero.

tolfloat, default=1e-12

Convergence tolerance for the root-finding procedure. The iteration stops when abs(sum((1/odds)**k) - 1) < tol.

max_iterint, default=50

Maximum number of Newton steps to attempt. If convergence is not reached within this many iterations, a RuntimeError is raised.

Returns

probsnp.ndarray

A 1-D array of implied probabilities corresponding to each input odd. These probabilities are non-negative and sum exactly (to machine precision) to 1.0.

marginfloat
The bookmaker’s over-round (or “vigorish”), computed as sum(1/odds) - 1.

A value of zero indicates a fair book (no margin).

Raises

ValueError

If odds is not a one-dimensional array-like, or if any entry in odds is ≤ 0.

RuntimeError

If the Newton root-finder fails to converge within max_iter iterations.

Notes

  1. When margin is already within tol of zero, the function treats the book as fair and

    returns the normalized inverses of the odds directly.

  2. Internally, we solve f(k) = sum((1/odds_i)**k) - 1 = 0 by applying Newton’s method

to the equivalent form f(k) = sum(exp(k * log(1/odds_i))) - 1.

Working in log-space improves numerical stability, especially when odds are large (inv-odds small).

  1. The default initial guess for k is 1. For typical sportsbook margins (up to 10–15%),

    convergence is very fast—often under 5 iterations.

Examples

>>> odds = [1.80, 2.10, 4.00]
>>> probs, margin = implied_probs_power(odds)
>>> np.isclose(probs.sum(), 1.0)
True
>>> margin  # e.g., around 0.043 (4.3% over-round)
0.043
Parameters:
Return type:

tuple[ndarray, float]

footix.implied_odds.implied.shin_method(odds, *, tol=1e-12)[source]

Compute implied probabilities and bookmaker margin using Shin’s method.

Shin’s method (Shin, 1992; Shin, 1993) adjusts raw decimal odds for insider information risk by finding a parameter z in (0, 1) that forces the “Shin adjusted” probabilities to sum to 1. This implementation uses Brent’s root finding algorithm to solve for z.

Parameters

oddsarraylike of float, shape (3,)

Decimal odds for the three mutually exclusive outcomes, in the order: [home_win, draw, away_win]. Each entry must be strictly positive.

tolfloat, optional

Absolute tolerance for the Brent solver when finding the Shin parameter z. Default is 1e-12.

Returns

impliedndarray, shape (3,)

Shin adjusted probabilities for [home_win, draw, away_win]. These probabilities account for bookmaker overround and the presence of insider information, and they sum to 1 within numerical tolerance.

marginfloat
Bookmaker overround (also called “vig” or “juice”), computed as

margin = sum(1 / odds_i) - 1.

Raises

ValueError

If odds does not have exactly three elements or if any element is non‐positive.

Parameters:
Return type:

tuple[ndarray, float]

Module contents

Implied odds computation from predicted probabilities.

This module provides methods to convert predicted probabilities into betting odds and market-consistent prices using various normalization techniques.

Exported functions:
  • multiplicative_method: Multiplicative odds normalization

  • power_method: Power-based odds normalization

  • shin_method: Shin’s method for market-consistent odds

footix.implied_odds.multiplicative_method(odds, axis=-1)[source]

Multiplicative way to normalize the odds. Work for multidimensionnal array.

Parameters:
  • odds (list or np.array) – list of odds

  • axis (int) – axis where compute the probabilities

Return type:

tuple[ndarray, float | ndarray]

footix.implied_odds.power_method(odds, *, max_iter=50, tol=1e-06)[source]

Compute implied probabilities using the power–margin method.

This function takes a collection of decimal (European) odds and returns a vector of implied probabilities that sum to one, while also computing the bookmaker’s margin. The power–margin approach raises each inverse-odds entry to a common exponent (k) that exactly normalizes them. Numerically, we solve for k via a Newton iteration in log-space.

Parameters

oddsArrayLike

A one-dimensional array-like of positive decimal odds. Each entry must be strictly greater than zero.

tolfloat, default=1e-12

Convergence tolerance for the root-finding procedure. The iteration stops when abs(sum((1/odds)**k) - 1) < tol.

max_iterint, default=50

Maximum number of Newton steps to attempt. If convergence is not reached within this many iterations, a RuntimeError is raised.

Returns

probsnp.ndarray

A 1-D array of implied probabilities corresponding to each input odd. These probabilities are non-negative and sum exactly (to machine precision) to 1.0.

marginfloat
The bookmaker’s over-round (or “vigorish”), computed as sum(1/odds) - 1.

A value of zero indicates a fair book (no margin).

Raises

ValueError

If odds is not a one-dimensional array-like, or if any entry in odds is ≤ 0.

RuntimeError

If the Newton root-finder fails to converge within max_iter iterations.

Notes

  1. When margin is already within tol of zero, the function treats the book as fair and

    returns the normalized inverses of the odds directly.

  2. Internally, we solve f(k) = sum((1/odds_i)**k) - 1 = 0 by applying Newton’s method

to the equivalent form f(k) = sum(exp(k * log(1/odds_i))) - 1.

Working in log-space improves numerical stability, especially when odds are large (inv-odds small).

  1. The default initial guess for k is 1. For typical sportsbook margins (up to 10–15%),

    convergence is very fast—often under 5 iterations.

Examples

>>> odds = [1.80, 2.10, 4.00]
>>> probs, margin = implied_probs_power(odds)
>>> np.isclose(probs.sum(), 1.0)
True
>>> margin  # e.g., around 0.043 (4.3% over-round)
0.043
Parameters:
Return type:

tuple[ndarray, float]

footix.implied_odds.shin_method(odds, *, tol=1e-12)[source]

Compute implied probabilities and bookmaker margin using Shin’s method.

Shin’s method (Shin, 1992; Shin, 1993) adjusts raw decimal odds for insider information risk by finding a parameter z in (0, 1) that forces the “Shin adjusted” probabilities to sum to 1. This implementation uses Brent’s root finding algorithm to solve for z.

Parameters

oddsarraylike of float, shape (3,)

Decimal odds for the three mutually exclusive outcomes, in the order: [home_win, draw, away_win]. Each entry must be strictly positive.

tolfloat, optional

Absolute tolerance for the Brent solver when finding the Shin parameter z. Default is 1e-12.

Returns

impliedndarray, shape (3,)

Shin adjusted probabilities for [home_win, draw, away_win]. These probabilities account for bookmaker overround and the presence of insider information, and they sum to 1 within numerical tolerance.

marginfloat
Bookmaker overround (also called “vig” or “juice”), computed as

margin = sum(1 / odds_i) - 1.

Raises

ValueError

If odds does not have exactly three elements or if any element is non‐positive.

Parameters:
Return type:

tuple[ndarray, float]