Kelly Criterion

Summary

The Kelly criterion (or Kelly bet/Kelly strategy) is a formula for sizing a sequence of bets to maximize the long-term expected value of the logarithm of wealth (equivalently, to maximize the long-term expected geometric growth rate). It was described by John Larry Kelly Jr. of Bell Labs in 1956.

The key insight of Kelly is that bet size should be proportional to your edge, not your confidence. A 60% win probability with even money odds (b=1) gives Kelly fraction f* = (0.6×1 - 0.4)/1 = 0.20 (20% of bankroll). The formula works for any odds and probability.

The Kelly criterion has been demonstrated for gambling and is widely used in sports betting, blackjack, and financial markets. Warren Buffett and Bill Gross are commonly cited as using Kelly-style approaches. The criterion assumes known outcome probabilities — which in sports betting are never truly known, creating a key practical limitation.

Key Concepts

  • Full Kelly: The mathematically optimal fraction for maximizing long-term growth. Can be aggressive — leads to high volatility and risk of ruin.
  • Fractional Kelly: Betting a fraction of the Kelly amount (half-Kelly, quarter-Kelly) to reduce volatility and account for estimation error. Most practitioners use half-Kelly or less.
  • Geometric growth rate: Kelly maximizes E[log(wealth)] rather than E[wealth], which accounts for compounding effects and risk of ruin.
  • Log-wealth utility: Maximizing expected log of wealth is the same as expected utility maximization with log utility — risk-averse in a specific sense.
  • Risk of ruin: Full Kelly bettors have a ~33% chance of halving their bankroll before doubling it; half-Kelly bettors only have ~11% chance.
  • Edge requirement: Kelly tells you to bet nothing (f ≤ 0) if you have no edge (bp ≤ q).

Formulas

Kelly fraction (binary outcome, full loss on loss):
$$f^* = \frac{bp - q}{b} = \frac{p(b+1) - 1}{b}$$

Where:
- f* = fraction of bankroll to bet
- p = probability of winning
- q = 1 - p = probability of losing
- b = net odds received on winning bet (for decimal odds d: b = d - 1)

Simplified Kelly (b=1, even money):
$$f^* = 2p - 1$$

A 60% win probability → f* = 0.20 (20% of bankroll).

Kelly with partial loss (investments):
$$f^* = \frac{p \cdot b - q \cdot c}{b \cdot c}$$

Where c = fraction lost on a losing bet.

General form:
$$f^* = \frac{E[R]}{Var[R]}$$

Where E[R] = expected return, Var[R] = variance of return. This arises from the Taylor expansion of log-wealth growth.

Expected geometric growth rate:
$$G(f) = p \ln(1 + fb) + q \ln(1 - f)$$

Kelly maximizes G(f) by setting dG/df = 0.

Python Implementation

def kelly_fraction(p, decimal_odds):
    """
    Calculate full Kelly fraction.

    Args:
        p: probability of winning (from model)
        decimal_odds: decimal odds (e.g., 2.00 for even money)

    Returns:
        Kelly fraction (0-1, where 1 = 100% of bankroll)
    """
    b = decimal_odds - 1  # net odds received on win
    q = 1 - p

    if b <= 0:
        return 0.0  # no positive edge possible

    f = (p * b - q) / b

    # Kelly tells you to go negative (take the other side) if edge is negative
    # In practice, we clip at 0 for betting the favorite
    return max(f, 0)

def half_kelly(p, decimal_odds):
    """Half Kelly — standard practice for managing volatility."""
    return kelly_fraction(p, decimal_odds) * 0.5

def kelly_stake(bankroll, p, decimal_odds, fraction=0.5):
    """
    Calculate Kelly stake in dollars.

    Args:
        bankroll: total bankroll
        p: probability of winning
        decimal_odds: decimal odds
        fraction: Kelly fraction to use (0.5 = half Kelly)
    """
    f = kelly_fraction(p, decimal_odds)
    return bankroll * f * fraction

# Example
bankroll = 10000
p_brazil = 0.60
odds_brazil = 1.80

f_full = kelly_fraction(p_brazil, odds_brazil)
f_half = half_kelly(p_brazil, odds_brazil)
stake_half = kelly_stake(bankroll, p_brazil, odds_brazil, fraction=0.5)

print(f"Full Kelly fraction: {f_full:.3f} ({f_full*100:.1f}%)")  # 0.167
print(f"Half Kelly fraction: {f_half:.3f} ({f_half*100:.1f}%)")  # 0.083
print(f"Half Kelly stake: ${stake_half:.2f}")  # $833

Notes

  • Kelly requires accurate probability estimates — if your probabilities are systematically overestimated, Kelly will overbet and increase risk of ruin
  • In practice, fractional Kelly (0.5 or 0.25) is standard because: (a) our probability estimates are never perfectly calibrated, (b) full Kelly has high volatility, (c) model error is always present
  • For the World Cup model: Kelly sizing should use the model's estimated probabilities relative to de-vigged Pinnacle odds, not relative to soft bookmaker odds
  • The client's spec calls for Half-Kelly, which is the industry standard for sports betting applications
  • Kelly is most effective over many bets — with only 64 World Cup matches, the actual results will vary significantly from theoretical Kelly growth