I built a trading bot. After 176 resolved trades on Polymarket, here's my total profit: about $2.
Not $2,000. Not $200. Two dollars.
But that number hides the real story — because inside those 176 trades, three completely different strategies were fighting each other. One of them has a 97% win rate. Another one nearly wiped me out. And the math behind why is something every developer building trading bots needs to understand before they write a single line of code.
What Are Polymarket 15-Minute Markets?
Polymarket runs prediction markets on everything — elections, sports, weather. But the ones I trade are their 15-minute crypto markets: "Will BTC go up or down in the next 15 minutes?"
Two outcomes. Binary. Every 15 minutes, a new market opens. You buy shares of UP or DOWN at whatever the market prices them. If you're right, your shares pay out $1.00. If you're wrong, they're worth $0.00.
Simple, right?
The simplicity is the trap.
The Three Strategies I Tried
Strategy 1: Binary Arbitrage (ARB)
The idea: buy BOTH sides (UP and DOWN) when their combined price is less than $1.00.
If UP costs $0.49 and DOWN costs $0.49, you spend $0.98 total. One side will pay out $1.00. Guaranteed $0.02 profit per share regardless of what BTC does.
Result: 97% win rate. The only strategy that made money.
The arb trades were small — $0.10 to $0.30 per trade — but they were reliable. Out of 98 true arb trades (both sides filled), nearly all were wins.
Strategy 2: Late Momentum
The idea: wait until minute 8-12 of a 15-minute window. Check Binance — has BTC moved more than 0.20% from the window open? If yes, buy the winning side on Polymarket before the window closes.
The backtest looked incredible. 95.7% win rate at 0.20% threshold. Some windows showed 98.8%.
Result: Net negative. Lost money.
Momentum generated the biggest wins ($2.90, $2.50, $2.30 per trade) but also the biggest losses (-$8.40, -$7.70 per trade). One reversal erased 3-4 wins.
Strategy 3: Late Snipe
The idea: at minute 13, if BTC has moved >0.10%, direction holds 99% of the time. Buy at $0.93-$0.97, collect $1.00. Tiny margin, near-zero risk.
Result: Net negative. The margin was too thin to survive any loss.
The Per-Asset Breakdown That Changed Everything
Here's the data that made me cut two assets entirely:
| Asset | Result |
|---|---|
| BTC | Profitable (arb opportunities, cleaner price action) |
| SOL | Net loser (half-fills turned arbs into directional bets, multiple -$8.50 and -$18.00 losses) |
| ETH | Net loser (same half-fill problem, -$5.60 to -$20.75 losses) |
| XRP | Net loser (worst of all, -$19.75 to -$20.75 single trade losses) |
ETH and XRP were the worst offenders. I cut them from the bot entirely. The code now reads:
ASSETS = ["btc", "sol"] # ETH (-$11.45) and XRP (-$3.90) are net losers — cut
That comment is written in blood (well, USDC).
The Binary Math Trap
This is the thing nobody tells you about binary prediction markets. Let me show you the actual math from my bot's config:
MAX_ENTRY_PRICE = 0.72 # LOWERED: at 0.85 losses are 5x wins
Here's why. Say you buy UP at $0.85:
- If you win: You get $1.00 back. Profit = $0.15 per share.
- If you lose: You get $0.00 back. Loss = $0.85 per share.
That's a 1:5.67 risk/reward ratio against you. You need to win 85% of the time just to break even.
My momentum strategy had a real-world win rate around 80%. Sounds great for most trading. In binary markets with entry at $0.85, it's a guaranteed loss.
Even at $0.72 entry (where I eventually moved the cap):
- Win: +$0.28 per share
- Lose: -$0.72 per share
- Breakeven win rate: 72%
The market is not dumb. When BTC has clearly moved up in the first 10 minutes, the UP token isn't sitting at $0.50. It's at $0.90+. By the time the signal is obvious, the edge is gone.
Here's a real log entry showing exactly this:
SKIP btc-updown-15m-1772810100: UP BTC +0.517% but price $0.9900 > max $0.85
BTC moved +0.52%. Clear signal. But Polymarket already priced UP at $0.99. If I bought at $0.99 and won, I'd make $0.01 per share. If I lost, I'd lose $0.99.
The market ate the edge before the bot could.
The Half-Fill Problem: When Arb Turns Into a Directional Bet
This was the most expensive lesson. My bot uses FOK (fill-or-kill) orders — the order either fills completely or not at all. But arb requires two orders: buy UP, then buy DOWN.
Sometimes the UP order fills but the DOWN order gets rejected. Now instead of a risk-free arb, you're holding a naked directional bet.
From the logs:
RESOLVED eth-updown-15m-1773108900: DOWN [DOWN_ONLY] → UP = LOSS | P&L: $-20.75
RESOLVED xrp-updown-15m-1773108900: DOWN [DOWN_ONLY] → UP = LOSS | P&L: $-20.75
Two half-fills in the same window. $41.50 gone in 15 minutes. That's more than the arb strategy made in days.
The fix was straightforward — track fill_status and only submit the second leg if the first fills. But even with FOK protection, the second order can fail if liquidity dries up between the two submissions:
if up_status in ("MATCHED", "matched"):
log.info(f" UP FILLED at ${up_price}")
else:
log.warning(f" UP not filled. Skipping DOWN — no arb.")
return result
You can't eliminate this risk on a CLOB. You can only size it so a half-fill doesn't blow up your account.
How the Bot Learned to Sit on Its Hands
The biggest improvement wasn't a new strategy. It was teaching the bot to not trade.
I built a pattern detector that classifies every 15-minute window into one of six patterns based on intra-window price action:
# From 400-window backtest:
# LATE_BREAK: 93.5% hold rate → TRADE
# SUSTAINED: 92.9% → TRADE
# CHOPPY: SKIP (catch-all "unclear direction")
# PUMP_DUMP: 67% → SKIP (coin flip)
Here's what yesterday's log looks like — nothing but SKIPs:
SKIP SNIPE [BTC] btc-updown-15m-1773411300 — CHOPPY (peak +0.450% at min 9, retrace 34%)
SKIP SNIPE [SOL] sol-updown-15m-1773411300 — CHOPPY (peak +0.498% at min 10, retrace 57%)
SKIP SNIPE [BTC] btc-updown-15m-1773411300 — CHOPPY (peak +0.450% at min 9, retrace 40%)
The CHOPPY filter detects when BTC spiked early (peak at minute 9-10) but then retraced 34-57%. That's a coin flip. The bot sees it and sits on its hands.
There's also a volatility filter using ATR (Average True Range) of the previous four 15-minute windows:
# Allow Q1+Q2 (ATR < 0.12%), skip Q3+Q4
if atr > 0.12:
return False, atr, f"ATR {atr:.4f}% too high (Q3/Q4)"
And a time-of-day filter that skips 12-16 UTC (US market open) where the win rate drops to 81.5% — technically positive but not enough to overcome the binary math.
The bot now rejects more trades than it takes. That's the feature.
The Only Strategy That Works (And Why)
Binary arb is the only thing that made money. Here's why it's structurally different from directional trading:
- No prediction required. You don't need to know which way BTC is going. You just need UP + DOWN < $1.00.
- The edge is mathematical, not statistical. A 2-cent gap is a 2-cent gap regardless of market conditions.
- Losses only happen from execution failure (half-fills), not from being wrong about direction.
But arb has its own problems:
- Gaps are tiny ($0.01 to $0.03 per share)
- At 10 shares per trade, you're making $0.10-$0.30 per trade
- You need hundreds of trades to make meaningful money
- Liquidity on the underdog side is often too thin for FOK orders to fill
The live log tells the story — arb opportunities detected, but the orders can't fill:
ARB DETECTED [BTC] on btc-updown-15m-1772951400
UP=0.7000 DOWN=0.2800 Combined=0.9800 Profit/share=$0.0200
Order execution failed: order couldn't be fully filled. FOK orders are fully filled or killed.
The bot sees $0.02/share profit. It tries to take it. The liquidity isn't there. Move on.
What the Data Actually Says
After 176 trades, 8 days of runtime, and more debugging sessions than I want to admit:
- Win rate: 92% (162 wins, 14 losses)
- Net P&L: ~$2 (arb profits minus directional losses minus half-fill disasters)
- Arb strategy: profitable. Small but reliable. $0.10/trade adds up if you can fill.
- Momentum strategy: net negative. Binary math kills it. Backtested win rate was higher than live win rate, and even the backtest rate wasn't enough.
- Snipe strategy: net negative. Margin too thin. One loss erases dozens of wins.
92% win rate and barely positive P&L. Read that again.
The win rate is meaningless when your wins average $0.15 and your losses average $-12.00. This is the fundamental problem with binary prediction markets for directional trading. The payoff structure is asymmetric in the wrong direction unless you're buying at $0.50 or below — and if the price is $0.50, the market is saying it's a coin flip.
What I'd Do Differently
Start with the math, not the backtest. Calculate your breakeven win rate at your entry price BEFORE you write the strategy code. If it's above 80%, the strategy can't work in binary markets.
Arb is the only edge for a bot. Directional trading on 15-minute crypto markets is a losing game for automated systems. The market prices in obvious signals faster than your bot can react.
Size for the worst case, not the average case. My half-fill losses ($20+ each) happened because I sized for the arb case. One execution failure turned a $0.20 expected profit into a $20 actual loss. That's 100:1 against you.
The CHOPPY filter should have been day one, not week two. Trading without pattern detection is gambling. The bot doesn't know if BTC's 0.25% move is a sustained trend or a spike about to reverse. The filter is the difference between 67% and 93% hold rate.
Log everything. Every trade gets a cryptographically signed receipt via
ai-decision-tracer. I can prove exactly what the bot saw, why it traded, and what happened. When you're debugging a -$20 loss at 3 AM, you need a tamper-proof audit trail, notprint()statements.
The Code
The bot, P&L tracker, and strategy logic are all open source:
- polymarket-ai — the full trading bot with arb, momentum, and snipe strategies
- ai-decision-tracer — cryptographically signed trade receipts (every trade gets a hash-chained, Ed25519-signed audit trail)
- ai-starter-protocol — the open-source safety stack for AI agents
The bot runs 24/7 on a Mac Mini, scanning every 5 seconds, with Telegram alerts for every fill and resolution. Total infrastructure cost: $0/month (runs locally).
This is Part 1 of the "I Built a Trading Bot" series. Next up: the copy trader — tracking the top 5 Polymarket winners and what their strategies reveal about where the real money is.
If you're building trading bots or working with prediction markets, I'd genuinely love to hear what's worked for you. The math is harder than the code.
Top comments (0)