Automated momentum trading for Polymarket Up/Down markets — detect sharp price moves, enter on the rising side, manage risk with a trailing stop, hedge when conditions flip, and redeem settled positions — all backed by a real-time dashboard.
- Overview
- How the strategy works
- Stack & architecture
- Multi-market & extensibility
- For developers
- Installation
- Usage
- Configuration
- Environment variables
- Disclaimer
The Polymarket Impulse Monitoring Bot is a TypeScript service plus a Next.js control panel. It watches short-lived Up/Down binary markets (e.g. crypto 5m/15m windows), streams prices from the Polymarket CLOB, persists state in MongoDB, and executes trades through your proxy wallet when impulse rules fire.
| Capability | Description |
|---|---|
| 📈 Impulse detection | Configurable jump + limit-price rules over a rolling lookback window |
| 🛡️ Risk | Trailing stop triggers an opposite-side hedge |
| 💰 Settlement | Optional auto-redeem when markets resolve |
| 🖥️ Dashboard | Live prices, chart, position, wallet context, buy history |
| ⚙️ Settings UI | Enable/disable bot and edit parameters (stored in MongoDB) |
The bot implements a momentum-style impulse workflow:
- Market selection — Tracks Up/Down markets matching a configurable slug prefix (e.g.
btc-updown-5m) inside a fixed time window (e.g. 300s or 900s). - Impulse detection — If either side’s price jumps by at least
minJumpfrom the minimum in the lookback window and the price is abovelimitPrice, the move qualifies as an impulse. - Initial buy — On impulse, the bot buys once on the rising side (FAK at best ask). It does not buy both sides on the same impulse.
- Trailing stop — After entry, it tracks the highest price since buy. If price falls by
trailingStopPctfrom that high, the stop triggers. - Hedge — On stop, it buys the opposite side so exposure is conceptually flattened ahead of resolution (Up + Down → $1 at settlement in the binary framing).
- Auto-redeem — When the market resolves, winning positions can be redeemed automatically (when enabled).
- Real-time prices — Backend uses the CLOB WebSocket; the dashboard reflects live Up/Down prices on the chart.
| Layer | Technology |
|---|---|
| Runtime | Node.js 18+, TypeScript |
| Trading / data | @polymarket/clob-client, WebSocket mid/book updates |
| Persistence | MongoDB (impulse_bot_meta, impulse_bot_prices, impulse_bot_positions, impulse_buys, …) |
| API & loop | Express + polling impulse monitor (src/) |
| Dashboard | Next.js 14 (frontend/, default dev port 3004) |
Shared database — The frontend API routes use the same MONGODB_URI / MONGODB_DB as the bot so the UI and backend always see one source of truth (no Redis).
The bot is driven by a slug prefix and window length. Examples:
| Slug prefix | Window (sec) | Example |
|---|---|---|
btc-updown-5m |
300 | Bitcoin 5-minute |
btc-updown-15m |
900 | Bitcoin 15-minute |
eth-updown-5m |
300 | Ethereum 5-minute |
- Set
POLYMARKET_SLUG_PREFIXandIMPULSE_WINDOW_SECONDSin.env, or - Use Settings in the UI (persisted in MongoDB; applied on the next backend poll).
The bot rolls forward to the next market when the current window ends.
The same state machine can be adapted to other domains that expose two-sided prices and executable orders: sports, politics, climate/event markets, or other binary instruments — swap the price feed, executor, and settlement adapters while keeping the config knobs (limitPrice, minJump, lookbackSec, trailingStopPct, buyAmountUsd).
To port the idea into your own system:
- Implement a price feed for two outcomes (bid/ask or mid).
- Implement an order executor for entry and hedge orders.
- Track position state (side,
highestPrice, hedge rules). - Preserve the same configuration surface for comparable behavior.
- Plug in a market selector that defines the active window and rollover (slug + duration is one pattern).
- Node.js 18 or newer
- MongoDB (local or Atlas)
- A Polymarket account with proxy wallet + API credentials workflow as documented below
-
Clone the repository.
-
Install dependencies
npm install cd frontend && npm install && cd ..
-
Environment — copy the example file and edit:
cp .env.example .env
Required highlights
Variable Role POLYMARKET_SLUG_PREFIXMarket family (e.g. btc-updown-5m)IMPULSE_WINDOW_SECONDSWindow in seconds (300 / 900 / …) PRIVATE_KEYEOA key used to sign (keep secret) PROXY_WALLET_ADDRESSPolymarket proxy / Safe address MONGODB_URIMongo connection string MONGODB_DBDatabase name (default polymarket_impulse)Frontend — create
frontend/.envorfrontend/.env.localwith the sameMONGODB_URIandMONGODB_DBso the dashboard APIs read/write shared state. -
Polymarket API credential (one-time; after
npm run buildor usets-nodeagainst source):npm run build npx ts-node -e " require('dotenv/config'); const { createCredential } = require('./dist/security/createCredential'); createCredential(); "
-
Build
npm run build cd frontend && npm run build && cd ..
Backend
npm run devFrontend
cd frontend && npm run devOpen http://localhost:3004 for the dashboard and settings.
npm run build
cd frontend && npm run build
pm2 start ecosystem.config.cjsTypical processes:
impulse-bot— trading loop + APIimpulse-frontend— Next.js on port 3004
Parameters can be set in .env (defaults / bootstrap) and overridden from the Settings page (MongoDB). The backend refreshes config on its poll cycle.
- Live Up / Down prices (WebSocket when connected)
- Position, position value, wallet balance, current market slug / condition
- Chart — window prices, limit reference, impulse markers
| Parameter | Default (env) | Description |
|---|---|---|
| Slug prefix | from POLYMARKET_SLUG_PREFIX |
Prefix; full slug adds timestamp segment |
| Window (sec) | IMPULSE_WINDOW_SECONDS |
e.g. 300 (5m), 900 (15m) |
| Limit price | 0.55 |
Minimum price to arm an impulse |
| Min jump | 0.05 |
Minimum rise vs lookback min |
| Lookback (sec) | 60 |
Rolling window for jump detection |
| Trailing stop % | 5 |
Drawdown from high → hedge |
| Buy amount (USD) | 10 |
Notional for entry / hedge orders |
| Poll interval (ms) | 2000 |
Backend poll cadence |
Bot control — Enable / disable is stored in MongoDB and honored on the next poll.
| Variable | Default | Description |
|---|---|---|
POLYMARKET_SLUG_PREFIX |
— | Market prefix (e.g. btc-updown-15m) |
IMPULSE_WINDOW_SECONDS |
900 |
Market window (seconds) |
IMPULSE_LIMIT_PRICE |
0.55 |
Min price for impulse |
IMPULSE_MIN_JUMP |
0.05 |
Min jump vs lookback min |
IMPULSE_LOOKBACK_SEC |
60 |
Lookback window (seconds) |
IMPULSE_TRAILING_STOP_PCT |
5 |
Trailing stop (percent) |
IMPULSE_BUY_AMOUNT_USD |
10 |
Order size (USD) |
IMPULSE_POLL_INTERVAL_MS |
2000 |
Poll interval (ms) |
ENABLE_IMPULSE_BOT |
true |
Master enable (unless "false") |
ENABLE_AUTO_REDEEM |
true |
Auto-redeem resolved positions |
PRIVATE_KEY |
— | Ethereum private key |
PROXY_WALLET_ADDRESS |
— | Polymarket proxy address |
CLOB_API_URL |
https://clob.polymarket.com |
CLOB base URL |
CHAIN_ID |
137 |
Polygon mainnet |
MONGODB_URI |
— | MongoDB URI |
MONGODB_DB |
polymarket_impulse |
Database name |
API_PORT |
3003 |
Backend HTTP port |
Built with TypeScript, MongoDB, and Next.js — happy shipping. 🚀

