An automated trading bot for Polymarket's BTC 15-minute UP/DOWN prediction markets, implementing a two-leg arbitrage strategy.
The bot implements a two-leg arbitrage strategy for BTC 15-minute UP/DOWN markets. The strategy runs automatically when the bot starts - paper trading mode protects you from real orders until you explicitly switch to live mode.
-
Leg 1 (Buy the Dump): During the first N minutes of a round, watch for rapid price drops. If either UP or DOWN drops by at least X% in ~3 seconds, buy that side.
-
Leg 2 (Hedge): After Leg 1, wait for the opposite side's price to satisfy:
leg1_price + opposite_ask <= sum_target -
Profit: When both legs complete, you hold equal shares on both sides. Since one side always wins, you get $1 payout per share pair while having paid less than $1 total.
Strategy detects a 17% dump in DOWN over 3 seconds
- Bot buys 10 DOWN at $0.35 (Leg 1)
- UP ask drops to $0.56, check: 0.35 + 0.56 = 0.91 <= 0.95
- Bot buys 10 UP at $0.56 (Leg 2)
- Total cost: $9.10, Guaranteed payout: $10.00
- Profit: $0.90 (9.9%)
-
Install Rust (if not installed):
# Windows (PowerShell) winget install Rustlang.Rust.MSVC # Or download from https://rustup.rs
-
Clone and build:
git clone https://github.com/yourusername/polybot.git cd polybot cargo build --release
-
Go to Polymarket and log in
-
Click on "Cash" in the top right
-
Click the three dots menu
-
Select "Export Private Key"
-
Copy your private key
-
Create a
.envfile:cp .env.example .env
-
Add your private key to
.env:PK=your_private_key_here
WARNING: Never share your private key or commit .env to version control!
# Normal mode (paper trading enabled by default - safe!)
cargo run --release
# Verbose logging to file (for debugging)
cargo run --release -- --verbose --log-file polybot.logOnce the bot is running, use these commands:
| Command | Description |
|---|---|
help |
Show all commands |
buy up <usd> |
Buy UP shares for USD amount |
buy down <usd> |
Buy DOWN shares for USD amount |
buyshares up <n> |
Buy N UP shares at best ask |
buyshares down <n> |
Buy N DOWN shares at best ask |
params |
Show/update strategy parameters |
mode paper |
Switch to paper trading |
mode live |
Switch to live trading (requires confirmation) |
book |
Show order book details |
balance |
Show detailed balance info |
positions |
Show all positions by token |
trades |
Show recent trades |
reset |
Reset paper trading balance/history |
quit |
Exit the bot |
Adjust the strategy parameters at runtime:
params <shares> [sum=0.95] [move=0.15] [window=2] [cycles=1]
- shares: Number of shares to buy for each leg
- sum: Hedge threshold (default 0.95 = 5% minimum profit)
- move: Dump threshold percentage (default 0.15 = 15%)
- window: Minutes from round start to watch for Leg 1 (default 2)
- cycles: Maximum cycles per round (default 1)
Theta Decay: The sum target uses options-like time decay. It stays strict (at your configured value) for most of the round, then decays exponentially toward 0.99 in the last 5 minutes. This mirrors how options lose time value as expiration approaches, making it easier to complete a hedge as time runs out while maintaining profit margins early in the round.
# Conservative: 10 shares, 5% profit target, 15% dump, 2 min window, 1 cycle
params 10 0.95 0.15 2 1
# Aggressive: 20 shares, 8% profit target, 10% dump, 4 min window, 2 cycles
params 20 0.92 0.10 4 2
# Very conservative: 5 shares, 3% profit target, 20% dump, 1 min window, 1 cycle
params 5 0.97 0.20 1 1The bot supports two trading modes:
- PAPER (default): Simulates trades without placing real orders. Safe for testing.
- LIVE: Places real orders on Polymarket using the official SDK. Requires confirmation.
Switch modes using:
mode paper # Switch to paper trading (no real orders)
mode live # Switch to live trading (requires 'yes' confirmation)
When in LIVE mode, the bot uses the official polymarket-client-sdk for order execution:
- FOK Orders: All orders are Fill-or-Kill for immediate execution certainty
- EIP-712 Signing: Orders are cryptographically signed using your private key
- Lazy Authentication: API auth happens on first order, not at startup
- Depth Awareness: Orders are sized to available liquidity to avoid rejections
The bot will show "LiveTrader initialized for wallet: 0x..." at startup if your private key is configured.
Edit config.toml to customize settings:
[api]
clob_endpoint = "https://clob.polymarket.com"
ws_endpoint = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
gamma_endpoint = "https://gamma-api.polymarket.com"
[trading]
default_shares = 10
default_sum_target = 0.95 # Hedge threshold (theta decay to 0.99 in last 5 min)
default_move_pct = 0.15 # 15% dump required for Leg 1
default_window_min = 2 # Watch for dumps in first 2 minutes
default_max_cycles = 1 # Max Leg1+Leg2 pairs per round
dump_window_secs = 3
[recording]
enabled = true
data_dir = "data"
interval_ms = 1000
[paper_trading]
enabled = true # Safe by default - no real orders
starting_balance = 1000 # Starting balance in USD
fee_rate = 0.005 # Simulated fee (0.5%)
slippage = 0.02 # Simulated slippage (2%)The bot records price snapshots for backtesting:
- Data is stored in
data/prices_YYYY-MM-DD.jsonl - Each line is a JSON object with timestamp, prices, and market info
- Use this data to test different parameter combinations
This bot involves financial risk:
- Past performance does not guarantee future results
- The strategy assumes price reversals happen frequently enough to profit
- Market conditions can change, making the strategy less effective
- You can lose money if Leg 2 never triggers before the round ends
- Always test with paper trading first (enabled by default)
- Paper trading is enabled by default for your safety
The bot implements smart order sizing based on order book depth:
- Before buying the dump, checks available depth at best ask
- If depth < desired shares, reduces order size to match available liquidity
- Accepts smaller profit on fewer shares rather than risking partial fills
- If hedge side depth < remaining imbalance, fills what's available
- Tracks remaining imbalance and retries on subsequent ticks
- Uses theta-decayed sum target for relaxed hedging near round end
- Completes cycle only when fully hedged (imbalance = 0)
The UI shows up to 3 depth levels for each side:
UP: $0.4500 x100@0.45 x50@0.46 x25@0.47
DOWN: $0.5200 x80@0.52 x40@0.53 x20@0.54
Format: x<size>@<price> for each level, or "no depth" if order book is empty.
src/
├── main.rs # Entry point and CLI
├── types.rs # Core data structures
├── config.rs # Configuration management
├── api/
│ ├── client.rs # REST API client
│ └── websocket.rs # WebSocket price streaming (with depth parsing)
├── market/
│ └── watcher.rs # Market monitoring
├── strategy/
│ └── auto.rs # Two-leg strategy with depth-aware sizing
├── paper/
│ └── mod.rs # Paper trading simulation
├── live/
│ └── mod.rs # SDK-based live trading (FOK/GTC orders)
├── recorder/
│ └── mod.rs # Data recording for backtesting
└── terminal/
├── app.rs # Application logic
└── ui.rs # Terminal UI with depth display
The bot uses:
- Polymarket CLOB API for trading
- Gamma API for market metadata
- WebSocket for real-time price updates
MIT License - See LICENSE for details.
This software is for educational purposes only. Trading on prediction markets involves substantial risk of loss. The authors are not responsible for any financial losses incurred through use of this software.