Full Code
The Math
For a binary prediction market with two outcomes (Yes at priceP, No at price 1 - P):
Kelly for Yes (buying Yes)
When you believe the true probabilityp exceeds the market price P:
Kelly for No (buying No)
When you believe the market is overpriced (p < P):
Edge
The expected value per dollar risked:All Kelly Functions
hz.kelly(prob, market_price)
Full Kelly fraction for the Yes side. Returns 0.0 if no edge.hz.kelly_no(prob, market_price)
Kelly fraction for the No side. Use when you think the market is too high.hz.fractional_kelly(prob, market_price, fraction)
Multiplies the raw Kelly by a scaling factor. Using fractional Kelly reduces variance at the cost of slightly lower expected growth.Most professional traders use quarter or half Kelly. Full Kelly is theoretically optimal for long-run growth but produces extreme drawdowns in practice. Half Kelly achieves 75% of the growth rate with substantially lower variance.
hz.kelly_size(prob, market_price, bankroll, fraction, max_size)
Converts the Kelly fraction into an actual contract count:max_size.
hz.edge(prob, market_price)
Raw expected edge. Can be negative (no edge).Kelly for the No Side
When you think a market is overpriced, bet on No:Multi-Position Kelly
When you have edge across multiple markets simultaneously, usemulti_kelly to prevent over-allocation:
- Computes Kelly fractions independently for each market.
- If the sum exceeds
max_total, proportionally scales all fractions down. - Markets with no edge (Kelly = 0) stay at 0.
Liquidity-Adjusted Kelly
In thin prediction markets, placing your full Kelly size would eat through the book.liquidity_adjusted_kelly uses square-root scaling to dampen sizing as you approach available liquidity:
Pipeline Integration
Thekelly_sizer function creates a pipeline-compatible sizing stage for use with hz.run():
kelly_sizer parameters
The sizer reads the market price from the first available feed’s bid/ask midpoint. It returns 0.0 if no feed data is available or if there is no edge.
Liquidity-adjusted pipeline sizer
When NOT to Use Kelly
Kelly criterion assumes you know the true probability. In practice, several conditions make Kelly dangerous:No edge
If your estimated probability equals the market price, Kelly returns 0. Do not override this. The market is efficient and you should not trade.Bad calibration
If your probability estimates are systematically wrong (overconfident or underconfident), Kelly will oversize or undersize. Usehz.backtest() with outcomes to measure your Brier score before going live.
Correlated positions
multi_kelly treats markets as independent. If your positions are correlated (e.g., multiple BTC price markets), the true optimal sizing is lower. Use a smaller max_total:
Thin liquidity
Full Kelly in a thin market causes massive slippage. Always useliquidity_adjusted_kelly or set a low max_size cap.
Function Reference
All core functions (
kelly, kelly_no, fractional_kelly, kelly_size, multi_kelly, liquidity_adjusted_kelly, edge) are implemented in Rust with #[inline] for zero-overhead calls from Python via PyO3.