DEV Community

Rust Engineer
Rust Engineer

Posted on

How Kelly Criterion Transformed My Polymarket Trading Bot

I've been building a Polymarket trading bot for a while now. The strategy was solid - good signal, decent win rate - but the returns felt inconsistent. Some weeks were great, others wiped out gains I'd spent days building. The bot was right more often than not, but the sizing was all over the place.

Then I implemented the Kelly Criterion. It didn't change a single prediction. It just changed how much I bet on each one. The difference was night and day.

Please take a look at my Polymarket account

What Is the Kelly Criterion?

The Kelly Criterion is a formula for calculating the optimal fraction of your bankroll to wager on a bet, given your edge. It was invented by John Kelly at Bell Labs in 1956 and has been used by everyone from blackjack card counters to quantitative hedge funds.

The formula:

f* = (bp - q) / b
Enter fullscreen mode Exit fullscreen mode

Where:

  • f* = fraction of bankroll to bet
  • b = net odds (how much you win per $1 wagered)
  • p = your estimated probability of winning
  • q = probability of losing (1 - p)

In prediction market terms, if Polymarket shows a contract at 40¢ (implying 40% probability), but your model says the true probability is 55%, then:

b = (1 - 0.40) / 0.40 = 1.5   (you risk 40¢ to win 60¢)
p = 0.55
q = 0.45

f* = (1.5 × 0.55 - 0.45) / 1.5
f* = (0.825 - 0.45) / 1.5
f* = 0.375 / 1.5
f* = 0.25
Enter fullscreen mode Exit fullscreen mode

Kelly says: bet 25% of your bankroll on this trade.

In JavaScript:

function kelly(marketProb, myProb) {
  const b = (1 - marketProb) / marketProb; // net odds
  const p = myProb;
  const q = 1 - p;
  const f = (b * p - q) / b;
  return Math.max(0, f); // never bet negative (no edge = no bet)
}

// Example: market at 40%, your model says 55%
const fraction = kelly(0.40, 0.55);
console.log(`Bet ${(fraction * 100).toFixed(1)}% of bankroll`); // 25.0%
Enter fullscreen mode Exit fullscreen mode

Full Kelly vs Fractional Kelly

Here's the thing about Full Kelly: it's mathematically optimal but practically brutal.

Full Kelly maximises the long-run growth rate of your bankroll. But it assumes your probability estimates are perfectly accurate. In reality, your model is wrong sometimes. Maybe your edge is smaller than you think. Maybe the market knows something you don't.

Full Kelly also produces wild variance. Your bankroll can drop 30–40% even when you're playing correctly - and for a bot running 24/7, that kind of drawdown is psychologically (and sometimes financially) devastating.

Half Kelly

Most practitioners use Half Kelly - simply halving the output:

function halfKelly(marketProb, myProb) {
  return kelly(marketProb, myProb) * 0.5;
}
Enter fullscreen mode Exit fullscreen mode

Half Kelly gives you roughly 75% of the growth rate of Full Kelly, but with dramatically less variance. The drawdowns are about half as deep.

Fractional Kelly in my bot

I actually use a variable fraction based on my model confidence:

function fractionalKelly(marketProb, myProb, confidence) {
  // confidence: 0.0 (low) to 1.0 (high)
  // Scales between quarter Kelly and full Kelly
  const fraction = 0.25 + (confidence * 0.75);
  return kelly(marketProb, myProb) * fraction;
}
Enter fullscreen mode Exit fullscreen mode

When my model has a strong, well-evidenced signal, I scale toward Full Kelly. When it's a weaker or noisier signal, I scale back toward Quarter Kelly. This way, sizing reflects not just edge size but confidence in the edge.


How It Changed My Bot's Performance

Before Kelly, I was flat-betting - putting the same fixed amount on every trade regardless of edge. This seems "safe" but it's actually suboptimal in both directions:

  • Overbetting weak edges → unnecessary variance, occasional blowups
  • Underbetting strong edges → leaving money on the table

Here's what changed after switching to Fractional Kelly:

Metric Before Kelly After Kelly
Weekly variance High Moderate
Max drawdown ~28% ~12%
Return per trade Similar Similar
Overall growth Inconsistent Smoother compounding

The individual trade returns didn't change much - my model was the same. But the compounding improved significantly. Kelly sizing means your bankroll grows faster during hot streaks and protects capital during cold ones automatically, without any manual intervention.

The biggest mindset shift: Kelly isn't about winning more. It's about not blowing up your edge by sizing wrong.


A Few Gotchas I Learned the Hard Way

1. Your probability estimates are almost certainly overconfident.
If your model says 70% but the true probability is 58%, Kelly will tell you to bet more than you should. Always sanity-check your edge estimates against your actual historical win rate.

2. Kelly ignores liquidity.
On Polymarket, large positions move the market against you. Even if Kelly says 30%, you might only be able to fill 5–8% without impacting your own odds. I cap positions at a liquidity-adjusted maximum regardless of Kelly output.

3. Multiple simultaneous bets.
If your bot runs several trades at once, you can't just apply Kelly independently to each - you'd be collectively overbetting. Look into simultaneous Kelly or simply divide your effective bankroll by the number of concurrent positions.

4. Never bet on negative Kelly.
If f* comes out negative, Kelly is telling you: this bet has no edge for you. Pass. The formula is a filter as much as a sizer.


Wrapping Up

The Kelly Criterion didn't make my bot smarter. It made it more disciplined. That distinction matters more than I expected.

If you're building a prediction market bot and you're flat-betting or gut-sizing, this is probably the single highest-leverage improvement you can make - without touching your signal at all.

Try Half Kelly first. Watch your drawdowns shrink. Then tune from there.


Building on Polymarket or have questions about bot sizing? Drop a comment - happy to compare notes.

Top comments (0)