How To Build A Live Polymarket Trading Bot Using Claude Code, Kelly Criterion, and the Wolf Hour Strategy
A complete engineering build log — from zero to a fully deployed prediction market bot running 24/7 on Railway, scanning Bitcoin, XRP, Ethereum, and Solana 5-minute markets using real quant math. No prior trading bot experience required.
Why We Built This — and Why Now
Most crypto trading bots are built by developers who already know how to code. They spend weeks on infrastructure before ever touching a strategy. We took a completely different approach: we built the entire thing using Claude Code as the engineering engine, with James directing strategy and architecture in plain English.
The result is Quant Saber — our AI Executive CFO bot — scanning Polymarket's 5-minute crypto prediction markets 24/7, running real quantitative math under the hood, and deployed to the cloud without touching a single server configuration file manually.
This post is the complete build log. Every decision, every bug, every fix. If you've ever wanted to build a trading bot but didn't know where to start — this is the blueprint.
Why Claude Code Is the Best Tool for Building This Kind of Bot
Before we get into the strategy, let's talk about the build environment — because this is where most people get stuck. Traditional trading bot development requires: setting up a Python environment, debugging dependency conflicts, understanding async architecture, reading API documentation, and handling edge cases you didn't anticipate. That's 80% of the work before you write a single line of strategy logic.
Claude Code collapses that entirely. Here's what it actually does that no other tool can match:
The Strategy: Wolf Hour + 5-Minute Crypto Markets
Quant Saber runs two complementary strategies. Understanding why they work requires understanding one counterintuitive fact about prediction markets: the price inefficiencies aren't in the outcomes, they're in the timing.
The Wolf Hour Window
Every night between 02:30 and 04:00 UTC, Polymarket goes partially dark. Three things happen simultaneously: US retail traders are asleep, European traders haven't opened, and market maker bots either widen their quotes defensively or go offline entirely. The result is that spreads on mid-tier markets — normally 2-3 cents — blow out to 8-10 cents.
Most people see this and think the market is broken. The correct read is that it's a structural gift. You're not predicting outcomes. You're buying at a price that only exists because of temporary illiquidity, then selling back to fair value when the market reopens.
The 5-Minute Crypto Markets
Polymarket runs 5-minute binary markets on Bitcoin, XRP, Ethereum, Solana, Dogecoin, and Hyperliquid. Every 5 minutes a new window opens: "Will BTC be UP or DOWN from its current price in 5 minutes?" These resolve automatically via Chainlink price feeds — no human oracle, no dispute process.
These are the highest-frequency markets on the platform. They're ideal for a bot because: they're purely mechanical, they resolve fast, and the orderbook depth is real during US trading hours (9 AM – 9 PM ET).
The Math: What's Actually Running Under the Hood
This is where Quant Saber separates from toy trading bots. We didn't just write "buy when the price looks good." We implemented three distinct mathematical frameworks that professional quants use on live markets.
1. Kelly Criterion — Position Sizing
The Kelly Criterion answers the question: given that I have an edge, how much of my bankroll should I bet? Bet too much and variance wipes you out even when you're right. Bet too little and you leave enormous returns on the table.
The formula: f* = (bp - q) / b where b is the net odds received, p is your estimated probability of winning, and q = 1 - p.
We run fractional Kelly at 25% — quarter of the mathematically optimal bet size. This is standard practice for real traders because full Kelly, while theoretically optimal, produces drawdowns that are psychologically destructive and practically unmanageable. At 25% Kelly, five consecutive losses drops your bankroll to ~$900 on a $1,000 start. At full Kelly, the same five losses drops you to ~$590.
| Kelly Fraction | 5 Consecutive Losses | Long-Run Growth | Recommendation |
|---|---|---|---|
| Full Kelly (100%) | $590 remaining | Maximum theoretical | Dangerous in practice |
| Half Kelly (50%) | $760 remaining | Strong | Aggressive but viable |
| Quarter Kelly (25%) | $900 remaining | Moderate | Our setting — recommended |
2. Markov Chain Monte Carlo — Probability Estimation
A Markov chain models a system where the next state depends only on the current state — not the full history. For prediction market prices, this is a reasonable approximation: where the price goes next depends more on where it is now than on where it was three weeks ago.
We discretize the price into 10 states (0-10¢, 10-20¢, ... 90-100¢) and build a transition matrix from price history: how often does the price move from state 4 to state 5? From state 7 to state 6? This matrix captures the actual dynamics of each specific market.
Then we run 10,000 Monte Carlo simulations — random walks through the transition matrix — and count how many paths end above 50¢. That fraction is our probability estimate. If the market is priced at 45¢ and our Monte Carlo says 55%, we have a 10-cent edge.
3. Becker Longshot Calibration
In 2026, researcher Jonathan Becker analyzed 72.1 million trades across $18.26 billion in volume on prediction markets. His finding: cheap contracts are systematically overpriced. A contract at 1¢ should win 1% of the time — it actually wins only 0.43% of the time. A contract at 5¢ should win 5% — it wins 4.18%.
This is the "longshot bias" — people overbet unlikely outcomes. We apply Becker's calibration table as a correction factor to our Monte Carlo output. If our model says a 5¢ contract has a 5% chance, we adjust it down to 4.18% before making any sizing decision. This prevents us from joining the 87% of wallets that lose money by chasing cheap contracts.
Risk Management: The Circuit Breakers
No strategy works 100% of the time. What separates systematic traders from gamblers is having hard rules that override emotion when the strategy is losing. Quant Saber has three non-negotiable circuit breakers baked into the code:
- Daily halt at -20% — if the portfolio drops 20% from the day-start balance, all trading stops until manual restart. This prevents a bad day from becoming a catastrophic day.
- Drawdown halt at 60% ATH — if the portfolio falls below 60% of its all-time high, the bot stops permanently until reviewed. A 40% drawdown means something is structurally wrong with the strategy.
- 5-loss streak pause — after five consecutive losses, the bot pauses for 30 minutes. This catches the scenario where market conditions have shifted temporarily and the strategy's edge has temporarily disappeared.
The Tech Stack
How We Actually Built It: The Real Build Log
Here's what the actual build process looked like — including the bugs, the wrong turns, and the fixes. We're sharing this because most tutorials show you the clean version. The real version is messier and more educational.
Phase 1: Project Scaffold (Day 1)
We started Claude Code, created a quant-saber/ directory, and gave it a single prompt describing the full architecture: Kelly + Markov signals, risk manager, BTC 5-min strategy, Wolf Hour strategy, paper simulator, claim manager, and main bot orchestrator. Claude Code generated all 22 files in one session. Every math assertion passed verification: Kelly correctly sized $50 on a 60% edge with $1,000 portfolio, Becker calibration correctly adjusted 1¢ contracts down to 0.43¢, circuit breakers triggered correctly on simulated losses.
Phase 2: Credentials and First Run (Day 1)
Getting Polymarket credentials required running a one-time script to derive API key, secret, and passphrase from your wallet's private key using the py-clob-client SDK. The tricky part: Python 3.9 doesn't support the union type syntax the SDK requires. We had to install Homebrew, then Python 3.11, rebuild the virtual environment, and run again. First successful connection: Polymarket CLOB connected, Binance feed live.
Phase 3: Deployment to Railway (Day 1-2)
We deployed to Railway so the bot would run 24/7 without keeping a laptop awake. Initial deployment hit a geo-block on binance.com — automatic fallback to binance.us solved it. The Binance WebSocket kept reconnecting every 60 seconds due to low volume at 2 AM. Switched from aggTrade (fires on trades) to bookTicker (fires on every quote update) — no more stale feed. Telegram chat ID — message @userinfobot to get the user ID.
Phase 4: Market Discovery Debugging (Days 3-7)
This was the hard phase. The bot was running but finding zero tradeable markets. Over several days we diagnosed and fixed:
- Resolution timestamp bug — missing
end_date_isofields defaulted to Unix epoch (year 1970), makinghours_left ≈ -500,000and dropping every market silently. - Markov cold start crash — the engine threw a
ValueErrorat fewer than 10 observations instead of returningNonegracefully. - Token ID parsing — Gamma API returns
clobTokenIdsas a JSON string, not a list.zip(string, outcomes)was iterating character by character, assigningtoken_id = "[". - UP/DOWN vs YES/NO — 5-minute crypto markets use
outcome='UP'andoutcome='DOWN'instead ofYES/NO. One line fix droppedno_tokenfrom 137 to near zero. - OrderBookSummary object — newer py-clob-client versions return an object, not a dict. Calls to
.get("bids")crashed. Fixed with a normalizer that handles both shapes. - Stale Railway container — Nixpacks builder was aggressively caching old images. Switched to a Dockerfile builder for clean rebuilds every time.
Realistic ROI — What This Bot Is Actually Capable Of
We're going to be honest here because most bot content is not. The numbers below are based on the Wolf Hour math from the original research.
| Scenario | Trades/Week | Avg Edge | Position Size | Weekly Return | Annual Return |
|---|---|---|---|---|---|
| Conservative | 2 | 6¢ | $200 | $24 | $1,248 |
| Moderate | 4 | 8¢ | $400 | $128 | $6,656 |
| Aggressive | 8 | 9¢ | $500 | $360 | $18,720 |
| Wolf Hour Research Baseline | 4 | 9¢ | $500 | $180 | $9,360 on ~$2K deployed |
p comes from vibes, the Kelly formula is useless. Garbage in, garbage out. Run paper mode until you have 200 trades of data before risking real capital.The constraint is that qualifying entries are genuinely rare. Some weeks there are zero. You are not manufacturing trades to fill windows. You are waiting for the market to serve you the right price, and only taking it when your pre-built analysis supports the position.
How to Build This Exact Bot — Step by Step
npm install -g @anthropic/claude-code. You'll need a Claude Pro or Max subscription./newbot, copy the token. Message @userinfobot to get your personal chat ID.Step 1 — Generate the Project
Open Claude Code, create a new folder called quant-saber, and paste this prompt:
Build the Quant Saber Polymarket trading bot. Create this full structure:
src/signals/kelly.py # fractional Kelly, position sizing, 8% hard cap
src/signals/markov_engine.py # transition matrix, 10K Monte Carlo, Becker calibration
src/signals/technical.py # RSI, MACD, ATR, price divergence
src/risk/risk_manager.py # daily -20% halt, 60% ATH drawdown halt, 5-loss pause
src/strategies/btc_5min.py # 5-min lifecycle: bootstrap → signal → limit order
src/strategies/wolf_hour.py # spread-sorted market scan + Wolf Hour entry logic
src/execution/claim_manager.py # auto-claim loop every 60s
src/market/polymarket_client.py # CLOB API + Gamma API wrapper
src/market/binance_feed.py # bookTicker WebSocket, BTC + XRP, auto-reconnect
paper/simulator.py # paper trading with latency and partial fill simulation
src/bot.py # main async orchestrator, Telegram heartbeat
requirements.txt # pinned versions, Python 3.11+
.env.example # all required env vars
Dockerfile # python:3.11-slim, clean build
railway.toml # Railway deployment config
Key requirements:
- Full async architecture (asyncio + aiohttp)
- Paper mode ON by default — live requires --live --confirm --i-understand-risks
- SQLite logging for all paper trades
- Telegram alert on every trade, error, and hourly heartbeat
- Polymarket CLOB API with limit orders only, never market orders
- Binance WebSocket bookTicker for BTC and XRP price feeds
- Reject price data older than 10 seconds
- Minimum 8% edge threshold before any trade (3% in paper mode)
- Half-Kelly sizing with 8% portfolio hard cap per trade
- Auto-claim winning positions every 60 seconds
- Wolf Hour: scan markets sorted by spread width, target spread >= 5¢
- 5-min crypto: detect UP/DOWN markets by question text, pending queue for inactive windows
- Markov engine: 10 states, 10K Monte Carlo, Becker longshot calibration applied
- Circuit breakers: daily -20% halt, 60% ATH drawdown halt, 5-loss streak pause
Step 2 — Get Your Credentials
Once the project generates, create a get_credentials.py script to derive your Polymarket API credentials from your wallet private key:
from py_clob_client.client import ClobClient
import os
from dotenv import load_dotenv
load_dotenv()
client = ClobClient(
host="https://clob.polymarket.com",
key=os.getenv("PRIVATE_KEY"),
chain_id=137
)
creds = client.create_or_derive_api_creds()
print("API Key:", creds.api_key)
print("Secret:", creds.api_secret)
print("Passphrase:", creds.api_passphrase)
Add your wallet's private key to .env as PRIVATE_KEY=0x..., run the script, and copy the three values into your .env file.
.env file to GitHub. Your private key controls your wallet — treat it like a password to your bank account.Step 3 — Run Paper Mode Locally
# Create Python 3.11 virtual environment
python3.11 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Start in paper mode (default)
python src/bot.py
You should see the startup banner, Polymarket connected, and Binance feed live. Paper mode is the default — no real money at risk.
Step 4 — Deploy to Railway
# Install Railway CLI
brew install railway
# Login and deploy
railway login
railway init
railway up
After deploy, set your environment variables in the Railway dashboard under Variables. Required: POLY_PRIVATE_KEY, POLY_API_KEY, POLY_SECRET, POLY_PASSPHRASE, TELEGRAM_TOKEN, TELEGRAM_CHAT_ID, ALCHEMY_RPC_URL, PAPER_MODE=true.
Step 5 — Wait for 200 Paper Trades
This is the most important step and the one most people want to skip. Don't. Run paper mode until you have:
- 200+ completed paper trades — enough data to calculate statistically meaningful win rate
- 75%+ win rate — below this and the strategy doesn't have real edge in current market conditions
- 7+ consecutive days without crashes — infrastructure stability before risking real capital
- Paper PnL is positive — obvious but worth stating explicitly
Only when all four conditions are met should you consider switching to live mode. And even then, start with minimum position sizes and scale up only after 50+ live trades confirm paper performance holds.
The 8 Bugs We Hit That You Won't Have to
We're documenting these explicitly because every one of them is non-obvious and will bite you if you build this from scratch:
| Bug | Symptom | Fix |
|---|---|---|
| Python version | py-clob-client fails to install on Python 3.9 | Use Python 3.11+. Install with Homebrew: brew install [email protected] |
| Geo-block | Binance.com returns HTTP 451 from US IPs | Auto-fallback to wss://stream.binance.us:9443/ws |
| aggTrade vs bookTicker | Feed goes silent for 60+ seconds at 2 AM | Switch to bookTicker — fires on every quote, not just trades |
| Token ID parsing | token_id = "[" — orderbook returns 404 | json.loads() the clobTokenIds field — it arrives as a string |
| UP/DOWN outcomes | 5-min markets dropped as no_token | Match outcome.upper() in ('YES', 'UP') not just 'YES' |
| OrderBookSummary | AttributeError: object has no .get() | Use getattr(ob, 'bids', None) — newer SDK returns object not dict |
| Telegram chat ID | 403 Forbidden: bot can't message itself | Message @userinfobot to get YOUR personal chat ID, not the bot's |
| Railway caching | New code deploys but old container keeps running | Switch from Nixpacks to Dockerfile builder for clean rebuilds |
Where This Get's you for Your Quant Saber Right Now
As of this writing, Quant Saber can be live on Railway. He sends hourly heartbeats to your Telegram with balance, PnL, win rate, and feed health. He scans 190+ unique Polymarket markets every 3 minutes across three data sources. He correctly identifies Bitcoin, XRP, Ethereum, Solana, Dogecoin, and Hyperliquid 5-minute windows and monitors them with a 30-second pending queue to catch the moment each window opens.

Read the full Groove playbook →
→ Claim Free Access to Groove
What Do You Think?
Building your own version? Hit a bug we didn't cover? Drop a comment below — questions, pushback, or your own take. This is where the real conversation happens.