c524ed92ef
- Replace single price/shares with 3-tier system (3c/2c/1c) - Tier allocation: 20%/30%/50% (high→low price) - Min 5 shares per tier enforced - Update .env.example with new config vars - Update README.md with strategy documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
384 lines
12 KiB
Markdown
384 lines
12 KiB
Markdown
# Polymarket Terminal
|
||
|
||
> An automated trading terminal for [Polymarket](https://polymarket.com) — copy trades, provide liquidity, and snipe low-priced orderbook fills, all from your command line.
|
||
|
||
**Created by [@direkturcrypto](https://twitter.com/direkturcrypto)**
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [Features](#features)
|
||
- [Prerequisites](#prerequisites)
|
||
- [Installation](#installation)
|
||
- [Configuration](#configuration)
|
||
- [Usage](#usage)
|
||
- [Running on VPS with PM2](#running-on-vps-with-pm2)
|
||
- [How It Works](#how-it-works)
|
||
- [Project Structure](#project-structure)
|
||
- [Important Warnings](#important-warnings)
|
||
- [License](#license)
|
||
|
||
---
|
||
|
||
## Features
|
||
|
||
### Copy Trade Bot
|
||
- **Watch Trader** — Monitor any Polymarket wallet address in real time via WebSocket
|
||
- **Copy Buy** — Automatically mirror buy orders with configurable position sizing
|
||
- **Copy Sell** — Automatically mirror sell orders (market or limit)
|
||
- **Auto Sell** — Place a GTC limit sell at a target profit % immediately after a buy fills
|
||
- **Auto Redeem** — Periodically check and redeem winning positions on-chain
|
||
- **Market Expiry Guard** — Skip buys if market closes within `MIN_MARKET_TIME_LEFT` seconds
|
||
- **GTC Fallback** — Falls back to a GTC limit order when copying "next market" trades with no liquidity
|
||
- **Per-Market Queue** — Concurrent events for the same market are serialized to prevent duplicate buys
|
||
- **Dry Run Mode** — Simulate the full flow without placing real orders
|
||
|
||
### Market Maker Bot
|
||
- **Automated Liquidity** — Splits USDC into YES+NO tokens and places limit sells on both sides at $0.50 entry
|
||
- **Cut-Loss Protection** — Merges unsold tokens back to USDC before market close
|
||
- **Recovery Buy** — Optional directional bet after a cut-loss triggers
|
||
- **Multi-Asset** — Supports BTC, ETH, SOL, and any 5m/15m Polymarket market
|
||
- **Simulation Mode** — Full dry-run with P&L tracking
|
||
|
||
### Orderbook Sniper Bot
|
||
- **3-Tier Strategy** — Places GTC BUY orders at 3c, 2c, and 1c with weighted sizing (20%/30%/50%)
|
||
- **Multi-Asset** — Targets ETH, SOL, XRP, and more simultaneously
|
||
- **Simulation Mode** — Preview orders without spending funds
|
||
- **Session Scheduling** — Per-asset time windows (UTC+8) for selective trading
|
||
|
||
---
|
||
|
||
## Prerequisites
|
||
|
||
| Requirement | Details |
|
||
|---|---|
|
||
| Node.js | v18 or higher (ESM support required) |
|
||
| Polygon Wallet | An EOA wallet with a private key |
|
||
| Polymarket Proxy Wallet | Your proxy wallet address (visible on your Polymarket profile → Deposit) |
|
||
| USDC.e on Polygon | Deposited via Polymarket's deposit flow |
|
||
| MATIC on Polygon | A small amount for gas fees (redeem & on-chain operations) |
|
||
| PM2 *(optional)* | For running on a VPS: `npm install -g pm2` |
|
||
|
||
---
|
||
|
||
## Installation
|
||
|
||
```bash
|
||
# 1. Clone the repository
|
||
git clone https://github.com/direkturcrypto/polymarket-terminal.git
|
||
cd polymarket-terminal
|
||
|
||
# 2. Install dependencies
|
||
npm install
|
||
|
||
# 3. Copy the environment template
|
||
cp .env.example .env
|
||
|
||
# 4. Fill in your credentials
|
||
nano .env
|
||
```
|
||
|
||
---
|
||
|
||
## Configuration
|
||
|
||
All settings are controlled via the `.env` file. **Never commit your `.env` file** — it is already listed in `.gitignore`.
|
||
|
||
### Wallet Setup
|
||
|
||
| Variable | Description | Required |
|
||
|---|---|---|
|
||
| `PRIVATE_KEY` | Your EOA private key (signing only, does not hold USDC) | Yes |
|
||
| `PROXY_WALLET_ADDRESS` | Your Polymarket proxy wallet address | Yes |
|
||
| `POLYGON_RPC_URL` | Polygon JSON-RPC endpoint | Yes |
|
||
|
||
> **How to find your Proxy Wallet:** Log in to polymarket.com → click your profile → Deposit → copy the wallet address shown.
|
||
|
||
### Polymarket API Credentials (Optional)
|
||
|
||
Leave these blank to have the client auto-derive credentials from your private key.
|
||
|
||
| Variable | Description |
|
||
|---|---|
|
||
| `CLOB_API_KEY` | CLOB API key |
|
||
| `CLOB_API_SECRET` | CLOB API secret |
|
||
| `CLOB_API_PASSPHRASE` | CLOB API passphrase |
|
||
|
||
### Copy Trade Bot Settings
|
||
|
||
| Variable | Description | Default |
|
||
|---|---|---|
|
||
| `TRADER_ADDRESS` | Proxy wallet address of the trader to copy | (required) |
|
||
| `SIZE_MODE` | `percentage` (of `MAX_POSITION_SIZE`) or `balance` (of your USDC balance) | `balance` |
|
||
| `SIZE_PERCENT` | Percentage to use per trade | `10` |
|
||
| `MIN_TRADE_SIZE` | Minimum trade size in USDC (skip if below) | `1` |
|
||
| `MAX_POSITION_SIZE` | Maximum USDC per market position | `10` |
|
||
| `AUTO_SELL_ENABLED` | Place a limit sell after each buy fills | `true` |
|
||
| `AUTO_SELL_PROFIT_PERCENT` | Target profit % for the auto-sell limit order | `10` |
|
||
| `SELL_MODE` | `market` or `limit` when copying a sell | `market` |
|
||
| `REDEEM_INTERVAL` | Seconds between redemption checks | `60` |
|
||
| `MIN_MARKET_TIME_LEFT` | Skip buy if market closes within this many seconds | `300` |
|
||
| `GTC_FALLBACK_TIMEOUT` | Seconds to wait for GTC fill when FAK finds no liquidity | `60` |
|
||
| `DRY_RUN` | Simulate without placing real orders | `true` |
|
||
|
||
### Market Maker Bot Settings
|
||
|
||
| Variable | Description | Default |
|
||
|---|---|---|
|
||
| `MM_ASSETS` | Comma-separated assets to market-make (e.g. `btc,eth`) | `btc` |
|
||
| `MM_DURATION` | Market duration: `5m` or `15m` | `5m` |
|
||
| `MM_TRADE_SIZE` | USDC per side (total exposure = 2×) | `5` |
|
||
| `MM_SELL_PRICE` | Limit sell price target (e.g. `0.60`) | `0.60` |
|
||
| `MM_CUT_LOSS_TIME` | Seconds before close to trigger cut-loss | `60` |
|
||
| `MM_MARKET_KEYWORD` | Keyword to filter market questions | `Bitcoin Up or Down` |
|
||
| `MM_ENTRY_WINDOW` | Max seconds after open to enter (0 = open only) | `45` |
|
||
| `MM_POLL_INTERVAL` | Seconds between new market polls | `10` |
|
||
| `MM_RECOVERY_BUY` | Enable recovery buy after cut-loss | `false` |
|
||
| `MM_RECOVERY_THRESHOLD` | Minimum dominant-side price to qualify for recovery | `0.70` |
|
||
| `MM_RECOVERY_SIZE` | USDC for recovery buy (0 = use `MM_TRADE_SIZE`) | `0` |
|
||
|
||
### Orderbook Sniper Settings
|
||
|
||
**3-Tier Strategy:** Places orders at 3 price levels with weighted sizing
|
||
|
||
| Variable | Description | Default |
|
||
|---|---|---|
|
||
| `SNIPER_ASSETS` | Comma-separated assets to snipe (e.g. `eth,sol,xrp`) | `eth,sol,xrp` |
|
||
| `SNIPER_TIER1_PRICE` | Highest price tier (e.g. `0.03` = 3c) | `0.03` |
|
||
| `SNIPER_TIER2_PRICE` | Mid price tier (e.g. `0.02` = 2c) | `0.02` |
|
||
| `SNIPER_TIER3_PRICE` | Lowest price tier (e.g. `0.01` = 1c) | `0.01` |
|
||
| `SNIPER_MAX_SHARES` | Max total shares per side (min 5 per tier) | `15` |
|
||
|
||
**Allocation:**
|
||
- Tier 1 (3c): 20% of max shares (min 5)
|
||
- Tier 2 (2c): 30% of max shares (min 5)
|
||
- Tier 3 (1c): 50% of max shares (min 5)
|
||
|
||
**Example with `SNIPER_MAX_SHARES=15`:**
|
||
- 3 shares @ 3c = $0.09
|
||
- 5 shares @ 2c = $0.10
|
||
- 7 shares @ 1c = $0.07
|
||
- **Total per side:** 15 shares = $0.26
|
||
|
||
---
|
||
|
||
## Usage
|
||
|
||
### Terminal UI (local)
|
||
|
||
Runs with an interactive split-panel dashboard (blessed TUI).
|
||
|
||
```bash
|
||
# Copy Trade Bot
|
||
npm start # live trading
|
||
npm run dev # live + auto-reload on file changes
|
||
|
||
# Market Maker Bot
|
||
npm run mm # live trading
|
||
npm run mm-sim # simulation (DRY_RUN=true)
|
||
npm run mm-dev # simulation + auto-reload
|
||
|
||
# Orderbook Sniper Bot
|
||
npm run sniper # live trading
|
||
npm run sniper-sim # simulation
|
||
npm run sniper-dev # simulation + auto-reload
|
||
```
|
||
|
||
### Plain Log Mode (no TUI)
|
||
|
||
Writes plain timestamped text to stdout — suitable for piping, `tail -f`, or PM2.
|
||
|
||
```bash
|
||
# Copy Trade Bot
|
||
npm run bot # live trading
|
||
npm run bot-sim # simulation
|
||
npm run bot-dev # simulation + auto-reload
|
||
|
||
# Market Maker Bot
|
||
npm run mm-bot # live trading
|
||
npm run mm-bot-sim # simulation
|
||
npm run mm-bot-dev # simulation + auto-reload
|
||
```
|
||
|
||
> **Always test with `DRY_RUN=true` (or `*-sim` scripts) first** before committing real funds.
|
||
|
||
---
|
||
|
||
## Running on VPS with PM2
|
||
|
||
Each bot has its own PM2 config file inside the `pm2/` folder.
|
||
|
||
### Install PM2
|
||
|
||
```bash
|
||
npm install -g pm2
|
||
```
|
||
|
||
### Copy Trade Bot
|
||
|
||
```bash
|
||
# Live trading
|
||
pm2 start pm2/copy.config.cjs
|
||
|
||
# Simulation
|
||
pm2 start pm2/copy.config.cjs --env sim
|
||
|
||
# View logs
|
||
pm2 logs polymarket-copy
|
||
tail -f logs/copy-out.log
|
||
|
||
# Management
|
||
pm2 restart polymarket-copy
|
||
pm2 stop polymarket-copy
|
||
pm2 delete polymarket-copy
|
||
```
|
||
|
||
### Market Maker Bot
|
||
|
||
```bash
|
||
# Live trading
|
||
pm2 start pm2/mm.config.cjs
|
||
|
||
# Simulation
|
||
pm2 start pm2/mm.config.cjs --env sim
|
||
|
||
# View logs
|
||
pm2 logs polymarket-mm
|
||
tail -f logs/mm-out.log
|
||
|
||
# Management
|
||
pm2 restart polymarket-mm
|
||
pm2 stop polymarket-mm
|
||
pm2 delete polymarket-mm
|
||
```
|
||
|
||
### Auto-start on reboot
|
||
|
||
```bash
|
||
pm2 startup # generates a startup command — run the command it prints
|
||
pm2 save # saves current process list
|
||
```
|
||
|
||
---
|
||
|
||
## How It Works
|
||
|
||
### Copy Trade Bot Flow
|
||
|
||
```
|
||
WebSocket (RTDS) — real-time trade events from trader
|
||
│
|
||
▼
|
||
Per-market queue (prevents concurrent duplicate buys)
|
||
│
|
||
┌────┴──────┐
|
||
│ │
|
||
BUY SELL
|
||
│ │
|
||
├─ Expiry guard (MIN_MARKET_TIME_LEFT)
|
||
├─ Max position cap ├─ Cancel open orders
|
||
├─ FAK market buy ├─ Reconcile on-chain balance
|
||
│ └─ 0 fill? → GTC fallback ├─ FAK market sell / limit sell
|
||
├─ Place auto-sell GTC └─ Remove position
|
||
└─ Save position
|
||
│
|
||
▼
|
||
Redeemer loop (every REDEEM_INTERVAL seconds)
|
||
→ Check on-chain payout → redeemPositions via Gnosis Safe
|
||
```
|
||
|
||
### Market Maker Flow
|
||
|
||
```
|
||
New Market Detected
|
||
│
|
||
▼
|
||
Split USDC → YES + NO tokens ($0.50 each, zero slippage)
|
||
│
|
||
▼
|
||
Place limit SELL on both sides at MM_SELL_PRICE
|
||
│
|
||
▼
|
||
Monitor fills every few seconds
|
||
│
|
||
┌────┴────┐
|
||
│ │
|
||
Fill Time < MM_CUT_LOSS_TIME
|
||
│ │
|
||
▼ ▼
|
||
Collect Cancel orders → Merge YES+NO back to USDC
|
||
profit (recovery buy optional)
|
||
```
|
||
|
||
---
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
polymarket-terminal/
|
||
├── src/
|
||
│ ├── index.js — Copy trade bot (TUI)
|
||
│ ├── bot.js — Copy trade bot (plain log / PM2)
|
||
│ ├── mm.js — Market maker bot (TUI)
|
||
│ ├── mm-bot.js — Market maker bot (plain log / PM2)
|
||
│ ├── sniper.js — Orderbook sniper bot
|
||
│ │
|
||
│ ├── config/
|
||
│ │ └── index.js — Environment variable loading & validation
|
||
│ │
|
||
│ ├── services/
|
||
│ │ ├── client.js — CLOB client initialization & USDC balance
|
||
│ │ ├── watcher.js — Poll-based trader activity detection
|
||
│ │ ├── wsWatcher.js — WebSocket real-time trade listener
|
||
│ │ ├── executor.js — Buy & sell order execution logic
|
||
│ │ ├── position.js — Position state management (CRUD)
|
||
│ │ ├── autoSell.js — Auto limit-sell placement
|
||
│ │ ├── redeemer.js — Market resolution check & CTF redemption
|
||
│ │ ├── ctf.js — On-chain CTF contract interactions
|
||
│ │ ├── mmDetector.js — Market detection for market maker
|
||
│ │ ├── mmExecutor.js — Market maker strategy execution
|
||
│ │ ├── sniperDetector.js — Market detection for sniper
|
||
│ │ └── sniperExecutor.js — Orderbook sniper order placement
|
||
│ │
|
||
│ ├── ui/
|
||
│ │ └── dashboard.js — Terminal UI (blessed)
|
||
│ │
|
||
│ └── utils/
|
||
│ ├── logger.js — Timestamped logging (TUI + plain modes)
|
||
│ ├── state.js — Atomic JSON state file management
|
||
│ └── simStats.js — Simulation P&L statistics
|
||
│
|
||
├── pm2/
|
||
│ ├── copy.config.cjs — PM2 config for copy trade bot
|
||
│ └── mm.config.cjs — PM2 config for market maker bot
|
||
│
|
||
├── data/ — Runtime state files (gitignored)
|
||
├── logs/ — PM2 log files (gitignored)
|
||
├── .env.example — Configuration template
|
||
├── .gitignore
|
||
└── package.json
|
||
```
|
||
|
||
---
|
||
|
||
## Important Warnings
|
||
|
||
- **Never commit your `.env` file.** Your private key must remain secret. The `.gitignore` already excludes it.
|
||
- **Always start with `DRY_RUN=true`** (or a `*-sim` script) to verify the bot behaves as expected before using real funds.
|
||
- **Use a small `SIZE_PERCENT`** for initial live runs to limit exposure.
|
||
- **Keep MATIC in your EOA wallet** for gas fees (redeem operations and on-chain CTF calls).
|
||
- **This software is provided as-is, with no guarantees.** Prediction market trading carries significant financial risk. You are solely responsible for any losses.
|
||
|
||
---
|
||
|
||
## Credits
|
||
|
||
Built and maintained by **[@direkturcrypto](https://twitter.com/direkturcrypto)**.
|
||
|
||
---
|
||
|
||
## License
|
||
|
||
ISC License — see [LICENSE](LICENSE) for details.
|