The Kelly idea is simple in spirit and very useful for bankroll management. If you actually have an edge in blackjack through counting and solid rules, Kelly tells you what fraction of your bankroll to bet on each hand so you grow over the long run. If you use it carelessly, the swings can still be rough.
f* = (b p - q) / b
f* is the fraction of bankroll to wager
b is the net odds. even money is 1.0 and a 3:2 natural is 1.5
p is the chance of winning
q is 1 minus p
In blackjack your edge and your p change with the true count and the table rules. Kelly adjusts your bet size as that edge moves around.
def kelly(p, b):
"""
p is win probability between 0 and 1
b is net odds. even money is 1.0, a 3:2 payout is 1.5
returns the Kelly fraction between 0 and 1
"""
if p <= 0 or p >= 1 or b <= 0:
return 0.0
f = (b * p - (1 - p)) / b
if f < 0:
return 0.0
if f > 1:
return 1.0
return f
def simulate(initial_bankroll, bets, kelly_frac=0.5, max_per_hand=0.05):
"""
bets is a list of dicts like {"p": 0.52, "b": 1.0, "won": True or False}
kelly_frac lets you run half Kelly or quarter Kelly etc
max_per_hand is a hard cap so you never bet too much at once
returns a list of bankroll values over time
"""
bk = float(initial_bankroll)
history = [bk]
for bet in bets:
p = float(bet["p"])
b = float(bet["b"])
f_star = kelly(p, b)
f_use = min(f_star * kelly_frac, max_per_hand)
stake = bk * f_use
if bet["won"]:
bk += stake * b
else:
bk -= stake
history.append(bk)
return history
def max_drawdown(values):
"""
values is the bankroll history
returns the worst drawdown as a fraction
"""
peak = values[0]
worst = 0.0
for x in values:
if x > peak:
peak = x
dd = (peak - x) / peak
if dd > worst:
worst = dd
return worst
Even money hands use b equal to 1.0. Naturals pay 3:2 so those events use b equal to 1.5 if you model them separately.
Estimate p from your count and your exact rules. Kelly needs a realistic p and it should change with the shoe.
Full Kelly grows the bankroll fastest in theory but the variance can be intense. Half Kelly or quarter Kelly is usually easier to live with.
Casinos have table limits and there is also heat in real life, so add hard caps in code and respect the table.
Start with half Kelly or quarter Kelly in any live test.
Model your specific rules and penetration.
Use a max fraction per hand so a hot count does not push bets to a silly level.
Track drawdowns and make sure the worst case does not make you panic.
Reestimate your edge as the shoe changes and update the bet size in real time.