A Python tool for backtesting, previewing, and running a live automated trading bot on Polymarket — a decentralized prediction market platform.
- Backtest — replay a strategy against historical resolved markets and measure P&L
- Preview — see which bets would be placed today without spending money
- Live (dry-run) — run the bot in real time, simulating trades without real money
- Live (real money) — place actual USDC bets on the Polymarket CLOB API
- Take-profit — automatically sell a position when it's up by a target % on your stake
- Stop-loss — automatically sell a position if the market probability drops below a threshold
- Sports filter — skip sports/esports markets with
--no-sports - PYNQ support — deploy and auto-start on a PYNQ embedded board via serial transfer
The bot looks for markets ending today or tomorrow where the current probability is at or above a configurable threshold (default 70%). It bets a flat stake on the favored outcome using Polymarket's CLOB (Central Limit Order Book) API, posting Fill-or-Kill orders to ensure instant execution.
Requires Python 3.10+.
pip install .Or install in development mode:
pip install -e .For live trading you need Polymarket API credentials. Run the helper script once:
python polymarket_sim/create_api_credentials.pyThis will prompt for your private key and derive the API key/secret/passphrase, then print the environment variables to set.
Set these environment variables before running in live mode:
export POLYMARKET_PRIVATE_KEY=<your_private_key>
export POLYMARKET_API_KEY=<your_api_key>
export POLYMARKET_API_SECRET=<your_api_secret>
export POLYMARKET_API_PASSPHRASE=<your_api_passphrase>
# Required if using a Magic.link / email account (proxy wallet):
export POLYMARKET_PROXY_WALLET=<your_proxy_wallet_address>Replay the strategy on historical resolved markets:
polymarket-sim backtest --start 2024-10-01 --end 2024-11-01With all options:
polymarket-sim backtest \
--start 2024-10-01 \
--end 2024-11-01 \
--threshold 0.75 \
--stake 25 \
--bankroll 5000 \
--min-volume 1000 \
--min-liquidity 500 \
--chart chart.png| Option | Default | Description |
|---|---|---|
--start |
required | Start date (YYYY-MM-DD) |
--end |
required | End date (YYYY-MM-DD, exclusive) |
--threshold |
0.70 | Min probability to bet (e.g. 0.70 = 70%) |
--stake |
10.0 | Flat dollar stake per market |
--bankroll |
1000.0 | Starting bankroll in USD |
--min-volume |
1000.0 | Minimum total market volume |
--min-liquidity |
0.0 | Minimum recent liquidity (suggested: 500) |
--chart |
None | Save bankroll chart to PNG file |
--no-chart |
False | Skip chart entirely |
Show which bets would be placed today (no money spent):
polymarket-sim previewpolymarket-sim preview --threshold 0.80 --stake 50 --min-liquidity 500Run the bot continuously. Default is dry-run (no real money):
polymarket-sim live --interval 30 --stake 10 --bankroll 1000Enable real money trading:
polymarket-sim live \
--live-trading \
--interval 30 \
--stake 10 \
--bankroll 1000 \
--min-volume 1000 \
--min-liquidity 500 \
--no-sports \
--take-profit 0.10 \
--sell-threshold 0.55| Option | Default | Description |
|---|---|---|
--interval |
300 | Seconds between market scans |
--threshold |
0.70 | Min probability to bet |
--stake |
10.0 | Flat dollar stake per bet |
--bankroll |
1000.0 | Starting bankroll in USD |
--min-volume |
1000.0 | Minimum total market volume |
--min-liquidity |
0.0 | Minimum recent liquidity |
--live-trading |
False | Enable real USDC trading |
--no-sports |
False | Skip sports/esports markets |
--take-profit |
0.0 | Sell when up X% on stake (e.g. 0.10 = sell at +10%) |
--sell-threshold |
0.0 | Stop-loss: sell if probability drops below this value |
--take-profit 0.10 sells a position when its current market value is at least 10% above your original stake. This is entry-price-relative — high-probability bets near 1.0 will never trigger (they're better left to resolve naturally).
--sell-threshold 0.55 sells a position immediately if the market probability drops below 55%, cutting losses before they grow.
The send_wheel.py script builds a .whl and transfers it to a PYNQ board over UART (COM port):
python send_wheel.pyTo auto-start on boot, add to the PYNQ's crontab:
@reboot /home/xilinx/start_polymarket.sh >> /home/xilinx/polymarket.log 2>&1polymarket_sim/
├── api_client.py # Gamma API + CLOB API clients
├── executor.py # Live order execution (PolymarketExecutor, DryRunExecutor)
├── simulator.py # BacktestEngine, PreviewEngine, LiveEngine
├── models.py # Data models (Bet, SettledBet, LiveConfig, etc.)
├── reporter.py # Console reports and bankroll chart
├── main.py # CLI entry point (Click)
├── create_api_credentials.py # One-time credential setup helper
└── _entry.py # Package entry point
pyproject.toml # Package metadata and build config
send_wheel.py # Build + transfer wheel to PYNQ over serial
serial_transfer.py # Low-level serial utilities
diagnose_allowance.py # Debug USDC allowance state on-chain
- Never commit credentials — all keys are read from environment variables only
- The private key gives full control of your Polymarket wallet — keep it secret
- For Magic.link / email accounts, set
POLYMARKET_PROXY_WALLETto your proxy wallet address
MIT