API

Here is the API documentation for the pybet package.

class pybet.market.Market

A betting market represented by a dictionary of runners and odds

Attributes:

places: The number of winning places in the market (default 1, i.e. win only).

Example:
>>> runners = ['Frankel', 'Sea The Stars', 'Nijinsky', 'Mill Reef', 'Quixall Crossett']
>>> odds = [Odds(x) for x in [2, 4, 5, 10, 1000]]
>>> market = Market(zip(runners, odds), places=2)
apply_margin(margin: Decimal) Market

Applies the specified margin to each runner’s underlying price, and thus to the overround. It is not applied cumulatively, i.e. a 10% margin applied to a market with a 105% overround, will become a 110% market, not 115%.

Parameters:

margin (Decimal) – The margin to apply to the market

Returns:

A revised market with the specified margin built in

Return type:

Market

Example:
>>> market = Market({'Frankel': Odds(3), 'Sea The Stars': Odds(3), 'Nijinsky': Odds(3)})
>>> market.apply_margin(20).get('Frankel')
Decimal('2.5')
derive(places: int, *, discounts: list[float] | None = None) Market

Derives a place market from a win market using the Harville formula (see https://en.wikipedia.org/wiki/Harville_formula) applying a specified discounted version of that formula if required

Parameters:
  • places (int) – The number of places to derive the market for

  • discounts (List[float], optional) – A list of discounts to apply to the probability of each horse in the market, defaults to None

Raises:
  • ValueError – If the number of places is invalid

  • ValueError – If the market is not a win market

Returns:

A revised market with the specified number of places

Return type:

Market

Example:
>>> market = Market({'Frankel': Odds(3), 'Sea The Stars': Odds(3), 'Nijinsky': Odds(3)})
>>> market.derive(2).get('Frankel')
Decimal('1.5')
equalise() Market

Resets a market so that all runners have equal odds with no overround

Returns:

A revised market with no margin built in

Return type:

Market

Example:
>>> market = Market({'Frankel': Odds(2.5), 'Sea The Stars': Odds(2.5), 'Nijinsky': Odds(2.5), 'Dancing Brave': Odds(2.5)})
>>> market.equalise().get('Frankel')
Decimal('4')
property favourites: list[Any]

Returns list of runners that are favourite for the event Note: Will be a list even if there is only one favourite

Returns:

A list of market favourites

Return type:

List[Any]

fill(margin: Decimal = Decimal('0')) Market

Fills out any missing odds in the market proportionately so that the specified margin is achieved

Parameters:

margin (Decimal, optional) – The margin to build into the market, defaults to zero

Raises:

ValueError – if there is already a larger margin built into the market

Returns:

A market with all missing odds filled in

Return type:

Market

Example:
>>> market = Market({'Frankel': Odds(4), 'Sea The Stars': Odds(4), 'Nijinsky': Odds(4), 'Dancing Brave': None})
>>> market.fill().get('Dancing Brave')
Decimal('4')
property is_fair: bool

Whether the market has no bias in favour of backer or layer

Returns:

True if there is no inbuilt margin, false otherwise

Return type:

bool

property is_overbroke: bool

Whether the market has no bias in favour of bettor or layer

Returns:

True if market as a whole in backer’s favour, false otherwise

Return type:

bool

property is_overround: bool

Whether the market is overround or not

Returns:

True if market as a whole in layer’s favour, false otherwise

Return type:

bool

meld(other: Market, other_percentage: float = 50) Market

Melds two markets together so that the odds for each runner are a weighted average of the two markets

Parameters:
  • other (Market) – The market to meld with

  • other_percentage (float, optional) – The percentage of the melded market that should be made up of the other market, defaults to 50

Raises:

ValueError – if the two markets do not have the same runners

Returns:

A market with the weighted average odds of the two markets

property overround_per_runner: Decimal

Excess market percentage divided by number of runners

Returns:

The overround per runner

Return type:

Decimal

property percentage: Decimal

The total market percentage of all runners

Returns:

The percentage market

Return type:

Decimal

places: int = 1
wipe() Market

Wipe market so that none of the runners have any odds

Returns:

An empty market

Return type:

Market

Example:
>>> market = Market({'Frankel': Odds(4), 'Sea The Stars': Odds(4), 'Nijinsky': Odds(4), 'Dancing Brave': Odds(4)})
>>> list(market.wipe().values())
[None, None, None, None]
without(runners: list[Any]) Market

Create a new market with the specified runners removed

Parameters:

runners (List[Any]) – Runners to remove from the market

Returns:

A new market without the specified runners

Return type:

Market

Example:
>>> market = Market({'Frankel': Odds(4), 'Sea The Stars': Odds(4), 'Nijinsky': Odds(4), 'Dancing Brave': Odds(4)})
>>> new_market = market.without(['Frankel'])
>>> list(new_market.keys())
['Sea The Stars', 'Nijinsky', 'Dancing Brave']
class pybet.odds.FractionalOddsSets

Constant lists of fractional odds for use in Odds instances to determine the proximate fractional odds to any particular value

STANDARD = ['1/1', '2/1', '3/1', '4/1', '5/1', '6/1', '7/1', '8/1', '9/1', '10/1', '12/1', '14/1', '16/1', '18/1', '20/1', '22/1', '25/1', '33/1', '40/1', '50/1', '66/1', '80/1', '100/1', '150/1', '200/1', '250/1', '500/1', '1000/1', '5/2', '7/2', '9/2', '11/2', '13/2', '15/2', '5/4', '9/4', '11/8', '13/8', '15/8', '10/3', '6/4', '11/10', '1/2', '1/3', '1/4', '1/5', '1/6', '1/7', '1/8', '1/9', '1/10', '1/12', '1/14', '1/16', '1/18', '1/20', '1/22', '1/25', '1/33', '1/40', '1/50', '1/66', '1/80', '1/100', '1/150', '1/200', '1/250', '1/500', '1/1000', '2/5', '2/7', '2/9', '2/11', '2/13', '2/15', '4/5', '4/9', '8/11', '8/13', '8/15', '3/10', '4/6', '10/11']
odds_against = ['1/1', '2/1', '3/1', '4/1', '5/1', '6/1', '7/1', '8/1', '9/1', '10/1', '12/1', '14/1', '16/1', '18/1', '20/1', '22/1', '25/1', '33/1', '40/1', '50/1', '66/1', '80/1', '100/1', '150/1', '200/1', '250/1', '500/1', '1000/1', '5/2', '7/2', '9/2', '11/2', '13/2', '15/2', '5/4', '9/4', '11/8', '13/8', '15/8', '10/3', '6/4', '11/10']
class pybet.odds.Odds(value='0', context=None)

A class that allows decimal odds to be created from and converted to a range of other odds formats

classmethod evens() Odds

Convenience constructor for creating an Odds value of evens

Returns:

An Odds instance equal to evens

Return type:

Odds

classmethod fractional(arg: Fraction) Odds
classmethod fractional(arg: str) Odds
classmethod fractional(arg1: int, arg2: int) Odds

Creates an Odds instance from fraction-like input, including typical odds strings like ‘9/4’, ‘9-4’, ‘9:4’

Returns:

An Odds instance equal to the value of the fraction passed in

Return type:

Odds

Example:
>>> Odds.fractional(Fraction(9, 4))
Decimal('3.25')
>>> Odds.fractional('9/4')
Decimal('3.25')
>>> Odds.fractional(9, 4)
Decimal('3.25')
classmethod inverted(value: Decimal) Odds

Creates an Odds instance that is the inverse of the input value, i.e. turns an odds on value into odds against and vice versa

Parameters:

value (Decimal) – A decimal representation of the odds to invert

Returns:

An odds instance representing the inverse of the value passed in

Return type:

Odds

Example:
>>> Odds.inverted(5)
Decimal('1.25')
property is_odds_against: bool

Whether the Odds instance is odds against

Returns:

True for odds greater than evens, false otherwise

Return type:

bool

Example:
>>> Odds(3).is_odds_against
True
>>> Odds(0.33).is_odds_against
False
property is_odds_on: bool

Whether the Odds instance is odds against

Returns:

True for odds less than evens, false otherwise

Return type:

bool

Example:
>>> Odds(0.33).is_odds_on
True
>>> Odds(3).is_odds_on
False
lengthen(percentage_points: Decimal) Decimal

Increases the chance represented by the current Odds instance by the specified number of percentage points and returns a new Odds instance with that value, i.e. “lengthening” the odds

Parameters:

percentage_points (Decimal) – Number of percentage points by which to increase the chance represented by the Odds

Returns:

A new Odds instance

Return type:

Decimal

Example:
>>> Odds(4).lengthen(5)
Decimal('5')
classmethod moneyline(value: str | int) Odds

Creates an Odds instance from an American moneyline value

Parameters:

value (Union[str, int]) – A representation of the moneyline value, e.g. -90

Raises:

ValueError – if the value is between the bounds of -100 and 100 and not suitable for moneyline values

Returns:

An odds instance representing the moneyline value passed in

Return type:

Odds

Example:
>>> Odds.moneyline(100)
Decimal('2.0')
>>> Odds.moneyline('-125')
Decimal('1.8')
classmethod percentage(value: Decimal) Odds

Creates an Odds instance from an equivalent percentage chance > 0 and < 100

Parameters:

value (Decimal) – A representation of the odds as a percentage

Raises:

ValueError – if the value is not between 0 and 100%

Returns:

An odds instance representing the percentage value passed in

Return type:

Odds

Example:
>>> Odds.percentage(40)
Decimal('2.5')
classmethod probability(value: Decimal) Odds

Creates an Odds instance from an equivalent probability > 0 and < 1

Parameters:

value (Decimal) – A representation of the odds as a probability

Raises:

ValueError – if the value is not between 0 and 1

Returns:

An odds instance representing the probability passed in

Return type:

Odds

Example:
>>> Odds.probability(0.4)
Decimal('2.5')
shorten(percentage_points: Decimal) Odds

Decreases the chance represented by the current Odds instance by the specified number of percentage points and returns a new Odds instance with that value, i.e. “shortening” the odds

Parameters:

percentage_points (Decimal) – Number of percentage points by which to decrease the chance represented by the Odds

Returns:

A new Odds instance

Return type:

Decimal

Example:
>>> Odds(5).shorten(5)
Decimal('4')
to_fractional(fractional_set: list[str], delim: str) str
to_fractional(fractional_set: list[Fraction], delim: str) str
to_fractional(fractional_set: list[tuple[int, int]], delim: str) str

Returns an Odds instance as a fractional string with the given delimiter (default ‘/’). The return value will be the closest equivalent value found in the given fractional_set.

Parameters:
  • fractional_set (List[str], optional) – A set of fractional odds to select from, defaults to standard UK fractionals

  • delim (str, optional) – A delimiter for the odds string, defaults to “/”

Raises:

ValueError – if the odds set provided is empty

Returns:

A string representation of the odds in fractional form

Return type:

str

Example:
>>> odds_set = ['3/1', '10/3', '7/2']
>>> Odds(4.27).to_fractional(odds_set)
'10/3'
>>> odds_set = ['3/1', '13/4', '10/3', '7/2']
>>> Odds(4.27).to_fractional(odds_set, '-')
'13-4'
to_moneyline() str

Returns an Odds instance as a string moneyline value

Returns:

An Odds instance in moneyline format

Return type:

str

Example:
>>> Odds.evens().to_moneyline()
'-100'
to_one() Decimal

Returns Odds instance as a value “to one”, i.e. like fractional odds, but the numerator can be a decimal

Returns:

The Odds instance adjusted to a “to one” value

Return type:

Decimal

Example:
>>> Odds(5).to_one()
Decimal('4')
to_percentage() Decimal

Returns an Odds instance as an equivalent percentage chance

Returns:

The Odds instance as a percentage

Return type:

Decimal

Example:
>>> Odds(5).to_percentage()
Decimal('20')
to_probability() Decimal

Returns an Odds instance as an equivalent probability

Returns:

The Odds instance as a probability

Return type:

Decimal

Example:
>>> Odds(5).to_probability()
Decimal('0.2')
class pybet.bets.Accumulator(stake: float | Decimal | str, bet_list: list[tuple[Odds | str, Callable[[...], bool], Callable[[...], bool] | None]], *, bog: bool = False)
class pybet.bets.Bet(stake: float | ~decimal.Decimal | str, odds: ~pybet.odds.Odds | ~typing.Literal['SP'], win_condition: ~typing.Callable[[...], bool], end_condition: ~typing.Callable[[...], bool] = <function Bet.<lambda>>, *, bog: bool = False)

A class to represent a bet.

Attributes:

stake: The stake of the bet. odds: The odds of the bet. win_condition: The callback that will determine whether the bet is currently a winner or a loser. end_condition: The callback that will determine whether the bet can be settled.

Example:
>>> bradford_city = {'position': 1}
>>> games_played = 45
>>> bradford_win_league = lambda: bradford_city['position'] == 1
>>> season_over = lambda: games_played == 46
>>> bet = Bet(2.00, Odds(21), bradford_win_league, season_over)
class Status(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

An enum to represent the status of a bet.

LOST = 2
OPEN = 0
VOID = 3
WON = 1
settle(*, sp: Odds | None = None, rf: int | Decimal = 0) Decimal

Returns the returns of the bet.

Returns:

The returns of the bet to 2 decimal places

Return type:

Decimal

Raises:

ValueError – If the bet is still open

Example:
>>> bet = Bet(2.00, Odds(21), bradford_win_league, season_over)
>>> bet.settle()
ValueError: Bet is still open
>>> games_played = 46
>>> bet.settle()
42.00
>>> bradford_city['position'] = 2
>>> bet.settle()
0
property status: Status

Returns the status of the bet.

Returns:

The status of the bet

Return type:

Status

Example:
>>> bet = Bet(2.00, Odds(21), bradford_win_league, season_over)
>>> bet.status
<Status.OPEN: 0>
>>> games_played = 46
<Status.WON: 1>
>>> bradford_city['position'] = 2
<Status.LOST: 2>
void() None

Voids the bet.

Returns:

None

class pybet.bets.Double(stake: float | Decimal | str, bet_list: list[tuple[Odds | str, Callable[[...], bool], Callable[[...], bool] | None]], *, bog: bool = False)
class pybet.bets.Treble(stake: float | Decimal | str, bet_list: list[tuple[Odds | str, Callable[[...], bool], Callable[[...], bool] | None]], *, bog: bool = False)
pybet.staking.kelly(true_odds: Odds, market_odds: Odds, bank: Decimal, percentage_commission: Decimal = Decimal('0')) Decimal

Calculates the stake that should be placed according to the Kelly Criterion [https://en.wikipedia.org/wiki/Kelly_criterion], i.e. edge over odds for any given true odds at any given market odds for any given bank size

Parameters:
  • true_odds (Odds) – The calculated true odds of the selection

  • market_odds (Odds) – The odds currently available in the market

  • bank (Decimal) – The bank available

  • percentage_commission (Decimal) – The percentage commission applied to winnings

Returns:

The stake to place according to the Kelly criterion

Return type:

Decimal

Example:
>>> kelly(Odds(4), Odds(5), 100)
Decimal('6.25')
>>> kelly(Odds(5), Odds(4), 100)
Decimal('0.00')