Build a custom OpenClaw skill that tells your agent whether a bet is worth taking. One SKILL.md file, zero dependencies beyond Python 3, and your agent can calculate expected value for any bet — the single most important number in sharp betting.
Why Your Agent Needs an EV Calculator
Every bet has an expected value. Most bettors never calculate it.
Expected value is the single number that separates sharp bettors from recreational ones. It answers the only question that matters: given the odds the sportsbook is offering and my estimate of the true probability, will this bet make money over time?
A bet at +150 looks attractive until you realize the true probability is only 35% — that’s a -EV bet the sportsbook designed to look good. Conversely, a -200 favorite that actually wins 72% of the time is solidly +EV despite the ugly price. Your intuition about odds is unreliable. Math isn’t.
This guide builds ev-calculator — a Layer 4 (Intelligence) skill that handles the bet evaluation step of the Agent Betting Stack. It takes odds from odds-scanner, applies your probability estimate, and outputs a clear +EV or -EV verdict with the exact expected profit per dollar.
What You’re Building
The ev-calculator skill teaches your OpenClaw agent four operations:
- Single bet EV — Expected value for one bet given odds and true probability
- Batch EV analysis — Evaluate multiple bets at once, sorted by EV per dollar
- Breakeven probability — The minimum true probability needed to make a bet +EV at given odds
- +EV opportunity flagging — Compare market-implied probability vs your estimate and flag edges
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
- An opinion on true probabilities — EV calculation requires your edge estimate (the skill does the math, you supply the conviction)
The Math Behind Expected Value
Expected value measures average profit per bet over the long run:
EV = (p × profit) - (q × stake)
Where:
- p = your estimated true probability of winning
- q = probability of losing (1 - p)
- profit = what you gain if you win (at decimal odds d, profit = stake × (d - 1))
- stake = amount wagered (usually normalized to $1 for comparison)
For a $1 bet at decimal odds d with true win probability p:
EV = p × (d - 1) - (1 - p) × 1
EV = p × d - 1
Example: Lakers at +150, you estimate 45% win probability.
- Decimal odds: 2.50 (American +150 → 1 + 150/100)
- EV per $1 = 0.45 × 2.50 - 1 = 1.125 - 1 = +$0.125
That’s 12.5 cents profit per dollar wagered over the long run. This bet is +EV — you should take it.
Example: Chiefs at -200, you estimate 62% win probability.
- Decimal odds: 1.50 (American -200 → 1 + 100/200)
- EV per $1 = 0.62 × 1.50 - 1 = 0.93 - 1 = -$0.07
That’s 7 cents lost per dollar wagered. Even though you think the Chiefs probably win, the price is too steep. This is -EV at your probability estimate.
Breakeven probability — the implied probability where EV = 0:
p_breakeven = 1 / decimal_odds
At +150 (decimal 2.50), breakeven is 1/2.50 = 40%. If you think the true probability exceeds 40%, the bet is +EV. The gap between your estimate and the breakeven probability is your edge.
| Odds | Decimal | Breakeven Prob | Your Estimate | EV per $1 | Verdict |
|---|---|---|---|---|---|
| +150 | 2.50 | 40.0% | 45% | +$0.125 | +EV |
| -200 | 1.50 | 66.7% | 62% | -$0.070 | -EV |
| +300 | 4.00 | 25.0% | 30% | +$0.200 | +EV |
| -110 | 1.909 | 52.4% | 55% | +$0.050 | +EV |
| EVEN | 2.00 | 50.0% | 48% | -$0.040 | -EV |
The Complete SKILL.md
Create the skill directory:
mkdir -p ~/.openclaw/skills/ev-calculator
Create ~/.openclaw/skills/ev-calculator/SKILL.md with this content:
---
name: ev-calculator
description: "Calculate expected value for any sports bet or prediction market position. Supports American odds, decimal odds, implied probability, and Kalshi contract prices. Use when asked about expected value, EV, whether a bet is worth it, +EV opportunities, or breakeven probability."
metadata:
openclaw:
emoji: "📈"
requires:
bins: ["python3"]
---
# Expected Value Calculator
Calculate the expected value of any bet given offered odds and your estimated true probability.
# When to Use
Use this skill when the user asks about:
- Expected value of a bet
- Whether a bet is +EV or -EV
- Is this bet worth taking at these odds
- Breakeven probability for given odds
- Comparing EV across multiple bets
- Finding the best value bets on a slate
- How much edge they have on a line
# Odds Conversion Reference
Before computing EV, convert all inputs to decimal odds:
| Format | Example | To Decimal Odds |
|--------|---------|-----------------|
| American (+) | +150 | 1 + odds/100 = 2.50 |
| American (-) | -200 | 1 + 100/|odds| = 1.50 |
| Decimal | 2.50 | Already decimal |
| Implied Prob | 40% | 1/prob = 2.50 |
| Kalshi price | $0.40 | 1/price = 2.50 |
# Operations
### 1. Single Bet EV
Calculate expected value for one bet. User must provide: odds (any format) and their estimated true probability.
```bash
python3 -c "
import sys
odds_input = sys.argv[1]
true_prob = float(sys.argv[2]) / 100 if float(sys.argv[2]) > 1 else float(sys.argv[2])
## Convert to decimal odds
if odds_input.startswith('+'):
decimal_odds = 1 + int(odds_input) / 100
elif odds_input.startswith('-'):
decimal_odds = 1 + 100 / abs(int(odds_input))
elif odds_input.startswith('$') or odds_input.startswith('0.'):
price = float(odds_input.replace('$', ''))
decimal_odds = 1 / price
else:
decimal_odds = float(odds_input)
implied_prob = 1 / decimal_odds
ev_per_dollar = true_prob * decimal_odds - 1
edge = true_prob - implied_prob
print(f'Offered odds: {odds_input} (decimal {decimal_odds:.3f})')
print(f'Implied probability: {implied_prob:.1%}')
print(f'Your true probability: {true_prob:.1%}')
print(f'Edge: {edge:+.1%}')
print(f'EV per \$1: {ev_per_dollar:+.4f}')
print(f'EV per \$100: {ev_per_dollar * 100:+.2f}')
print(f'Verdict: {\"✅ +EV — BET\" if ev_per_dollar > 0 else \"❌ -EV — PASS\"} ')
" "ODDS" "TRUE_PROB_PERCENT"
Replace ODDS with the offered odds (e.g., +150, -200, 2.50, $0.40) and TRUE_PROB_PERCENT with the user’s probability estimate as a percentage (e.g., 45 for 45%).
2. Batch EV Analysis
Evaluate multiple bets at once. Takes a list of bets as pipe-separated values: name|odds|true_prob_percent.
python3 -c "
import sys
bets_raw = sys.argv[1:]
results = []
for bet in bets_raw:
parts = bet.split('|')
name = parts[0]
odds_input = parts[1]
true_prob = float(parts[2]) / 100 if float(parts[2]) > 1 else float(parts[2])
if odds_input.startswith('+'):
decimal_odds = 1 + int(odds_input) / 100
elif odds_input.startswith('-'):
decimal_odds = 1 + 100 / abs(int(odds_input))
elif odds_input.startswith('$') or odds_input.startswith('0.'):
price = float(odds_input.replace('$', ''))
decimal_odds = 1 / price
else:
decimal_odds = float(odds_input)
implied_prob = 1 / decimal_odds
ev_per_dollar = true_prob * decimal_odds - 1
edge = true_prob - implied_prob
results.append((name, odds_input, decimal_odds, implied_prob, true_prob, edge, ev_per_dollar))
results.sort(key=lambda x: -x[6])
print(f'{\"Bet\":<25} {\"Odds\":<8} {\"Impl%\":<7} {\"True%\":<7} {\"Edge\":<7} {\"EV/\$1\":<9} {\"Verdict\"}')
print('-' * 80)
for name, odds, dec, impl, true_p, edge, ev in results:
verdict = '+EV' if ev > 0 else '-EV'
marker = '>>>' if ev > 0 else ' '
print(f'{marker} {name:<22} {odds:<8} {impl:<7.1%} {true_p:<7.1%} {edge:<+7.1%} {ev:<+9.4f} {verdict}')
plus_ev = [r for r in results if r[6] > 0]
print(f'\n+EV bets found: {len(plus_ev)} of {len(results)}')
if plus_ev:
total_ev = sum(r[6] for r in plus_ev)
print(f'Combined EV per \$1 staked equally: {total_ev / len(plus_ev):+.4f}')
" "NAME1|ODDS1|PROB1" "NAME2|ODDS2|PROB2" "NAME3|ODDS3|PROB3"
Replace each argument with a pipe-separated bet entry. Add or remove entries as needed.
3. Breakeven Probability Finder
Calculate the minimum true probability needed to make a bet +EV at given odds.
python3 -c "
import sys
odds_input = sys.argv[1]
if odds_input.startswith('+'):
decimal_odds = 1 + int(odds_input) / 100
elif odds_input.startswith('-'):
decimal_odds = 1 + 100 / abs(int(odds_input))
elif odds_input.startswith('$') or odds_input.startswith('0.'):
price = float(odds_input.replace('$', ''))
decimal_odds = 1 / price
else:
decimal_odds = float(odds_input)
breakeven = 1 / decimal_odds
print(f'Odds: {odds_input} (decimal {decimal_odds:.3f})')
print(f'Breakeven probability: {breakeven:.1%}')
print(f'You need to believe the true probability is ABOVE {breakeven:.1%} for this bet to be +EV')
print()
print('EV at various true probabilities:')
for offset in [-5, -2, 0, 2, 5, 10]:
p = breakeven + offset / 100
if 0 < p < 1:
ev = p * decimal_odds - 1
label = ' ← breakeven' if offset == 0 else ''
print(f' {p:.1%}: EV = {ev:+.4f} per \$1{label}')
" "ODDS"
Replace ODDS with the offered odds in any format.
4. +EV Opportunity Flagger
Compare market-implied probabilities against your estimates. Input: pipe-separated values name|odds|your_prob. Flags any bet where your edge exceeds a threshold (default 2%).
python3 -c "
import sys
threshold = float(sys.argv[1]) / 100
bets_raw = sys.argv[2:]
opportunities = []
for bet in bets_raw:
parts = bet.split('|')
name = parts[0]
odds_input = parts[1]
true_prob = float(parts[2]) / 100 if float(parts[2]) > 1 else float(parts[2])
if odds_input.startswith('+'):
decimal_odds = 1 + int(odds_input) / 100
elif odds_input.startswith('-'):
decimal_odds = 1 + 100 / abs(int(odds_input))
elif odds_input.startswith('$') or odds_input.startswith('0.'):
price = float(odds_input.replace('$', ''))
decimal_odds = 1 / price
else:
decimal_odds = float(odds_input)
implied_prob = 1 / decimal_odds
ev_per_dollar = true_prob * decimal_odds - 1
edge = true_prob - implied_prob
if edge >= threshold:
opportunities.append((name, odds_input, decimal_odds, implied_prob, true_prob, edge, ev_per_dollar))
if opportunities:
opportunities.sort(key=lambda x: -x[6])
print(f'🔥 {len(opportunities)} +EV OPPORTUNITIES (edge >= {threshold:.0%})')
print('=' * 75)
for name, odds, dec, impl, true_p, edge, ev in opportunities:
print(f' {name}')
print(f' Odds: {odds} | Implied: {impl:.1%} | Your prob: {true_p:.1%} | Edge: {edge:+.1%} | EV/\$1: {ev:+.4f}')
else:
print(f'No +EV opportunities found with edge >= {threshold:.0%}')
print('Consider lowering the threshold or re-evaluating your probability estimates.')
" "THRESHOLD_PERCENT" "NAME1|ODDS1|PROB1" "NAME2|ODDS2|PROB2"
Replace THRESHOLD_PERCENT with the minimum edge percentage to flag (e.g., 2 for 2%). Replace each subsequent argument with a bet entry.
Output Rules
- Always show the offered odds in the original format AND decimal
- Always show implied probability vs the user’s true probability estimate
- Show edge as a percentage (true prob minus implied prob)
- Show EV per $1 wagered to 4 decimal places
- For batch mode, sort results by EV per $1 descending with +EV bets marked
- Always include a clear verdict: +EV (bet) or -EV (pass)
- If the user provides no true probability estimate, compute and display the breakeven probability instead
Error Handling
- If no true probability is provided, default to the breakeven probability operation and ask the user for their estimate
- If odds format is unrecognized, ask the user to specify as American (+150/-200), decimal (2.50), or implied probability (40%)
- If true probability is outside 0-100%, flag the input as invalid
- If true probability equals the implied probability exactly, report EV as zero and note the bet has no edge
## Test It
Restart OpenClaw (or wait for hot-reload if your version supports it), then try these prompts:
| Prompt | Expected Behavior |
| -------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| "Is a +150 bet worth it if I think the true probability is 45%?" | Calculates EV per $1, shows +$0.125, verdict: +EV |
| "What's the breakeven probability at -110?" | Shows 52.4%, explains you need to believe >52.4% to have edge |
| "Calculate EV for these bets: Lakers +150 at 45%, Celtics -200 at 70%, Warriors +120 at 50%" | Batch analysis sorted by EV, flags +EV bets |
| "Scan my probability estimates against tonight's lines and flag anything with 3%+ edge" | Uses +EV flagger with 3% threshold |
| "I think this Polymarket contract at $0.35 has a true probability of 42%. Is it +EV?" | Converts Kalshi/Polymarket price to odds, calculates EV |
Your agent reads the SKILL.md, identifies the relevant operation, substitutes the values, and runs the Python math inline.
## 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 "is this bet +EV?", this is what happens:
User message → OpenClaw Gateway → LLM reads system prompt + active skills → LLM matches “is this bet +EV” to ev-calculator skill → LLM extracts odds and probability from user’s message → LLM generates python3 -c command with substituted values → OpenClaw executes command via shell tool → Python outputs EV calculation results → LLM formats output for user with verdict
The quality of your SKILL.md directly determines how reliably the agent picks the right operation and formats the output. The ev-calculator skill uses explicit operation names, exact Python commands, and strict output rules to minimize agent improvisation.
## Extending the Skill
### Add Automated +EV Scanning
Chain ev-calculator with odds-scanner to automatically flag +EV bets. Set up a cron job that scans a full slate:
```json
{
"cron": "0 10 * * *",
"prompt": "Use odds-scanner to get today's NBA and NFL lines. For each game, use my model probabilities from the file ~/models/today.json. Calculate EV for every bet and alert me on Telegram with any that have 3%+ edge."
}
This turns manual bet evaluation into a systematic edge-finding pipeline — the core of a sharp betting workflow.
Chain with Other Skills
The ev-calculator is the decision gate in a complete betting pipeline:
- odds-scanner → feeds raw odds into ev-calculator as input
- ev-calculator → evaluates which bets are +EV (this skill)
- kelly-sizer → takes +EV bets and calculates optimal stake for each
- clv-tracker → logs the placed bets and validates edge by comparing to closing line
- bankroll-manager → tracks P&L and enforces risk limits
The flow: scan odds → evaluate EV → size bets → execute → track performance. Each skill handles one step, and together they form the intelligence layer of the Agent Betting Stack.
Add Prediction Market Support
The skill already handles Kalshi contract prices ($0.40) and Polymarket implied probabilities. Chain with polymarket-monitor or kalshi-tracker to evaluate prediction market positions alongside sportsbook bets in a unified EV framework.
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 (this guide), Kelly sizing, 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
- Kelly Sizer Skill — Size your +EV bets with the Kelly Criterion
- Odds Scanner Skill — Feed live odds into EV calculations
- Sharp Betting Guide — The broader framework for beating the market
- Agent Betting Stack Overview — Understand the four-layer framework these skills map to
- AgentBets Vig Index — Daily sportsbook efficiency rankings powered by the same odds data
