Files
polymarket-reverse-arbitrag…/README.md
T

270 lines
7.0 KiB
Markdown
Raw Normal View History

2026-06-28 23:29:56 +08:00
# Polymarket Reverse Arbitrage Bot
2026-06-28 23:29:56 +08:00
TypeScript automation for my Polymarket reverse strategy on **15-minute BTC/ETH Up or Down** markets.
2026-06-28 23:29:56 +08:00
---
2026-06-28 23:29:56 +08:00
## My Polymarket account
<img width="815" height="291" alt="image" src="https://github.com/user-attachments/assets/0971eb6d-de7e-4f9a-82a1-14a2163db209" />
2026-06-28 23:29:56 +08:00
| | |
|---|---|
| **Profile** | [@odahoa](https://polymarket.com/@odahoa?tab=activity) |
| **Username** | `odahoa` |
| **Proxy wallet** | `0xe2511c9e41c5e762887e538b1d6e7221807aa237` |
| **Markets** | `btc-updown-15m`, `eth-updown-15m` |
2026-06-28 23:29:56 +08:00
All activity, positions, and PnL live on my profile:
**https://polymarket.com/@odahoa?tab=activity**
2026-06-28 23:29:56 +08:00
This bot trades **from that account** — it automates what I already do manually. It is not copy trading and does not watch any other wallet.
2026-06-28 23:29:56 +08:00
---
2026-06-28 23:29:56 +08:00
## Overview
Polymarket runs 15-minute windows like:
> **Bitcoin Up or Down — 1:45PM2:00PM ET**
Each window has two tokens:
| Token | Wins when |
|-------|-----------|
| **Up** | Price at end ≥ price at start |
| **Down** | Price at end < price at start |
Winning tokens pay **$1.00**. Losing tokens pay **$0.00**.
My strategy — the **reverse bot** — posts limit **BUY** orders on **both sides** every window:
1. **Cheap reversal side (710¢)** on the underdog outcome
2. **Expensive hedge side (9095¢)** on the favorite outcome
That is the same pattern visible on my [activity tab](https://polymarket.com/@odahoa?tab=activity): round limit prices (7¢, 8¢, 10¢ … 95¢), 2090 shares per fill, no sells — hold to resolution.
---
## Why "reverse"?
Early in a window, price often trends one way:
```
2026-06-28 23:29:56 +08:00
BTC pumps in first 10 minutes
→ Up token ~9097¢ (favorite)
→ Down token ~310¢ (underdog)
```
2026-06-28 23:29:56 +08:00
The crowd prices the underdog as nearly dead. The **reverse bet** is: *it flips before the window closes*.
| Leg | Outcome | Entry | If it wins |
|-----|---------|-------|------------|
| **Reverse** | Underdog | 710¢ | ~1014× |
| **Hedge** | Favorite | 9095¢ | ~511% |
Only one side pays $1 per window. I run both legs because:
- Cheap fills are rare but pay huge when they hit.
- Hedge fills are smaller profit but hit more often.
- Over hundreds of windows, a few reversals cover many losses.
---
## How I trade (manual → bot)
From my account history:
| Pattern | Detail |
|---------|--------|
| Markets | BTC & ETH 15m Up/Down only |
| Order type | Limit BUY only — never sell |
| Cheap leg | Fills at 710¢ (sometimes 525¢) on underdog |
| Hedge leg | Fills at 9095¢ on favorite |
| Both sides | Same window — e.g. Down @ 95¢ and Up @ 15¢ |
| Size | 2090 shares per order |
The bot replaces hand-placing every limit order each window.
---
## Bot logic
Every **5 seconds** (configurable):
```
2026-06-28 23:29:56 +08:00
1. Scan active btc-updown-15m / eth-updown-15m markets
2. Load Up & Down order books (CLOB API)
3. Underdog = outcome with lower best ask
4. Favorite = the other outcome
5. Post limit BUYs on underdog @ 7¢, 8¢, 9¢, 10¢
6. Post limit BUYs on favorite @ 90¢–95¢ (if hedge enabled)
7. Skip price levels already posted this session
```
2026-06-28 23:29:56 +08:00
### Cheap leg — underdog @ 710¢
```
2026-06-28 23:29:56 +08:00
Down best ask = 4¢ → bot bids 7¢, 8¢, 9¢, 10¢ on Down
```
2026-06-28 23:29:56 +08:00
If Down reverses and wins:
```
2026-06-28 23:29:56 +08:00
90 shares × 8¢ = $7.20 in
90 shares × $1 = $90.00 out → +$82.80 (~1,150%)
```
2026-06-28 23:29:56 +08:00
### Hedge leg — favorite @ 9095¢
```
2026-06-28 23:29:56 +08:00
Up best ask = 97¢ → bot bids 90¢–95¢ on Up
```
2026-06-28 23:29:56 +08:00
If Up holds and wins:
```
2026-06-28 23:29:56 +08:00
52 shares × 95¢ = $49.40 in
52 shares × $1 = $52.00 out → +$2.60 (~5%)
```
2026-06-28 23:29:56 +08:00
---
2026-06-28 23:29:56 +08:00
## Example window
2026-06-28 23:29:56 +08:00
**Market:** Bitcoin Up or Down — 1:452:00 PM ET
**BTC pumped early** → Up favored, Down cheap
2026-06-28 23:29:56 +08:00
| Token | Book | Bot posts |
|-------|------|-----------|
| Up (favorite) | ask 97¢ | BUY limits @ 9095¢ |
| Down (underdog) | ask 4¢ | BUY limits @ 710¢ |
2026-06-28 23:29:56 +08:00
| Result | Cheap leg | Hedge leg |
|--------|-----------|-----------|
| Up wins | Down → $0 | Up → small profit |
| Down reverses | Down → big profit | Up → $0 |
2026-06-28 23:29:56 +08:00
---
2026-06-28 23:29:56 +08:00
## Return table
2026-06-28 23:29:56 +08:00
| Buy price | Payout | Return if win |
|-----------|--------|---------------|
| 7¢ | $1.00 | +1,329% |
| 8¢ | $1.00 | +1,150% |
| 9¢ | $1.00 | +1,011% |
| 10¢ | $1.00 | +900% |
| 95¢ | $1.00 | +5% |
2026-06-28 23:29:56 +08:00
Most 710¢ bets go to zero. Edge comes from occasional reversals at high multiples.
2026-06-28 23:29:56 +08:00
---
2026-06-28 23:29:56 +08:00
## Quick start
2026-06-28 23:29:56 +08:00
```bash
git clone https://github.com/abwhaoms502/polymarket-reverse-arbitrage-bot
cd reverse-bot
npm install
cp .env.example .env
npm start # dry-run: logs orders, no submission
```
2026-06-28 23:29:56 +08:00
### Go live on @odahoa
2026-06-28 23:29:56 +08:00
```env
DRY_RUN=false
PRIVATE_KEY=0x... # account signing key
FUNDER_ADDRESS=0xe2511c9e41c5e762887e538b1d6e7221807aa237 # @odahoa proxy wallet
SIGNATURE_TYPE=2
```
2026-06-28 23:29:56 +08:00
| `SIGNATURE_TYPE` | Use for |
|------------------|---------|
| `0` | EOA / MetaMask |
| `2` | Gnosis Safe proxy *(typical Polymarket account)* |
| `3` | POLY_1271 deposit wallet |
2026-06-28 23:29:56 +08:00
---
2026-06-28 23:29:56 +08:00
## Config
2026-06-28 23:29:56 +08:00
### Strategy
| Variable | Default | Description |
|----------|---------|-------------|
| `CHEAP_BUY_MIN` | `0.07` | Low end of reversal bids |
| `CHEAP_BUY_MAX` | `0.10` | High end of reversal bids |
| `CHEAP_ORDER_USDC` | `10` | USDC per cheap limit order |
| `ENABLE_EXPENSIVE_HEDGE` | `true` | Post 9095¢ favorite bids |
| `EXPENSIVE_BUY_MIN` | `0.90` | Low end of hedge bids |
| `EXPENSIVE_BUY_MAX` | `0.95` | High end of hedge bids |
| `EXPENSIVE_ORDER_USDC` | `50` | USDC per hedge limit order |
| `MAX_SHARES_PER_ORDER` | `90` | Max shares per order |
### Markets & timing
| Variable | Default | Description |
|----------|---------|-------------|
| `MARKET_SLUG_PREFIXES` | `btc-updown-15m,eth-updown-15m` | Markets to scan |
| `POLL_INTERVAL_MS` | `5000` | Scan interval |
| `MINUTES_BEFORE_CLOSE_MIN` | `0` | Start trading N min into window |
| `MINUTES_BEFORE_CLOSE_MAX` | `15` | Stop trading N min before close |
Trade only late window (when cheap tokens show up):
```env
MINUTES_BEFORE_CLOSE_MIN=3
MINUTES_BEFORE_CLOSE_MAX=12
```
### Safety
| Variable | Default | Description |
|----------|---------|-------------|
| `DRY_RUN` | `true` | Log only — no real orders |
---
## Project layout
```
reverse-bot/
├── src/
│ ├── index.ts # main loop
│ ├── market-scanner.ts # active 15m markets + books
│ ├── strategy.ts # underdog/favorite + limit prices
│ ├── trader.ts # CLOB order submission
│ └── config.ts
├── .env.example
└── package.json
```
---
## Commands
```bash
npm start # run bot
npm run dev # run with hot reload
npm run build # compile TypeScript
```
---
## Risks
- **Most cheap bids lose.** 710¢ tokens frequently expire worthless.
- **Limits may not fill.** Bidding 7¢ when ask is 4¢ waits for sellers.
- **Both legs can't both win.** One side always goes to $0.
- **Real money.** Test with `DRY_RUN=true` first.
---
## Links
- My profile: https://polymarket.com/@odahoa
- My activity: https://polymarket.com/@odahoa?tab=activity
- Polymarket settings: https://polymarket.com/settings