English | 简体中文
A beginner-friendly Python trading bot for Polymarket with gasless transactions and real-time WebSocket data.
- Simple API: Just a few lines of code to start trading
- Gasless Transactions: No gas fees with Builder Program credentials
- Real-time WebSocket: Live orderbook updates via WebSocket
- 15-Minute Markets: Built-in support for BTC/ETH/SOL/XRP 15-minute Up/Down markets
- Flash Crash Strategy: Pre-built strategy for volatility trading
- Terminal UI: Real-time orderbook display with in-place updates
- Secure Key Storage: Private keys encrypted with PBKDF2 + Fernet
- Fully Tested: 89 unit tests covering all functionality
git clone https://github.com/your-username/polymarket-trading-bot.git
cd polymarket-trading-bot
pip install -r requirements.txt# Set your credentials
export POLY_PRIVATE_KEY=your_metamask_private_key
export POLY_SAFE_ADDRESS=0xYourPolymarketSafeAddressWhere to find your Safe address? Go to polymarket.com/settings and copy your wallet address.
# Run the quickstart example
python examples/quickstart.py
# Or run the Flash Crash Strategy
python strategies/flash_crash_strategy.py --coin BTCThat's it! You're ready to trade.
Monitors 15-minute Up/Down markets for sudden probability drops and executes trades automatically.
# Run with default settings (0.30 drop threshold)
python strategies/flash_crash_strategy.py --coin BTC
# Custom settings
python strategies/flash_crash_strategy.py --coin ETH --drop 0.25 --size 10
# Available options
--coin BTC, ETH, SOL, XRP (default: ETH)
--drop Drop threshold as absolute change (default: 0.30)
--size Trade size in USDC (default: 5.0)
--lookback Detection window in seconds (default: 10)
--take-profit TP in dollars (default: 0.10)
--stop-loss SL in dollars (default: 0.05)Strategy Logic:
- Auto-discover current 15-minute market
- Monitor orderbook prices via WebSocket in real-time
- When probability drops by 0.30+ in 10 seconds, buy the crashed side
- Exit at +$0.10 (take profit) or -$0.05 (stop loss)
- See
docs/strategy_guide.mdfor a step-by-step tutorial and templates.
View live orderbook data in a beautiful terminal interface:
python strategies/orderbook_tui.py --coin BTC --levels 5from src import create_bot_from_env
import asyncio
async def main():
# Create bot from environment variables
bot = create_bot_from_env()
# Get your open orders
orders = await bot.get_open_orders()
print(f"You have {len(orders)} open orders")
asyncio.run(main())from src import TradingBot, Config
import asyncio
async def trade():
# Create configuration
config = Config(safe_address="0xYourSafeAddress")
# Initialize bot with your private key
bot = TradingBot(config=config, private_key="0xYourPrivateKey")
# Place a buy order
result = await bot.place_order(
token_id="12345...", # Market token ID
price=0.65, # Price (0.65 = 65% probability)
size=10.0, # Number of shares
side="BUY" # or "SELL"
)
if result.success:
print(f"Order placed! ID: {result.order_id}")
else:
print(f"Order failed: {result.message}")
asyncio.run(trade())from src.websocket_client import MarketWebSocket, OrderbookSnapshot
import asyncio
async def main():
ws = MarketWebSocket()
@ws.on_book
async def on_book_update(snapshot: OrderbookSnapshot):
print(f"Mid price: {snapshot.mid_price:.4f}")
print(f"Best bid: {snapshot.best_bid:.4f}")
print(f"Best ask: {snapshot.best_ask:.4f}")
await ws.subscribe(["token_id_1", "token_id_2"])
await ws.run()
asyncio.run(main())from src.gamma_client import GammaClient
gamma = GammaClient()
# Get current BTC 15-minute market
market = gamma.get_market_info("BTC")
print(f"Market: {market['question']}")
print(f"Up token: {market['token_ids']['up']}")
print(f"Down token: {market['token_ids']['down']}")
print(f"Ends: {market['end_date']}")# Cancel a specific order
await bot.cancel_order("order_id_here")
# Cancel all orders
await bot.cancel_all_orders()
# Cancel orders for a specific market
await bot.cancel_market_orders(market="condition_id", asset_id="token_id")polymarket-trading-bot/
├── src/ # Core library
│ ├── bot.py # TradingBot - main interface
│ ├── config.py # Configuration handling
│ ├── client.py # API clients (CLOB, Relayer)
│ ├── signer.py # Order signing (EIP-712)
│ ├── crypto.py # Key encryption
│ ├── utils.py # Helper functions
│ ├── gamma_client.py # 15-minute market discovery
│ └── websocket_client.py # Real-time WebSocket client
│
├── strategies/ # Trading strategies
│ ├── flash_crash_strategy.py # Volatility trading strategy
│ └── orderbook_tui.py # Real-time orderbook display
│
├── examples/ # Example code
│ ├── quickstart.py # Start here!
│ ├── basic_trading.py # Common operations
│ └── strategy_example.py # Custom strategies
│
├── scripts/ # Utility scripts
│ ├── setup.py # Interactive setup
│ ├── run_bot.py # Run the bot
│ └── full_test.py # Integration tests
│
└── tests/ # Unit tests
| Variable | Required | Description |
|---|---|---|
POLY_PRIVATE_KEY |
Yes | Your wallet private key |
POLY_SAFE_ADDRESS |
Yes | Your Polymarket Safe address |
POLY_BUILDER_API_KEY |
For gasless | Builder Program API key |
POLY_BUILDER_API_SECRET |
For gasless | Builder Program secret |
POLY_BUILDER_API_PASSPHRASE |
For gasless | Builder Program passphrase |
Create config.yaml:
safe_address: "0xYourSafeAddress"
# For gasless trading (optional)
builder:
api_key: "your_api_key"
api_secret: "your_api_secret"
api_passphrase: "your_passphrase"Then load it:
bot = TradingBot(config_path="config.yaml", private_key="0x...")To eliminate gas fees:
- Apply for Builder Program
- Set the environment variables:
export POLY_BUILDER_API_KEY=your_key
export POLY_BUILDER_API_SECRET=your_secret
export POLY_BUILDER_API_PASSPHRASE=your_passphraseThe bot will automatically use gasless mode when credentials are present.
| Method | Description |
|---|---|
place_order(token_id, price, size, side) |
Place a limit order |
cancel_order(order_id) |
Cancel a specific order |
cancel_all_orders() |
Cancel all open orders |
cancel_market_orders(market, asset_id) |
Cancel orders for a specific market |
get_open_orders() |
List your open orders |
get_trades(limit=100) |
Get your trade history |
get_order_book(token_id) |
Get market order book |
get_market_price(token_id) |
Get current market price |
is_initialized() |
Check if bot is ready |
| Method | Description |
|---|---|
subscribe(asset_ids, replace=False) |
Subscribe to market data |
run(auto_reconnect=True) |
Start WebSocket connection |
disconnect() |
Close connection |
get_orderbook(asset_id) |
Get cached orderbook |
get_mid_price(asset_id) |
Get mid price |
| Method | Description |
|---|---|
get_current_15m_market(coin) |
Get current 15-min market |
get_market_info(coin) |
Get market with token IDs |
get_all_15m_markets() |
List all 15-min markets |
Your private key is protected by:
- PBKDF2 key derivation (480,000 iterations)
- Fernet symmetric encryption
- File permissions set to
0600(owner-only)
Best practices:
- Never commit
.envfiles to git - Use a dedicated wallet for trading
- Keep your encrypted key file private
# Run all tests
pytest tests/ -v
# Run with coverage
pytest tests/ -v --cov=src| Problem | Solution |
|---|---|
POLY_PRIVATE_KEY not set |
Run export POLY_PRIVATE_KEY=your_key |
POLY_SAFE_ADDRESS not set |
Get it from polymarket.com/settings |
Invalid private key |
Check key is 64 hex characters |
Order failed |
Check you have sufficient balance |
WebSocket not connecting |
Check network/firewall settings |
- Fork the repository
- Create a feature branch
- Write tests for new code
- Run
pytest tests/ -v - Submit a pull request
MIT License - see LICENSE file for details.