Simulators

Simulators are classes that take in a bankroll and a strategy and apply that strategy to a situation. They can be used to evaluate the efficacy of strategies in certain domains.

Repeated Binary Simulator

class keeks.simulators.repeated_binary.RepeatedBinarySimulator(payoff: float, loss: float, fee_per_bet: float, probability: float, trials: int = 1000, seed: int | None = None)[source]

Bases: object

Simulator for binary betting strategies with a fixed probability.

This simulator uses the same probability for each trial, simulating repeated bets on events with identical odds.

Parameters:
  • payoff (float) – The amount won per unit bet on a successful outcome.

  • loss (float) – The amount lost per unit bet on an unsuccessful outcome.

  • fee_per_bet (float) – The flat fee charged once per settled bet, regardless of outcome. This is an absolute bankroll amount, not a fraction of the stake, so it does not scale with bet size: it is subtracted from a winning settlement and added to a losing one. Note this differs in unit from the singular transaction_cost_rate taken by strategies in keeks.binary_strategies, which is a per-unit fraction of the bet used for sizing.

  • probability (float) – The fixed probability of a successful outcome for all trials.

  • trials (int, default=1000) – The number of betting trials to simulate.

  • seed (int or None, default=None) – Seed for a private outcome generator. When omitted, the process-global random generator is used for backward compatibility.

Raises:

ValueError – If payoff is not finite and positive, if loss or fee_per_bet is not finite and nonnegative, if probability is not finite within [0, 1], or if trials is not a nonnegative integer, or if seed is not a nonnegative integer or None.

Notes

RNG family and seeding. All outcome draws come from Python’s random.Random - this is the one simulator in the package on the stdlib generator family; the multi-outcome and allocation simulators draw from private numpy numpy.random.Generator instances on spawned SeedSequence children, so cross-generation seeded comparisons are not aligned by seed alone. With a seed the outcome generator is private and a seeded run replays byte-identically; without one, the process-global random generator drives the draws.

evaluate_strategy(strategy: BaseStrategy, bankroll: BankRoll) → None[source]

Evaluate a betting strategy over multiple trials with fixed probability.

For each trial, the strategy is evaluated with the fixed probability, and the bankroll is updated based on the outcome. The simulation stops early if the bankroll is depleted (bankruptcy).

Parameters:
  • strategy (BaseStrategy) – The betting strategy to evaluate.

  • bankroll (BankRoll) – The bankroll to use for the simulation.

Returns:

The bankroll object is updated in-place with the results of the simulation.

Return type:

None

Raises:

ValueError – If strategy is a BaseStrategy whose payoff or loss differs from this simulator’s, since it would then size bets against different odds than the ones the simulator settles at, or if the strategy returns a non-finite or out-of-range stake fraction.

Random Binary Simulator

class keeks.simulators.random_binary.RandomBinarySimulator(payoff: float, loss: float, fee_per_bet: float, trials: int = 1000, stdev: float = 0.1, seed: int | None = None)[source]

Bases: object

Simulator for binary betting strategies with random probabilities.

This simulator generates random probabilities for each trial, centered around 0.5 with a configurable standard deviation. It evaluates a betting strategy against these random probabilities and updates the bankroll accordingly.

Parameters:
  • payoff (float) – The amount won per unit bet on a successful outcome.

  • loss (float) – The amount lost per unit bet on an unsuccessful outcome.

  • fee_per_bet (float) – The flat fee charged once per settled bet, regardless of outcome. This is an absolute bankroll amount, not a fraction of the stake, so it does not scale with bet size: it is subtracted from a winning settlement and added to a losing one. Note this differs in unit from the singular transaction_cost_rate taken by strategies in keeks.binary_strategies, which is a per-unit fraction of the bet used for sizing.

  • trials (int, default=1000) – The number of betting trials to simulate.

  • stdev (float, default=0.1) – The standard deviation of the normal distribution used to generate probabilities. Samples are clamped to [0.0, 1.0].

  • seed (int or None, default=None) – Seed for private outcome and probability generators. When omitted, the process-global random and numpy.random generators are used for backward compatibility.

Raises:

ValueError – If payoff is not finite and positive, if loss, fee_per_bet or stdev is not finite and nonnegative, or if trials is not a nonnegative integer, or if seed is not a nonnegative integer or None.

Notes

RNG family and seeding. This simulator mixes two generator families: bet outcomes draw from Python’s random.Random and win probabilities from a numpy numpy.random.Generator (default_rng). With a seed, both generators are private instances driven by that one integer and a seeded run replays byte-identically; without one, both fall back to the process-global generators (random.random and numpy.random.normal). Cross-family seeded comparisons with the multi-outcome and allocation simulators, which draw from spawned SeedSequence children only, are not aligned by seed alone - see the reproducibility contracts there.

evaluate_strategy(strategy: BaseStrategy, bankroll: BankRoll) → None[source]

Evaluate a betting strategy over multiple trials.

For each trial, a random probability is generated, the strategy is evaluated with this probability, and the bankroll is updated based on the outcome. The simulation stops early if the bankroll is depleted (bankruptcy).

Parameters:
  • strategy (BaseStrategy) – The betting strategy to evaluate.

  • bankroll (BankRoll) – The bankroll to use for the simulation.

Returns:

The bankroll object is updated in-place with the results of the simulation.

Return type:

None

Raises:

ValueError – If strategy is a BaseStrategy whose payoff or loss differs from this simulator’s, since it would then size bets against different odds than the ones the simulator settles at, or if the strategy returns a non-finite or out-of-range stake fraction.

Random Uncertain Binary Simulator

class keeks.simulators.random_uncertain_binary.RandomUncertainBinarySimulator(payoff: float, loss: float, fee_per_bet: float, trials: int = 1000, stdev: float = 0.1, uncertainty_stdev: float = 0.05, seed: int | None = None)[source]

Bases: object

Simulator for binary betting strategies with random probabilities and uncertainty.

This simulator generates random probabilities for each trial, centered around 0.5 with a configurable standard deviation. It adds an additional uncertainty factor to the actual outcome probability, simulating imperfect information.

Parameters:
  • payoff (float) – The amount won per unit bet on a successful outcome.

  • loss (float) – The amount lost per unit bet on an unsuccessful outcome.

  • fee_per_bet (float) – The flat fee charged once per settled bet, regardless of outcome. This is an absolute bankroll amount, not a fraction of the stake, so it does not scale with bet size: it is subtracted from a winning settlement and added to a losing one. Note this differs in unit from the singular transaction_cost_rate taken by strategies in keeks.binary_strategies, which is a per-unit fraction of the bet used for sizing.

  • trials (int, default=1000) – The number of betting trials to simulate.

  • stdev (float, default=0.1) – The standard deviation of the normal distribution used to generate probabilities. Samples are clamped to [0.0, 1.0].

  • uncertainty_stdev (float, default=0.05) – The standard deviation of the normal distribution used to add uncertainty to the actual outcome probability. The resulting outcome probability is clamped to [0.0, 1.0].

  • seed (int or None, default=None) – Seed for private outcome, probability, and uncertainty generators. When omitted, the process-global random and numpy.random generators are used for backward compatibility.

Raises:

ValueError – If payoff is not finite and positive, if loss, fee_per_bet, stdev or uncertainty_stdev is not finite and nonnegative, if trials is not a nonnegative integer, or if seed is not a nonnegative integer or None.

Notes

RNG family and seeding. Like RandomBinarySimulator, this simulator mixes two generator families: bet outcomes draw from Python’s random.Random and both the win probabilities and the uncertainty adjustments from one numpy numpy.random.Generator (default_rng). With a seed, all generators are private instances driven by that one integer and a seeded run replays byte-identically; without one, every draw falls back to the process-global generators. Cross-family seeded comparisons with the multi-outcome and allocation simulators, which draw from spawned SeedSequence children only, are not aligned by seed alone - see the reproducibility contracts there.

evaluate_strategy(strategy: BaseStrategy, bankroll: BankRoll) → None[source]

Evaluate a betting strategy over multiple trials with uncertainty.

For each trial, a random probability is generated, the strategy is evaluated with this probability, but the actual outcome is determined by the probability plus a random uncertainty factor. The simulation stops early if the bankroll is depleted (bankruptcy).

Parameters:
  • strategy (BaseStrategy) – The betting strategy to evaluate.

  • bankroll (BankRoll) – The bankroll to use for the simulation.

Returns:

The bankroll object is updated in-place with the results of the simulation.

Return type:

None

Raises:

ValueError – If strategy is a BaseStrategy whose payoff or loss differs from this simulator’s, since it would then size bets against different odds than the ones the simulator settles at, or if the strategy returns a non-finite or out-of-range stake fraction.

Historical Binary Simulator

Replays a log of real bets: each trial uses a recorded probability and settles on the recorded outcome, so you can ask what a strategy would have done with your own bets. It draws no random numbers and takes no seed; the number of trials is the length of the log. Settlement matches the repeated binary simulator.

from keeks import BankRoll, HistoricalBinarySimulator, KellyCriterion

simulator = HistoricalBinarySimulator(
    payoff=1.0, loss=1.0, fee_per_bet=0.0,
    probabilities=[0.55, 0.60, 0.52],
    outcomes=[True, False, True],
)
bankroll = BankRoll(initial_funds=1000)
simulator.evaluate_strategy(KellyCriterion(payoff=1.0, loss=1.0, transaction_cost_rate=0.0), bankroll)
class keeks.simulators.historical_binary.HistoricalBinarySimulator(payoff: float, loss: float, fee_per_bet: float, probabilities: Sequence[float], outcomes: Sequence[bool | int])[source]

Bases: object

Replay a recorded sequence of binary bets through a strategy.

Each trial uses the recorded probability and settles on the recorded outcome, so the run answers “what would this strategy have done with my bets?”. Settlement, validation, hooks and early-stop behaviour match RepeatedBinarySimulator. No random numbers are drawn, so there is no seed.

Parameters:
  • payoff (float) – The amount won per unit bet on a successful outcome.

  • loss (float) – The amount lost per unit bet on an unsuccessful outcome.

  • fee_per_bet (float) – The flat fee, in currency, charged once per settled bet.

  • probabilities (sequence of float) – The probability estimate for each recorded bet, each in [0, 1].

  • outcomes (sequence of bool or int) – Whether each recorded bet won: True/False or 1/0. Must be the same length as probabilities.

trials

The number of recorded bets, len(probabilities).

Type:

int

Raises:

ValueError – If the sequences differ in length, a probability is not finite within [0, 1], an outcome is not boolean-like, or the odds controls are invalid.

evaluate_strategy(strategy: BaseStrategy, bankroll: BankRoll) → None[source]

Replay the recorded bets through strategy, updating bankroll in place.

The run stops early if the bankroll is depleted or a settlement raises RuinError (reported as a warning).

Parameters:
  • strategy (BaseStrategy) – The betting strategy to evaluate.

  • bankroll (BankRoll) – The bankroll to use for the simulation.

Raises:

ValueError – If the strategy’s payoff or loss differs from this simulator’s, or it returns an invalid stake fraction.