Kelly Criterion
Optimal bet size given win odds and payoff.
Kelly tells you how much of your money to risk per trade so it grows fastest without ever hitting zero. The math takes your win odds and your win/loss size and gives back the optimal bet fraction. Most pros use half-Kelly because full Kelly accepts giant drawdowns.
Kelly tells you how much of your bankroll to risk per trade so it grows fastest without ever hitting zero. The math is rigorous: f* = (p·b − q) / b, where p is your win probability, q is loss probability, b is win/loss ratio. Half-Kelly (0.5×) gives 75% of the growth with way less stomach-turn — that's what most pros actually use.
f* = (p·b − q) / b where q = 1−p, b = win$/loss$
Real Kelly Criterion bot, running on real Yahoo data when the symbol is available. Drag the params — the bot re-runs instantly.
This is the actual code the bot runs — not a re-explanation, not a simplified version. Whatever ships here is what executes when you press Run All in the workbench. Read it, copy it, fork it, build a better one.
const kellyBot: BotDef = {
id: "kelly",
name: "Kelly Criterion",
category: "risk",
glyph: "$",
tagline: "Optimal bet size given win odds and payoff.",
formula: "f* = (p·b − q) / b where q = 1−p, b = win$/loss$",
params: [
{ key: "winProb", label: "Win probability %", kind: "number", default: 55, min: 10, max: 90, step: 1 },
{ key: "winAmt", label: "Avg win $", kind: "number", default: 200, min: 10, max: 5000, step: 10 },
{ key: "lossAmt", label: "Avg loss $", kind: "number", default: 150, min: 10, max: 5000, step: 10 },
{ key: "bankroll", label: "Bankroll $", kind: "number", default: 100000, min: 100, max: 10000000, step: 100 },
{ key: "fraction", label: "Kelly fraction", kind: "number", default: 0.5, min: 0.1, max: 1, step: 0.05, hint: "use 0.25–0.5 in real life" },
],
run: (_ctx, p): BotResult => {
const pw = num(p, "winProb", 55) / 100;
const w = num(p, "winAmt", 200);
const l = num(p, "lossAmt", 150);
const bk = num(p, "bankroll", 100000);
const frac = num(p, "fraction", 0.5);
const b = w / l;
const fStar = Math.max(0, (pw * b - (1 - pw)) / b);
const fUse = fStar * frac;
const sizeRaw = bk * fStar;
const sizeUsed = bk * fUse;
const ev = pw * w - (1 - pw) * l;
return {
signals: [],
metrics: [
{ key: "f", label: "f* full", value: `${(fStar * 100).toFixed(1)}%`, tone: fStar > 0 ? "bull" : "bear" },
{ key: "f-use", label: `f used (${frac}×)`, value: `${(fUse * 100).toFixed(1)}%`, tone: "neutral" },
{ key: "size", label: "Bet size", value: fmtMoney(sizeUsed), tone: "info" },
{ key: "ev", label: "EV / trade", value: fmtMoney(ev), tone: ev > 0 ? "bull" : "bear" },
],
summary: `Full Kelly = ${(fStar * 100).toFixed(1)}%. Using ${(fUse * 100).toFixed(1)}% → bet ${fmtMoney(sizeUsed)} on a ${fmtMoney(bk)} stack.`,
beginner:
"Kelly tells you how much of your bankroll to risk per trade so it grows fastest without ever hitting zero. Half-Kelly (0.5×) gives 75% of the growth with way less stomach-turn — that's what most pros actually use.",
verdict: {
side: fStar > 0 ? "buy" : "warn",
text: fStar > 0 ? `Edge exists. Bet up to ${(fUse * 100).toFixed(1)}% per shot.` : "No edge — don't bet.",
confidence: Math.min(1, fStar * 4),
},
};
},
};id— unique key the workbench uses to find the bot.params— the sliders + inputs you see on the cell.run(ctx, p)— the function that gets called with candles + your params and returns the verdict.verdict— the BUY / SELL / HOLD pill at the top of the cell.metrics— the small stat boxes shown in the cell body.
- Copy the whole block above.
- On /quant, click + Import your bot in the bot library.
- Paste, hit save. It hot-loads into your workspace.
- Edit any param defaults or logic to your taste — it's now yours.
- ·Long-horizon compounding. Kelly's optimality is asymptotic — over many trades, full Kelly maximises geometric growth.
- ·Sizing high-conviction setups. When the AI Consensus says ULTRA, plug those probabilities into Kelly for sizing.
- ·Sanity checking gut sizing. Most retail traders over-size; Kelly's number tells you what's actually optimal vs what feels right.
- ·Probability mis-estimation. Kelly is wildly sensitive to the win-probability input — overstating p by 10% can double your recommended size.
- ·Non-stationary edges. The classic Kelly formula assumes stable p and b; real edges decay.
- ·Drawdown-averse traders. Full Kelly accepts ~50% drawdowns as optimal. Most humans don't.
BUY when f* > 0 (positive edge exists). WARN when f* ≤ 0 (no edge — don't bet). Confidence scales with the magnitude of the edge. The bet-size dollar value is computed against your declared bankroll. Real practitioners use ¼ to ½ Kelly to dampen the drawdowns.