Skip to content
python.financial

The Kelly criterion chooses the fraction of current wealth that maximizes expected logarithmic wealth growth under a specified probability model. It does not minimize drawdown or maximize expected terminal wealth. It is also not a complete position-sizing rule until the payoff, loss amount, estimation method, costs, portfolio correlations, and trading constraints are defined.

John L. Kelly Jr. introduced the growth-rate argument in his 1956 paper, A New Interpretation of Information Rate. Edward Thorp later developed its gambling and market applications, including the fixed-fraction interpretation described in The Kelly Criterion and the Stock Market.

Kelly formula for a binary bet

Suppose each independent repetition has two outcomes:

  • A win has probability p and earns b net units for each unit staked.
  • A loss has probability q = 1 - p and loses the entire stake.
  • f is the fraction of current wealth staked each time, with 0 <= f < 1 for an unlevered long bet.

The expected log-growth rate per bet is:

g(f) = p * ln(1 + b * f) + q * ln(1 - f)

Differentiating this function gives the full-Kelly fraction:

f* = p - q / b

For a 55% win probability and even-money payoff, f* = 0.55 - 0.45 / 1 = 0.10, or 10% of current wealth. A negative result means the modeled long bet is unfavorable. Shorting is justified only if a separately specified short payoff and the relevant constraints support it. A result above 1 implies leverage in the idealized model, not automatic permission to borrow.

The formula assumes the probabilities and payoff are known and stable, the stated loss really is the full amount at risk, and wealth can be resized after every outcome. Dependence between bets, limits, taxes, fees, market impact, funding, and the possibility of a loss beyond the assumed bound all change the problem.

What happens below and above full Kelly

The growth curve is concave. Expected log growth rises until f* and then falls, but that does not make every over-Kelly fraction worse than every under-Kelly fraction on every measure. An over-Kelly strategy can still have positive expected log growth, while suffering much deeper drawdowns and a worse left tail.

The following reproducible simulation uses the same 20,000 sets of outcomes for every fraction, so differences are caused by sizing rather than different random samples. It includes starting wealth when calculating drawdown.

import numpy as np

rng = np.random.default_rng(42)
p, b = 0.55, 1.0
n_sims, n_bets = 20_000, 200
wins = rng.random((n_sims, n_bets)) < p

fractions = {
    "Quarter": 0.025,
    "Half": 0.05,
    "Full": 0.10,
    "1.5x": 0.15,
    "Double": 0.20,
}

print("Size     Log growth  Median wealth  Median max DD  P(wealth < 0.1)")
for label, fraction in fractions.items():
    multipliers = np.where(wins, 1 + b * fraction, 1 - fraction)
    wealth = np.cumprod(multipliers, axis=1)
    wealth_with_start = np.column_stack((np.ones(n_sims), wealth))
    running_max = np.maximum.accumulate(wealth_with_start, axis=1)
    max_dd = (wealth_with_start / running_max - 1).min(axis=1)
    log_growth = p * np.log(1 + b * fraction) + (1 - p) * np.log(1 - fraction)
    below_tenth = np.mean(wealth[:, -1] < 0.1)
    print(
        f"{label:7}  {log_growth:10.6f}  {np.median(wealth[:, -1]):13.2f}x"
        f"  {np.median(max_dd):12.1%}  {below_tenth:15.1%}"
    )
Size     Log growth  Median wealth  Median max DD  P(wealth < 0.1)
Quarter    0.002188           1.55x        -22.8%             0.0%
Half       0.003753           2.12x        -41.7%             0.0%
Full       0.005008           2.72x        -69.9%             0.9%
1.5x       0.003736           2.11x        -86.8%             6.8%
Double    -0.000138           0.97x        -95.4%            21.3%

Full Kelly has the highest expected log growth in this exact model. Half Kelly and 1.5 times Kelly have almost the same expected log growth, but the larger fraction has a far worse typical drawdown and left tail. Double Kelly is slightly negative in expected log growth here. These are simulated binary bets with known fixed parameters, not expected market returns or evidence of a trading edge.

Continuous-return and multi-asset Kelly sizing

For one strategy under an idealized continuous-time diffusion, a commonly used approximation is:

f* = (mu - r) / sigma^2

Here mu - r is the expected excess arithmetic return per unit of time, and sigma is return volatility per square root of the same time unit. Therefore sigma^2 is variance per unit of time and f* is dimensionless. Mixing a daily mean with annualized volatility, or substituting a log-return drift without the corresponding conversion, gives the wrong fraction.

For n correlated assets, the unconstrained diffusion result becomes:

w* = Sigma^-1 * (mu - r * 1)

w* is the vector of portfolio weights, mu is the vector of expected arithmetic returns, r is the matching risk-free rate, 1 is a vector of ones, and Sigma is the return covariance matrix in matching time units. This is an idealized unconstrained solution. Nearly collinear assets can make Sigma^-1 unstable, and small changes in expected returns can cause large changes in weights.

A usable portfolio calculation normally needs covariance shrinkage, leverage and concentration limits, turnover and transaction costs, borrow availability, funding rates, liquidity limits, and stress scenarios. Rebalancing frequency also matters because continuous resizing is impossible in real trading.

Why practitioners use fractional Kelly

The full-Kelly solution is optimal only for the assumed distribution and parameters. Expected returns are especially noisy estimates. If estimated edge is twice the true edge while risk is estimated correctly, the resulting full-Kelly position can be roughly double Kelly under the true model.

Fractional Kelly multiplies the estimated full-Kelly allocation by a coefficient such as 0.25 or 0.5. This gives up modeled growth in exchange for less sensitivity to estimation error and generally smaller drawdowns. The coefficient is a risk choice, not a universal constant. It should be selected against uncertainty, leverage, liquidity, tail losses, mandate limits, and the consequences of model failure.

Historical estimation introduces further problems:

  • Backtest selection can inflate the expected return used in the numerator.
  • Regime changes can invalidate both the mean and covariance estimate.
  • Serial correlation and overlapping positions violate the independent-bet picture.
  • Options, leveraged products, short positions, and gap risk can lose more than a simple model assumes.
  • Fees, slippage, market impact, borrow costs, and funding reduce the edge before Kelly sizing is calculated.

A Kelly fraction is capital at risk, not always position value

For the binary formula, f is the fraction of wealth lost when the losing outcome occurs. That equals position notional only when the entire stake is lost. In a trade with a planned stop, the translation is instead:

units = (equity * risk_fraction) / loss_per_unit

If equity is $100,000, the chosen risk fraction is 1%, entry is $100, and the modeled exit on loss is $98, then loss_per_unit is $2 and the calculated position is 500 units. Its $50,000 notional is 50% of equity, while modeled capital at risk is $1,000. Gaps and slippage can make the realized loss larger than $2 per unit.

This distinction matters in software. Community VectorBT defines size_type="percent" as a percentage of available resources, not a percentage of position value or a stop-defined risk budget. Passing size=0.10 can allocate available cash, but it does not prove that 10% of equity is the maximum loss. The official size-type reference states this boundary explicitly.

VectorBT PRO is useful for evaluating many sizing rules, correlated portfolios, shared capital, rebalancing schedules, costs, and constrained portfolio-optimization workflows. Its portfolio optimization material includes integrations for covariance-aware allocation methods. Those tools can simulate an estimated Kelly or fractional-Kelly policy, but they cannot make the expected returns or loss model true. pysystemtrade takes a different practical route through volatility targeting and forecast-weighted risk allocation rather than treating a single estimated Kelly fraction as known.

Checklist before using Kelly sizing

Before using a Kelly-derived size:

  1. Define the complete payoff distribution, including losses beyond a planned stop.
  2. Estimate edge after all trading and financing costs.
  3. Keep means, variances, covariances, and the risk-free rate in consistent units.
  4. Account for correlation between simultaneous and repeated bets.
  5. Apply leverage, concentration, liquidity, turnover, and mandate constraints.
  6. Reduce the allocation for parameter uncertainty and model error.
  7. Simulate drawdowns, tail loss, and gap scenarios, not just expected log growth.
  8. Re-estimate only on a documented schedule and validate the sizing rule out of sample.

Kelly sizing is best treated as a model-relative upper reference for growth-oriented allocation. The deployable fraction is usually a constrained, cost-aware, uncertainty-adjusted version of that reference.

Choose which optional services may run. You can change these settings at any time.