Build a custom OpenClaw skill that tells your agent exactly how much to bet. One SKILL.md file, zero dependencies beyond Python 3, and your agent can size positions using Kelly Criterion — the same formula used by professional bettors and hedge funds.

Why Your Agent Needs a Kelly Sizer

Finding a +EV bet is only half the problem. The other half — the half most bettors ignore — is knowing how much to stake.

Bet too much and a losing streak wipes you out. Bet too little and you leave growth on the table. Kelly Criterion solves this mathematically: it calculates the exact fraction of your bankroll that maximizes long-term growth given your edge and the offered odds.

Most betting agents skip position sizing entirely. They find a good line, bet a flat unit, and hope for the best. That’s leaving money on the table. A properly sized Kelly bet compounds edge over hundreds of wagers, and the difference between flat betting and Kelly betting over 1,000 bets is often the difference between a 10% return and a 40% return.

This guide builds kelly-sizer — a Layer 4 (Intelligence) skill that handles the position-sizing step of the Agent Betting Stack. It takes odds from odds-scanner and your edge estimate, then outputs the mathematically optimal stake.

What You’re Building

The kelly-sizer skill teaches your OpenClaw agent four operations:

  1. Single bet Kelly — Optimal stake for one bet given bankroll, odds, and true probability
  2. Fractional Kelly — Conservative variants (quarter, half, three-quarter Kelly) for lower variance
  3. Multi-bet Kelly — Simultaneous position sizing across multiple bets with exposure limits
  4. Max-bet enforcement — Hard caps on single-bet and total-exposure percentages

The skill uses inline Python 3 math — no pip packages, no API keys, no network calls. It runs entirely locally.

Prerequisites

  • OpenClaw installed and running — Any channel (WhatsApp, Telegram, Discord, WebChat)
  • Python 3 — Pre-installed on macOS and most Linux distributions
  • Basic probability understanding — You need to estimate the true probability of outcomes (the skill does the rest)

The Math Behind Kelly Criterion

The Kelly formula calculates the optimal fraction of your bankroll to wager:

f* = (bp - q) / b

Where:

  • f* = fraction of bankroll to bet
  • b = net decimal odds (decimal odds minus 1). For American odds: positive = odds/100, negative = 100/|odds|
  • p = your estimated true probability of winning
  • q = probability of losing (1 - p)

Example: Lakers at +150, you estimate 45% win probability.

  • b = 150/100 = 1.5
  • p = 0.45, q = 0.55
  • f* = (1.5 × 0.45 − 0.55) / 1.5 = (0.675 − 0.55) / 1.5 = 0.0833

Kelly says bet 8.33% of your bankroll. On a $1,000 bankroll, that’s $83.30.

Why fractional Kelly? Full Kelly maximizes growth rate but produces stomach-churning drawdowns. The standard deviation of your bankroll is proportional to the Kelly fraction. Half Kelly gives you 75% of the growth rate at 50% of the volatility. Most professionals use quarter to half Kelly.

VariantMultiplierGrowth RateDrawdown Risk
Quarter Kelly0.25~44% of fullVery low
Half Kelly0.50~75% of fullModerate
Three-quarter Kelly0.75~94% of fullHigh
Full Kelly1.00MaximumVery high

The Complete SKILL.md

Create the skill directory:

mkdir -p ~/.openclaw/skills/kelly-sizer

Create ~/.openclaw/skills/kelly-sizer/SKILL.md with this content:

---
name: kelly-sizer
description: "Calculate optimal bet sizes using Kelly Criterion. Supports single bets, fractional Kelly (quarter/half/three-quarter), multi-bet portfolio sizing, and max-bet enforcement. Use when asked about bet sizing, how much to bet, position sizing, Kelly Criterion, or bankroll allocation."
metadata:
  openclaw:
    emoji: "🎯"
    requires:
      bins: ["python3"]
---

# Kelly Criterion Bet Sizer

Calculate mathematically optimal bet sizes based on your edge and bankroll.

# When to Use

Use this skill when the user asks about:
- How much to bet on a specific wager
- Kelly Criterion or optimal bet sizing
- Position sizing for a bet with known edge
- Fractional Kelly or conservative bet sizing
- Sizing multiple simultaneous bets
- Maximum bet limits or bankroll allocation

# Odds Conversion Reference

Before computing Kelly, convert all odds to decimal probability format:

| Format | Example | To Decimal Odds | To Implied Prob |
|--------|---------|-----------------|-----------------|
| American (+) | +150 | 1 + odds/100 = 2.50 | 100/(odds+100) |
| American (-) | -200 | 1 + 100/|odds| = 1.50 | |odds|/(|odds|+100) |
| Decimal | 2.50 | Already decimal | 1/decimal |
| Probability | 40% | 1/prob | Already prob |

# Operations

### 1. Single Bet — Full Kelly

Calculate the optimal Kelly stake for a single bet. User must provide: bankroll, odds (any format), and their estimated true probability.

```bash
python3 -c "
import sys
bankroll = float(sys.argv[1])
odds_input = sys.argv[2]
true_prob = float(sys.argv[3])

## Convert odds to decimal
if odds_input.startswith('+'):
    decimal_odds = 1 + int(odds_input[1:]) / 100
elif odds_input.startswith('-'):
    decimal_odds = 1 + 100 / abs(int(odds_input[1:]))
else:
    decimal_odds = float(odds_input)

b = decimal_odds - 1  # net odds
p = true_prob
q = 1 - p

## Kelly fraction
kelly_f = (b * p - q) / b if b > 0 else 0
kelly_f = max(kelly_f, 0)  # never negative

implied_prob = 1 / decimal_odds
edge = true_prob - implied_prob

print(f'Odds: {odds_input} (decimal: {decimal_odds:.4f})')
print(f'Implied prob: {implied_prob:.2%} | Your estimate: {true_prob:.2%} | Edge: {edge:.2%}')
print(f'Kelly fraction: {kelly_f:.4f} ({kelly_f:.2%} of bankroll)')
print(f'Recommended stake: \${kelly_f * bankroll:.2f} of \${bankroll:.2f} bankroll')
if kelly_f <= 0:
    print('⚠️  No edge detected — Kelly says do not bet')
elif kelly_f > 0.10:
    print('⚠️  Kelly > 10% — consider fractional Kelly to reduce variance')
" BANKROLL ODDS TRUE_PROB

Replace BANKROLL with the dollar amount, ODDS with American (+150, -200) or decimal (2.50), and TRUE_PROB with the estimated probability as a decimal (0.45 for 45%).

2. Fractional Kelly — Conservative Sizing

Calculate quarter, half, and three-quarter Kelly for reduced variance:

python3 -c "
import sys
bankroll = float(sys.argv[1])
odds_input = sys.argv[2]
true_prob = float(sys.argv[3])

if odds_input.startswith('+'):
    decimal_odds = 1 + int(odds_input[1:]) / 100
elif odds_input.startswith('-'):
    decimal_odds = 1 + 100 / abs(int(odds_input[1:]))
else:
    decimal_odds = float(odds_input)

b = decimal_odds - 1
p = true_prob
q = 1 - p
kelly_f = max((b * p - q) / b, 0) if b > 0 else 0

print(f'Odds: {odds_input} | True prob: {true_prob:.2%} | Full Kelly: {kelly_f:.4f}')
print(f'')
print(f'| Variant         | Fraction | Stake        | % of Bankroll |')
print(f'|-----------------|----------|--------------|---------------|')
for label, mult in [('Quarter Kelly', 0.25), ('Half Kelly', 0.50), ('Three-Quarter', 0.75), ('Full Kelly', 1.00)]:
    f = kelly_f * mult
    stake = f * bankroll
    print(f'| {label:<15} | {f:.4f}   | \${stake:>10.2f} | {f:>12.2%} |')
print(f'')
if kelly_f <= 0:
    print('⚠️  No edge — Kelly says pass on this bet')
else:
    half_stake = kelly_f * 0.5 * bankroll
    print(f'💡 Recommended: Half Kelly = \${half_stake:.2f} (best risk/reward tradeoff)')
" BANKROLL ODDS TRUE_PROB

3. Multi-Bet Kelly — Portfolio Sizing

Size multiple simultaneous bets with total exposure limits. Pass bets as a semicolon-separated list of odds:prob pairs:

python3 -c "
import sys
bankroll = float(sys.argv[1])
max_exposure = float(sys.argv[2])  # max % of bankroll across all bets
kelly_mult = float(sys.argv[3])    # fractional kelly multiplier
bets_raw = sys.argv[4]             # 'label,odds,prob;label,odds,prob;...'

bets = []
for entry in bets_raw.split(';'):
    parts = entry.strip().split(',')
    label = parts[0].strip()
    odds_input = parts[1].strip()
    true_prob = float(parts[2].strip())

    if odds_input.startswith('+'):
        decimal_odds = 1 + int(odds_input[1:]) / 100
    elif odds_input.startswith('-'):
        decimal_odds = 1 + 100 / abs(int(odds_input[1:]))
    else:
        decimal_odds = float(odds_input)

    b = decimal_odds - 1
    q = 1 - true_prob
    kelly_f = max((b * true_prob - q) / b, 0) if b > 0 else 0
    adj_f = kelly_f * kelly_mult
    bets.append((label, odds_input, decimal_odds, true_prob, kelly_f, adj_f))

total_f = sum(b[5] for b in bets)
needs_scaling = total_f > max_exposure

if needs_scaling:
    scale = max_exposure / total_f
else:
    scale = 1.0

print(f'Bankroll: \${bankroll:.2f} | Kelly mult: {kelly_mult} | Max exposure: {max_exposure:.0%}')
print(f'')
print(f'| Bet              | Odds   | True P  | Kelly  | Adj Kelly | Stake      |')
print(f'|------------------|--------|---------|--------|-----------|------------|')
for label, odds_str, dec, tp, kf, af in bets:
    final_f = af * scale
    stake = final_f * bankroll
    print(f'| {label:<16} | {odds_str:>6} | {tp:>6.1%} | {kf:.4f} | {final_f:.4f}    | \${stake:>8.2f} |')
final_total = total_f * scale
total_stake = final_total * bankroll
print(f'|------------------|--------|---------|--------|-----------|------------|')
print(f'| TOTAL            |        |         |        | {final_total:.4f}    | \${total_stake:>8.2f} |')
print(f'')
if needs_scaling:
    print(f'⚠️  Exposure scaled down from {total_f:.2%} to {max_exposure:.0%} cap')
print(f'Remaining bankroll: \${bankroll - total_stake:.2f} ({(1-final_total):.1%})')
" BANKROLL MAX_EXPOSURE KELLY_MULT "LABEL1,ODDS1,PROB1;LABEL2,ODDS2,PROB2"

Replace BANKROLL with your bankroll, MAX_EXPOSURE with max total allocation as decimal (0.20 for 20%), KELLY_MULT with fractional Kelly multiplier (0.5 for half Kelly), and the quoted bet string with semicolon-separated entries.

4. Max-Bet Enforcement Check

Validate a proposed bet against bankroll limits:

python3 -c "
import sys
bankroll = float(sys.argv[1])
proposed_stake = float(sys.argv[2])
max_single_pct = float(sys.argv[3])  # e.g., 0.05 for 5%
max_daily_pct = float(sys.argv[4])   # e.g., 0.15 for 15%
already_wagered = float(sys.argv[5]) # today's total wagers

max_single = bankroll * max_single_pct
max_daily = bankroll * max_daily_pct
remaining_daily = max_daily - already_wagered

approved = proposed_stake <= max_single and proposed_stake <= remaining_daily
final_stake = min(proposed_stake, max_single, remaining_daily)

print(f'Bankroll: \${bankroll:.2f}')
print(f'Proposed stake: \${proposed_stake:.2f} ({proposed_stake/bankroll:.1%} of bankroll)')
print(f'Max single bet: \${max_single:.2f} ({max_single_pct:.0%})')
print(f'Daily limit: \${max_daily:.2f} ({max_daily_pct:.0%}) | Used: \${already_wagered:.2f} | Remaining: \${remaining_daily:.2f}')
print(f'')
if approved:
    print(f'✅ APPROVED: \${proposed_stake:.2f}')
else:
    print(f'🚫 REDUCED: \${proposed_stake:.2f} → \${max(final_stake,0):.2f}')
    if proposed_stake > max_single:
        print(f'   Reason: Exceeds single-bet limit of \${max_single:.2f}')
    if proposed_stake > remaining_daily:
        print(f'   Reason: Exceeds remaining daily limit of \${remaining_daily:.2f}')
" BANKROLL PROPOSED_STAKE MAX_SINGLE_PCT MAX_DAILY_PCT ALREADY_WAGERED

Replace BANKROLL, PROPOSED_STAKE, MAX_SINGLE_PCT (0.05 for 5%), MAX_DAILY_PCT (0.15 for 15%), and ALREADY_WAGERED with today’s total wagered amount.

Output Rules

  1. Always show the Kelly fraction as both a decimal and a percentage
  2. Always show the dollar stake alongside the fraction
  3. For fractional Kelly, default to recommending half Kelly unless the user specifies otherwise
  4. When Kelly fraction is negative or zero, explicitly say “no edge — do not bet”
  5. When Kelly fraction exceeds 10%, warn about high variance and suggest fractional Kelly
  6. For multi-bet operations, always show total exposure and remaining bankroll
  7. All monetary amounts use two decimal places

Error Handling

  • If the user provides no bankroll amount, ask for it before computing
  • If the user provides no probability estimate, explain that Kelly requires a true probability estimate and cannot work from odds alone
  • If the computed Kelly fraction is negative, the bet has negative expected value — advise against betting
  • If Python 3 is not available, report the error and suggest installing Python

## Test It

Restart OpenClaw (or wait for hot-reload if your version supports it), then try these prompts:

| Prompt                                                                                                          | Expected Behavior                                                           |
| --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| "I have $5000 and want to bet on the Celtics at -150. I think they win 70% of the time. How much should I bet?" | Computes full Kelly and fractional variants, recommends half Kelly          |
| "Kelly criterion for +200 odds, 40% true probability, $2000 bankroll"                                           | Shows full Kelly = 10% of bankroll, flags as high and recommends fractional |
| "Size these bets: Lakers +150 at 45%, Celtics -130 at 60%, Nuggets +200 at 38%. Bankroll $10,000"               | Multi-bet Kelly table with exposure limits                                  |
| "Should I bet $500 on this game? My bankroll is $3000"                                                          | Max-bet enforcement check against default 5% single-bet limit               |
| "What's the difference between half Kelly and full Kelly?"                                                      | Explains growth rate vs variance tradeoff with the fractional Kelly table   |

Your agent reads the SKILL.md, identifies the relevant operation, plugs in your numbers, and runs the Python calculation.

## How It Works Under the Hood

OpenClaw skills are not plugins that execute code directly. The SKILL.md is a set of instructions that the LLM (Claude, GPT, etc.) reads and follows at runtime.

When you ask "how much should I bet on the Lakers at +150," this is what happens:

User message → OpenClaw Gateway → LLM reads system prompt + active skills → LLM matches “how much to bet” to kelly-sizer skill → LLM extracts bankroll, odds, and probability from context → LLM generates python3 -c command with substituted values → OpenClaw executes command via shell tool → Python outputs Kelly fraction and stake amount → LLM formats output for user with recommendation


The kelly-sizer skill uses explicit operations, exact Python commands, and strict output rules to minimize agent improvisation. The math is deterministic — given the same inputs, you always get the same Kelly fraction.

## Extending the Skill

### Add Cron-Based Portfolio Rebalancing

OpenClaw supports cron jobs. Add a scheduled task that recalculates Kelly stakes as your bankroll changes:

```json
{
  "cron": "0 9 * * *",
  "prompt": "My bankroll is now $X (check bankroll-manager for current balance). Recalculate Kelly stakes for all open position targets using half Kelly."
}

This ensures your position sizes stay proportional to your current bankroll — scaling up after wins and scaling down after losses, which is exactly how Kelly is designed to work.

Chain with Other Skills

The kelly-sizer consumes data from upstream skills and informs downstream decisions:

  • odds-scanner → Provides the best available odds that kelly-sizer uses as input
  • ev-calculator → Validates that a bet is +EV before kelly-sizer determines the stake
  • vig-calculator → Helps estimate true probability by removing vig from market odds
  • bankroll-manager → Tracks the current bankroll that kelly-sizer sizes against
  • clv-tracker → Logs whether Kelly-sized bets outperform flat-unit bets over time

This is the power of the Agent Betting Stack — composable skills where each layer feeds the next.

Full Skill Series

This guide is part of the AgentBets OpenClaw Skills series. We’re building a complete library of betting-specific OpenClaw skills that map to the four layers of the Agent Betting Stack:

  • Layer 1 — Identity: Agent reputation tracking via Moltbook
  • Layer 2 — Wallet: Bankroll management, balance checking across platforms
  • Layer 3 — Trading: Odds scanning, Polymarket monitoring, Kalshi tracking, arbitrage detection
  • Layer 4 — Intelligence: EV calculation, Kelly sizing (this guide), CLV tracking, news sentiment

Each skill is a standalone SKILL.md you can install independently or compose into a full autonomous betting pipeline.

What’s Next