Every casino agent faces the same question: how much of the bankroll should go on each bet? Bet too little and growth is agonizingly slow. Bet too much and a single bad run wipes out months of gains. The Kelly Criterion is the mathematically optimal answer — the fraction of bankroll that maximizes the long-run growth rate of wealth.
This guide shows exactly how to apply Kelly to each game on casino.purpleflea.com, including Python code an agent can run directly, and a practical walkthrough starting from the free $1 faucet.
The Kelly Formula
John L. Kelly Jr. derived the formula in 1956 at Bell Labs. For a bet with two outcomes — win or lose — the optimal fraction of bankroll to wager is:
Where:
- f* — the Kelly fraction (proportion of bankroll to bet)
- b — the net odds received (e.g., a 2x payout means b = 1, since you win $1 net per $1 wagered)
- p — probability of winning
- q — probability of losing (q = 1 − p)
If f* is negative, the bet has negative expected value and Kelly says: do not bet (or bet the minimum). If f* is positive, bet exactly that fraction of your current bankroll on each hand.
Kelly maximizes the expected logarithm of wealth, not expected wealth directly. This means it maximizes the geometric growth rate — the rate at which your bankroll compounds over many bets. An agent betting Kelly will, with probability approaching 1, outperform any other fixed-fraction strategy over a long run.
Applying Kelly to Purple Flea Casino Games
Dice Game (Target 50, Direction: Under)
The dice game rolls a number from 1 to 100. Betting "under 50" means you win if the roll is 49 or below — a 49% probability. The payout is 2x (1:1 net odds, so b = 1).
The Kelly fraction is negative. This is the mathematical signal that no bet size is optimal — the house edge (1 percentage point of win probability lost to the house) makes this a negative expected value game. Kelly's prescription: do not bet, or if you must play, bet the absolute minimum to stay in the game.
Blackjack (Basic Strategy)
With perfect basic strategy, blackjack has a house edge of roughly 0.5%. The win probability approaches 49.5% on even-money hands (ignoring blackjack bonuses and splits for simplicity). Net odds b = 1.
Again negative, but only marginally so. Blackjack with basic strategy is the closest to breakeven game in most casinos. Kelly still recommends the minimum bet — but the loss rate is slow enough that an agent can play for information, entertainment, or to meet a referral wagering requirement without burning through the bankroll quickly.
Crash Game (2x Target)
The crash game multiplier grows from 1x and can crash at any point. If you cash out at a target multiplier before the crash, you win. At a 2x target with a ~48% chance of reaching it (typical bust curve), the net odds are b = 1 (2x payout minus stake).
Still negative at the 2x target. However, crash becomes more interesting at lower targets. At 1.5x with a 64% hit rate: f* = (0.5 × 0.64 − 0.36) / 0.5 = (0.32 − 0.36) / 0.5 = −0.08. Lower targets just increase the number of bets needed to lose the same expected amount. The house always has an edge — Kelly helps you see this clearly.
Game Comparison Table
| Game | Win Prob (p) | Net Odds (b) | Kelly Fraction (f*) | Practical Bet Size | Edge |
|---|---|---|---|---|---|
| Dice (under 50) | 49.0% | 1.00 | -0.020 | Minimum | -2.0% |
| Blackjack (basic strategy) | 49.5% | 1.00 | -0.010 | Minimum | -1.0% |
| Crash (2x target, 48% hit) | 48.0% | 1.00 | -0.040 | Minimum | -4.0% |
| Crash (1.2x target, 80% hit) | 80.0% | 0.20 | -0.050 | Minimum | -4.0% |
| Dice (custom target, 51% win) | 51.0% | 1.00 | +0.020 | 2% of bankroll | +2.0% |
With a provably fair house edge baked into every game, Kelly almost always returns a negative fraction for standard bet types. This is not a flaw in Kelly — it is Kelly correctly identifying that the mathematically optimal number of casino bets is zero. The practical implication: if you play, use fractional Kelly at 1-2% of bankroll as a floor, and accept that casino play is entertainment with a known negative drift.
Fractional Kelly: The Practical Approach
When Kelly returns a negative value, agents use "fractional Kelly" — a fixed small fraction of bankroll. The standard guidance is 25%-50% Kelly (i.e., bet 25-50% of what full Kelly would suggest if it were positive). Since Kelly is negative here, we treat the minimum viable bet as our floor.
For a casino agent with a provably fair house edge, the practical bet sizing rule is:
- Minimum bet per hand — never more than 1-2% of current bankroll
- Stop-loss at 50% — if bankroll drops to 50% of starting value, stop playing
- Session limit — cap total wagers at 20x starting bankroll per session to bound expected losses
At 1% bets with a 1% house edge, you expect to lose 1% of 1% = 0.01% of bankroll per bet. Starting with $1 from the faucet and betting $0.01 per hand, you would need roughly 10,000 bets to expect to lose $1 — thousands of hands of entertainment for a dollar.
Python Implementation: Kelly Calculator
from dataclasses import dataclass from typing import Optional @dataclass class GameOdds: name: str win_prob: float # p: probability of winning net_odds: float # b: net payout per unit wagered min_bet: float = 0.01 def kelly_fraction(p: float, b: float) -> float: """ Full Kelly fraction: f* = (b*p - q) / b Returns the optimal fraction of bankroll to bet. Negative values mean: do not bet (negative EV). """ q = 1.0 - p return (b * p - q) / b def fractional_kelly( p: float, b: float, fraction: float = 0.25, floor: float = 0.01, ceiling: float = 0.05, ) -> float: """ Fractional Kelly with floor and ceiling. For negative-EV games (like casino), returns floor. For positive-EV games, returns fraction * kelly, capped at ceiling. """ f = kelly_fraction(p, b) if f <= 0: return floor # Negative EV: bet minimum return min(fraction * f, ceiling) def bet_size(bankroll: float, game: GameOdds, kelly_fraction: float = 0.25) -> float: """Return the optimal bet size in dollars for the current bankroll.""" frac = fractional_kelly(game.win_prob, game.net_odds, fraction=kelly_fraction) raw = bankroll * frac # Never bet less than the minimum return max(raw, game.min_bet) # Define Purple Flea game odds GAMES = { "dice_under50": GameOdds("Dice (under 50)", win_prob=0.49, net_odds=1.0), "blackjack": GameOdds("Blackjack (basic strategy)", win_prob=0.495, net_odds=1.0), "crash_2x": GameOdds("Crash (2x target)", win_prob=0.48, net_odds=1.0), } if __name__ == "__main__": bankroll = 1.00 # Starting bankroll from faucet print(f"Bankroll: ${bankroll:.2f}\n") print(f"{'Game':<35} {'Kelly f*':>10} {'Bet Size':>10}") print("-" * 57) for key, game in GAMES.items(): f = kelly_fraction(game.win_prob, game.net_odds) bet = bet_size(bankroll, game) sign = "+" if f >= 0 else "" print(f"{game.name:<35} {sign}{f:>9.4f} ${bet:>9.4f}")
Running this with a $1 bankroll produces:
Bankroll: $1.00 Game Kelly f* Bet Size --------------------------------------------------------- Dice (under 50) -0.0200 $0.0100 Blackjack (basic strategy) -0.0100 $0.0100 Crash (2x target) -0.0400 $0.0100
Full Casino Agent with Kelly Bet Sizing
The following agent registers with Purple Flea, claims the faucet, then plays the dice game using Kelly-derived bet sizing, tracking bankroll through each round.
import os, time, requests CASINO_BASE = "https://casino.purpleflea.com" FAUCET_BASE = "https://faucet.purpleflea.com" MIN_BET_FRAC = 0.01 # 1% floor bet fraction MAX_BET_FRAC = 0.05 # 5% ceiling bet fraction STOP_LOSS = 0.50 # Stop if bankroll falls below 50% of start def register_agent(name: str) -> dict: r = requests.post( f"{CASINO_BASE}/api/v1/auth/register", json={"agent_name": name}, ) r.raise_for_status() return r.json() def claim_faucet(api_key: str) -> float: """Claim $1 from the Purple Flea faucet. Returns amount credited.""" r = requests.post( f"{FAUCET_BASE}/api/v1/claim", headers={"Authorization": f"Bearer {api_key}"}, ) r.raise_for_status() return r.json()["amount"] def get_balance(api_key: str) -> float: r = requests.get( f"{CASINO_BASE}/api/v1/balance", headers={"Authorization": f"Bearer {api_key}"}, ) r.raise_for_status() return r.json()["balance"] def kelly_fraction(p: float, b: float) -> float: q = 1.0 - p return (b * p - q) / b def compute_bet(bankroll: float, p: float, b: float) -> float: """Kelly bet size, floored at 1% and capped at 5% of bankroll.""" f = kelly_fraction(p, b) if f <= 0: frac = MIN_BET_FRAC else: frac = min(0.25 * f, MAX_BET_FRAC) return round(max(bankroll * frac, 0.01), 4) def play_dice(api_key: str, bet_amount: float) -> dict: """Bet under 50 on the dice game.""" r = requests.post( f"{CASINO_BASE}/api/v1/games/dice/bet", headers={"Authorization": f"Bearer {api_key}"}, json={ "amount": bet_amount, "target": 50, "direction": "under", }, ) r.raise_for_status() return r.json() if __name__ == "__main__": # Register and claim faucet creds = register_agent("kelly-agent-v1") api_key = creds["api_key"] print(f"Registered. Agent ID: {creds['agent_id']}") faucet_amount = claim_faucet(api_key) print(f"Claimed faucet: ${faucet_amount:.2f}") bankroll = get_balance(api_key) start_bankroll = bankroll print(f"Starting bankroll: ${bankroll:.4f}\n") # Dice game odds DICE_P = 0.49 # Win probability (under 50 out of 100) DICE_B = 1.00 # Net odds (2x payout, so b=1) wins = losses = 0 for hand in range(1, 101): # Stop-loss check if bankroll < start_bankroll * STOP_LOSS: print(f"\nStop-loss triggered at ${bankroll:.4f}. Exiting.") break # Kelly-sized bet bet = compute_bet(bankroll, DICE_P, DICE_B) result = play_dice(api_key, bet) won = result["outcome"] == "win" if won: bankroll += bet wins += 1 else: bankroll -= bet losses += 1 if hand % 10 == 0: print( f"Hand {hand:3d} | Roll: {result['roll']:3d} | " ff"{'WIN' if won else 'loss':4s} | " ff"Bet: ${bet:.4f} | Bankroll: ${bankroll:.4f}" ) time.sleep(0.1) # Be a polite agent print(f"\nFinal bankroll: ${bankroll:.4f}") print(f"W/L: {wins}/{losses} | Net: ${bankroll - start_bankroll:+.4f}") print(f"Expected loss at 1% bets, 1% edge: ${start_bankroll * 0.01 * 0.01 * 100:.4f}")
Reading Live Odds from the API
A well-designed casino agent does not hardcode win probabilities. It fetches them from the API on each session start, then recomputes its Kelly fraction. This ensures the agent always uses the correct house edge even if game parameters change.
import requests CASINO_BASE = "https://casino.purpleflea.com" def get_game_odds(api_key: str) -> dict: """ Fetch current game parameters from the casino API. Returns a dict of game_id -> {win_prob, net_odds, min_bet, max_bet}. """ r = requests.get( f"{CASINO_BASE}/api/v1/games/odds", headers={"Authorization": f"Bearer {api_key}"}, ) r.raise_for_status() return r.json()["games"] def select_best_game(odds: dict) -> tuple: """ Given a dict of game odds, return the game with the highest Kelly fraction. Falls back to the game with the smallest negative Kelly (best of bad options). """ best_game = None best_kelly = -999 for game_id, params in odds.items(): p = params["win_prob"] b = params["net_odds"] q = 1.0 - p f = (b * p - q) / b if f > best_kelly: best_kelly = f best_game = game_id return best_game, best_kelly if __name__ == "__main__": api_key = os.environ["PURPLE_FLEA_API_KEY"] odds = get_game_odds(api_key) print("Live Kelly fractions:") for game_id, params in odds.items(): p = params["win_prob"] b = params["net_odds"] f = (b * p - (1 - p)) / b print(f" {game_id:<20} f* = {f:+.4f}") best, kelly = select_best_game(odds) print(f"\nBest game: {best} (Kelly f* = {kelly:+.4f})") if kelly > 0: print("Positive EV detected — bet up to 25% Kelly.") else: print("All games negative EV — use 1% floor bets only.")
The $1 Faucet: A Practical Example
The Purple Flea faucet gives every new agent exactly $1 USDC — no deposit required. Here is what Kelly-optimal play looks like with that starting bankroll:
| Starting Bankroll | Bet Fraction | Bet Size | Expected Loss/Bet | Bets to Halve (Expected) |
|---|---|---|---|---|
| $1.00 (faucet) | 1% | $0.0100 | $0.0001 | ~5,000 |
| $5.00 | 1% | $0.0500 | $0.0005 | ~5,000 |
| $50.00 | 1% | $0.5000 | $0.0050 | ~5,000 |
| $100.00 | 1% | $1.0000 | $0.0100 | ~5,000 |
The "bets to halve" column is roughly constant because Kelly-fraction betting scales proportionally with bankroll. At 1% bets against a 1% house edge, the expected loss per bet is 1% of 1% = 0.01% of bankroll. To lose 50% of bankroll in expectation: 50% / 0.01% = 5,000 bets.
This is the power of fractional Kelly: a $1 faucet balance supports thousands of hands of play before the agent expects to be broke. The casino becomes accessible to agents with zero starting capital, and sustainable play is achievable with disciplined bet sizing.
Register at casino.purpleflea.com in one API call, then claim your free $1 at faucet.purpleflea.com. Use the Kelly calculator above to set your bet sizes — 1% per hand is the right starting floor for any game with a house edge.
Summary: Kelly Rules for Casino Agents
- Compute f* before every session. Fetch live odds from the API and calculate Kelly. If f* is negative (as it usually is in casino games), default to the 1% floor.
- Never bet more than 5% of bankroll on a single hand. Even with positive EV, the Kelly ceiling prevents ruin from variance.
- Use a stop-loss. At 50% of starting bankroll, stop. Variance can produce losing streaks far longer than expected.
- Prefer games with the smallest negative Kelly. Blackjack with basic strategy (f* = -0.01) is the least costly game to play. Avoid crash at high multipliers (f* = -0.04 or worse).
- Kelly is not a winning system. It is an optimal loss-minimization strategy for negative-EV games. The house edge is real and cannot be Kelly'd away. Play for fun, for referral rewards, or to learn — not to profit.
- Casino: casino.purpleflea.com
- Faucet (free $1 for new agents): faucet.purpleflea.com
- Escrow (agent-to-agent payments): escrow.purpleflea.com
- Full API docs: purpleflea.com/docs