Kelly Criterion Sizing
Kelly criterion position sizing. A complete hands-on Jupyter notebook with production-ready Python implementation, best practices, and step-by-step walkthrough for risk workflows in quantitative cryptocurrency trading.
The Kelly Criterion for Optimal Capital Sizing
1. Introduction: What is the Kelly Criterion?
The Kelly Criterion is a mathematical formula used to determine the optimal size of a series of bets (or investments) to maximize the long-term growth rate of capital. Developed by John L. Kelly Jr. in 1956, it's widely applied in gambling, investing, and other fields involving sequential decision-making under uncertainty.
Purpose:
The primary purpose of the Kelly Criterion is to balance risk and reward by preventing over-betting (which can lead to ruin) and under-betting (which leads to slower capital growth). It aims to find the 'sweet spot' for capital allocation that maximizes expected utility, specifically the geometric growth rate of wealth over time.
Importance:
- Optimal Growth: It suggests the bet size that maximizes the long-term compound annual growth rate (CAGR) of an investment portfolio or betting bankroll.
- Risk Management: By providing an optimal fraction, it inherently manages risk by ensuring that a single bet doesn't disproportionately jeopardize the entire capital.
- Behavioral Edge: It helps overcome emotional biases that often lead to suboptimal betting or investment decisions.
However, it's crucial to understand that the Kelly Criterion relies on accurate estimations of win probability and payout ratios, which can be challenging in real-world scenarios.
2. The Kelly Criterion Formula
The basic form of the Kelly Criterion for a simple bet (binary outcome) is:
$$f = \frac{bp - q}{b}$$
Where:
- $f$: The fraction of current capital to wager (the Kelly fraction).
- $b$: The net odds received on the bet (payout ratio). For example, if you bet $10 and win $20, then $b = 20/10 = 2$.
- $p$: The probability of winning the bet.
- $q$: The probability of losing the bet, which is $1 - p$.
Interpretation of $f$:
- If $f > 0$: The bet has a positive expected value, and the optimal fraction of your capital to bet is $f$.
- If $f \le 0$: The bet has a negative or zero expected value, and the Kelly Criterion suggests not betting (or betting 0 fraction of your capital).
Let's implement a function to calculate this fraction.
import numpy as np
import matplotlib.pyplot as plt
def calculate_kelly_fraction(win_prob: float, payout_ratio: float) -> float:
"""
Calculates the optimal Kelly fraction for a simple bet.
Inputs:
win_prob (float): The probability of winning the bet (p). Must be between 0 and 1.
payout_ratio (float): The net odds received on the bet (b). For a 1:1 payout, b=1.
For a 2:1 payout, b=2. Must be greater than 0.
Outputs:
float: The Kelly fraction (f). Returns 0 if the expected value is not positive.
Formula Used:
f = (b * p - q) / b
where q = 1 - p
"""
if not (0 <= win_prob <= 1):
raise ValueError("Win probability must be between 0 and 1.")
if payout_ratio <= 0:
raise ValueError("Payout ratio must be greater than 0.")
q = 1 - win_prob
# The core Kelly formula
kelly_f = (payout_ratio * win_prob - q) / payout_ratio
# If Kelly fraction is negative or zero, it means the bet has a non-positive expected value,
# so the optimal strategy is to not bet (or bet 0).
return max(0.0, kelly_f)
# --- Example Usage ---
print("--- Example 1: Favorable Bet ---")
win_prob_1 = 0.55 # 55% chance of winning
payout_ratio_1 = 1.0 # Even money (1:1 payout)
kelly_f_1 = calculate_kelly_fraction(win_prob_1, payout_ratio_1)
print(f"Win Probability: {win_prob_1*100:.1f}%")
print(f"Payout Ratio (b): {payout_ratio_1:.2f}")
print(f"Kelly Fraction (f): {kelly_f_1:.4f}")
print(f"Optimal bet size: {kelly_f_1*100:.2f}% of capital\n")
print("--- Example 2: Less Favorable Bet ---")
win_prob_2 = 0.51 # 51% chance of winning
payout_ratio_2 = 1.0 # Even money (1:1 payout)
kelly_f_2 = calculate_kelly_fraction(win_prob_2, payout_ratio_2)
print(f"Win Probability: {win_prob_2*100:.1f}%")
print(f"Payout Ratio (b): {payout_ratio_2:.2f}")
print(f"Kelly Fraction (f): {kelly_f_2:.4f}")
print(f"Optimal bet size: {kelly_f_2*100:.2f}% of capital\n")
print("--- Example 3: Unfavorable Bet ---")
win_prob_3 = 0.49 # 49% chance of winning
payout_ratio_3 = 1.0 # Even money (1:1 payout)
kelly_f_3 = calculate_kelly_fraction(win_prob_3, payout_ratio_3)
print(f"Win Probability: {win_prob_3*100:.1f}%")
print(f"Payout Ratio (b): {payout_ratio_3:.2f}")
print(f"Kelly Fraction (f): {kelly_f_3:.4f}")
print(f"Optimal bet size: {kelly_f_3*100:.2f}% of capital")--- Example 1: Favorable Bet --- Win Probability: 55.0% Payout Ratio (b): 1.00 Kelly Fraction (f): 0.1000 Optimal bet size: 10.00% of capital --- Example 2: Less Favorable Bet --- Win Probability: 51.0% Payout Ratio (b): 1.00 Kelly Fraction (f): 0.0200 Optimal bet size: 2.00% of capital --- Example 3: Unfavorable Bet --- Win Probability: 49.0% Payout Ratio (b): 1.00 Kelly Fraction (f): 0.0000 Optimal bet size: 0.00% of capital
Interpretation of Results:
From the examples, we can see:
- A favorable bet (Example 1) with a 55% win probability and even money payout suggests betting 10% of your capital.
- As the edge decreases (Example 2, 51% win probability), the optimal Kelly fraction also decreases significantly.
- For an unfavorable bet (Example 3), where the win probability is less than what's implied by the odds (for even money, anything less than 50%), the Kelly fraction is 0, meaning you should not bet.
3. Simulating Capital Growth with Kelly Criterion
To truly understand the power and implications of the Kelly Criterion, it's helpful to simulate a series of bets over time. This will demonstrate how different betting fractions impact capital growth, particularly the benefits of optimal Kelly betting versus over-betting or under-betting.
def simulate_kelly_bets(initial_capital: float,
num_bets: int,
win_prob: float,
payout_ratio: float,
betting_fraction: float) -> np.ndarray:
"""
Simulates a series of bets and tracks capital growth over time.
Inputs:
initial_capital (float): The starting capital.
num_bets (int): The number of bets to simulate.
win_prob (float): The probability of winning each bet (p).
payout_ratio (float): The net odds received on each bet (b).
betting_fraction (float): The fraction of current capital to bet on each round.
Outputs:
np.ndarray: An array containing the capital after each bet.
"""
capital_history = np.zeros(num_bets + 1)
capital_history[0] = initial_capital
current_capital = initial_capital
for i in range(num_bets):
if current_capital <= 0: # Check for ruin
capital_history[i+1:] = 0
break
bet_size = current_capital * betting_fraction
if np.random.rand() < win_prob: # Bet wins
current_capital += bet_size * payout_ratio
else: # Bet loses
current_capital -= bet_size
capital_history[i+1] = current_capital
return capital_history
# --- Simulation Parameters ---
initial_capital = 1000.0
num_bets = 500
win_prob_sim = 0.52 # A slight edge
payout_ratio_sim = 1.0 # Even money
# Calculate full Kelly fraction for these parameters
kelly_f_sim = calculate_kelly_fraction(win_prob_sim, payout_ratio_sim)
print(f"Simulation Parameters:")
print(f" Initial Capital: ${initial_capital:.2f}")
print(f" Number of Bets: {num_bets}")
print(f" Win Probability: {win_prob_sim*100:.1f}%")
print(f" Payout Ratio: {payout_ratio_sim:.2f}")
print(f" Calculated Full Kelly Fraction: {kelly_f_sim*100:.2f}%\n")
# Simulate for different betting strategies
full_kelly_history = simulate_kelly_bets(initial_capital, num_bets, win_prob_sim, payout_ratio_sim, kelly_f_sim)
half_kelly_history = simulate_kelly_bets(initial_capital, num_bets, win_prob_sim, payout_ratio_sim, kelly_f_sim / 2)
fixed_fraction_history = simulate_kelly_bets(initial_capital, num_bets, win_prob_sim, payout_ratio_sim, 0.05) # Fixed 5% bet
over_betting_history = simulate_kelly_bets(initial_capital, num_bets, win_prob_sim, payout_ratio_sim, kelly_f_sim * 1.5) # 150% of KellySimulation Parameters: Initial Capital: $1000.00 Number of Bets: 500 Win Probability: 52.0% Payout Ratio: 1.00 Calculated Full Kelly Fraction: 4.00%
4. Visualizations
4.1. Capital Growth Over Time with Different Betting Strategies
This visualization compares the capital growth trajectories for different betting fractions: full Kelly, half Kelly, a fixed (but reasonable) fraction, and an over-betting scenario. It highlights how the Kelly Criterion aims for optimal long-term growth while managing drawdowns.
plt.figure(figsize=(14, 7))
plt.plot(full_kelly_history, label=f'Full Kelly (f={kelly_f_sim*100:.1f}%)', color='green')
plt.plot(half_kelly_history, label=f'Half Kelly (f={(kelly_f_sim/2)*100:.1f}%)', color='blue', linestyle='--')
plt.plot(fixed_fraction_history, label='Fixed 5% Bet', color='orange')
plt.plot(over_betting_history, label=f'Over-Betting (1.5x Kelly, f={(kelly_f_sim*1.5)*100:.1f}%)', color='red', linestyle=':')
plt.title('Capital Growth Over 500 Bets (Simulated)', fontsize=16)
plt.xlabel('Number of Bets', fontsize=12)
plt.ylabel('Capital ($)', fontsize=12)
plt.axhline(y=0, color='black', linestyle='-', linewidth=0.8) # Line at 0 capital (ruin)
plt.grid(True, linestyle='--', alpha=0.6)
plt.legend(fontsize=10)
plt.yscale('log') # Use a log scale for better visualization of exponential growth
plt.ylim(1, plt.ylim()[1]) # Ensure y-axis starts above 0 for log scale
plt.show()Interpretation of Visualization 4.1:
- Full Kelly (Green Line): Shows the fastest long-term growth. However, it can experience significant volatility and drawdowns due to its aggressive nature. Notice its final capital is often the highest.
- Half Kelly (Blue Dashed Line): Often considered a more practical approach, 'half Kelly' delivers good growth but with significantly reduced volatility and lower risk of ruin. It's a common compromise for risk-averse investors.
- Fixed 5% Bet (Orange Line): A conservative fixed fraction bet still shows growth but at a slower pace compared to optimal Kelly strategies, especially in the long run.
- Over-Betting (Red Dotted Line): This strategy, despite having a positive edge, quickly leads to ruin. Betting more than the Kelly fraction, even slightly, drastically increases the probability of losing all capital. This vividly illustrates the importance of not being too aggressive.
4.2. Kelly Fraction as a Function of Win Probability and Payout Ratio
This heatmap illustrates how the optimal Kelly fraction changes depending on the win probability ($p$) and the net payout ratio ($b$). It helps to visualize the sensitivity of the Kelly fraction to these two critical inputs.
# Create a grid of win probabilities and payout ratios
win_probs = np.linspace(0.4, 0.8, 100) # Probabilities from 40% to 80%
payout_ratios = np.linspace(0.5, 3.0, 100) # Payouts from 0.5:1 to 3:1
# Initialize a matrix to store Kelly fractions
kelly_fractions_matrix = np.zeros((len(win_probs), len(payout_ratios)))
# Calculate Kelly fraction for each combination
for i, p in enumerate(win_probs):
for j, b in enumerate(payout_ratios):
kelly_fractions_matrix[i, j] = calculate_kelly_fraction(p, b)
plt.figure(figsize=(12, 8))
plt.imshow(kelly_fractions_matrix, origin='lower', extent=[payout_ratios.min(), payout_ratios.max(), win_probs.min(), win_probs.max()],
aspect='auto', cmap='viridis', vmin=0, vmax=kelly_fractions_matrix.max())
plt.colorbar(label='Kelly Fraction (f)')
plt.title('Kelly Fraction (f) vs. Win Probability (p) and Payout Ratio (b)', fontsize=16)
plt.xlabel('Payout Ratio (b)', fontsize=12)
plt.ylabel('Win Probability (p)', fontsize=12)
plt.axvline(x=1.0, color='white', linestyle=':', linewidth=1) # Highlight even money payout
plt.axhline(y=0.5, color='white', linestyle=':', linewidth=1) # Highlight 50% win probability
plt.show()Interpretation of Visualization 4.2:
- The darker regions (lower left) indicate scenarios where the Kelly fraction is zero, meaning the expected value of the bet is not positive, and no bet should be placed.
- As win probability ($p$) increases (moving upwards on the y-axis), the optimal Kelly fraction generally increases, assuming a constant payout ratio.
- As payout ratio ($b$) increases (moving rightwards on the x-axis), the optimal Kelly fraction also tends to increase, especially with a positive win probability.
- The brightest regions (upper right) represent situations with both high win probabilities and high payout ratios, leading to very large optimal Kelly fractions.
- Notice the white dashed lines showing the boundaries for $p=0.5$ and $b=1.0$. Only above $p = q/b$ (or $pb > q$) is the Kelly fraction positive. For $b=1$ (even money), this means $p>0.5$. This visualization clearly shows how intertwined $p$ and $b$ are in determining the optimal bet size.
5. Practical Considerations and Limitations
While powerful, the Kelly Criterion has important practical considerations and limitations:
- Accurate Estimation of P and B: The biggest challenge is accurately estimating the true win probability ($p$) and the exact payout ratio ($b$) for future bets/investments. In real markets, these are rarely known with certainty and often change.
- "Half Kelly" or Fractional Kelly: Due to the difficulty in precisely estimating $p$ and $b$, and to reduce volatility and the risk of significant drawdowns, many practitioners use a fractional Kelly (e.g., half Kelly or quarter Kelly). This provides a balance between maximizing growth and managing risk more conservatively.
- Single-Asset vs. Multi-Asset: The basic formula is for a single, independent bet. Extending it to multiple, correlated assets is more complex and requires a matrix form of the criterion.
- Assumptions: The Kelly Criterion assumes an infinite series of independent bets, that capital is infinitely divisible, and that the bettor's primary goal is maximizing long-term geometric growth.
- Volatility: Even with optimal Kelly betting, capital can experience significant volatility and drawdowns. This makes it psychologically challenging to implement consistently.
- Transaction Costs: The formula typically does not account for transaction costs, commissions, or taxes, which can erode returns.
6. Conclusion
The Kelly Criterion is a fundamental concept in optimal capital allocation, offering a mathematically sound approach to maximizing long-term wealth growth while explicitly considering risk. It teaches us the dangers of both under-betting (leaving potential growth on the table) and, more importantly, over-betting (which can lead to ruin even with a positive edge).
While its direct application can be challenging in dynamic real-world scenarios due to the difficulty in estimating probabilities and payouts, the principles of Kelly are invaluable. It serves as a powerful conceptual framework for understanding the relationship between risk, reward, and capital sizing, guiding more disciplined and rational investment and betting strategies, often through the use of fractional Kelly approaches.