Skip to content

Repository files navigation

Keeks

License: MIT

Python bet sizing and bankroll simulation for developers modeling repeated binary outcomes.

Given your estimated win probability, payoff, loss, and normalized transaction cost, Keeks calculates a model-derived fraction of the current bankroll to stake. You can then run the same rule over repeated trials and inspect the bankroll path.

Nine-strategy risk benchmark — what growth, drawdown and early-stop behaviour each shipped strategy actually produces under identical, seeded assumptions, and how that changes with edge, cost, probability-estimate error and the bankroll's loss cap. Regenerate every number with uv run python benchmarks/strategy_benchmark.py.

Install

pip install keeks

Keeks supports Python 3.10 through 3.14.

Get a bet fraction

from keeks.binary_strategies import KellyCriterion

bankroll = 1_000.0
strategy = KellyCriterion(
    payoff=1.0,
    loss=1.0,
    transaction_cost=0.01,
)

fraction = strategy.evaluate(probability=0.55, current_bankroll=bankroll)
amount = bankroll * fraction

print(f"Bankroll fraction: {fraction:.4%}")
print(f"Amount from a $1,000 bankroll: ${amount:.2f}")
Bankroll fraction: 9.0009%
Amount from a $1,000 bankroll: $90.01

evaluate() returns a fraction, not a currency amount. The example multiplies that fraction by the current bankroll only to make the result concrete.

Compare repeated-bet strategies

Keeks includes a headless comparison example that gives every strategy a fresh bankroll under the same repeated-bet inputs:

python -m examples.strategy_comparison

Bankroll paths from the strategy comparison example

The chart is one simulated comparison under the example's assumptions. It does not validate the probability estimate or predict future results.

Choose a strategy

All nine strategies expose evaluate(probability, current_bankroll), but their constructors and sizing rules differ.

Strategy Choose it when you want to model
KellyCriterion Full Kelly sizing from a binary win probability, payoff, loss, and cost.
FractionalKellyCriterion A fixed fraction of the full-Kelly result.
DrawdownAdjustedKelly Kelly sizing scaled by an acceptable-drawdown input.
OptimalF A geometric-growth rule based on a supplied win rate, with a risk-fraction cap.
FixedFractionStrategy A constant fraction above a minimum probability; useful as a baseline.
CPPIStrategy A cushion-based rule relative to a bankroll floor.
DynamicBankrollManagement A fraction adjusted from recent recorded outcomes.
MertonShare A CRRA risk-aversion rule adapted to binary outcomes.
NaiveStrategy A positive-expected-value rule without utility-based sizing.

See the strategy API for constructor parameters and formulas.

Simulate a bankroll

Once you have chosen a strategy, pass it and a fresh BankRoll to a simulator:

from keeks.bankroll import BankRoll
from keeks.binary_strategies import FractionalKellyCriterion
from keeks.simulators.repeated_binary import RepeatedBinarySimulator

bankroll = BankRoll(
    initial_funds=1_000.0,
    percent_bettable=0.8,
    max_draw_down=0.3,
)
strategy = FractionalKellyCriterion(
    payoff=1.0,
    loss=1.0,
    transaction_cost=0.01,
    fraction=0.5,
)
simulator = RepeatedBinarySimulator(
    payoff=1.0,
    loss=1.0,
    transaction_costs=0.01,
    probability=0.55,
    trials=1_000,
)

simulator.evaluate_strategy(strategy, bankroll)

print(f"Final bankroll: ${bankroll.total_funds:.2f}")
bankroll.plot_history(fname="bankroll-history.png")

Simulation mutates the bankroll and records its history. Use matching payoff and loss assumptions in the strategy and simulator; Keeks does not enforce that they match. The cost assumption is a separate matter — see the note below.

Repeated sizing is not one-time pricing

strategy.evaluate(...) answers a repeated-bet question:

Given this binary model, what fraction of the current bankroll does this rule allocate now?

find_indifference_price(...) and supported strategy.calculate_max_entry_price(...) methods answer a different question:

Given possible outcomes and their probabilities, what is the maximum entry price that leaves modeled utility unchanged for a one-time gamble?

Run the shipped decision-theory example with:

python -m examples.st_petersburg_paradox

See examples/st_petersburg_paradox.py and the utilities documentation for the one-time workflow.

Safety semantics and model limits

  • Strategy fractions are floored at zero and capped so the modeled loss plus transaction cost cannot allocate more than the current bankroll.
  • BankRoll can restrict the bettable percentage and stop a simulation when a withdrawal breaches its configured maximum drawdown.
  • These constraints apply to the values in Keeks' binary model. They do not prevent losses, verify your probability estimate, or model spreads, slippage, market impact, venue-specific commissions, correlated positions, or portfolio rebalancing.
  • A strategy's transaction_cost is a per-unit fractional cost that scales with stake size. A simulator's transaction_costs (plural) is a flat, absolute bankroll amount charged once per settled bet. The two are different units — passing the same number to both models two different real-world costs, and Keeks does not convert between them.

Documentation and examples

References

Disclaimer

Keeks is for educational purposes. It does not provide investment, legal, or tax advice. Models and simulations can be wrong, and financial loss is possible. You are responsible for validating your inputs and deciding whether any real-world use is appropriate.

Contributing

Contributions are welcome. To set up the project and run its checks:

git clone https://github.com/wdm0006/keeks.git
cd keeks
make setup
make install-dev
make test
make lint

Build the documentation with:

make docs

Keeks is available under the MIT License.

About

A python library for bankroll allocation strategies

Resources

Code of conduct

Stars

6 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages