9.7 KiB
Exchange Monitor Go
Cross-exchange perpetual futures arbitrage scanner and automated trading system. Monitors real-time prices from 4 exchanges via WebSocket, identifies Bitget ↔ HyperLiquid arbitrage opportunities, executes maker-fee trades, and provides a real-time Web dashboard.
Architecture
┌──────────────┐
┌──────────────┤ Binance │◄──── bookTicker WS (price reference)
│ └──────────────┘
│ ┌──────────────┐
│──────────────┤ Bitget │◄──── ticker WS (trading exchange)
│ └──────────────┘
PriceStore ─────────┼──────────────┤
│ │ HyperLiquid │◄──── webData2 WS (trading exchange)
│ └──────────────┘
│ ┌──────────────┐
└──────────────┤ dYdX │◄──── v4_markets WS (price reference)
└──────────────┘
│
┌─────────▼─────────┐
│ ScanBGHL (200ms) │
│ BG ↔ HL only │
└─────────┬─────────┘
│
┌───────────────▼────────────────┐
│ Trader (trading logic only) │
│ TryEntry / Tick / Exit │
│ Maker fees, scale-in, stop │
│ Synchronous entry (no goroutine)│
│ NO display/stat calculations │
└───────────────┬────────────────┘
│
┌─────────▼─────────┐
│ SpreadWindowTracker│
│ (opportunity life) │
└─────────┬─────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
┌─────▼─────┐ ┌────────▼───────┐ ┌─────▼─────┐
│ Notifier │ │ Dashboard │ │ DB │
│ TG │ │ :8888 │ │ SQLite │
│ │ │ Stats calc │ │ trades.db │
│ │ │ (calcDetailed) │ │ │
└───────────┘ └────────────────┘ └───────────┘
Tracked Coins
| Coin | Binance | Bitget | HyperLiquid | dYdX |
|---|---|---|---|---|
| DOGE | DOGEUSDT | DOGEUSDT | DOGE | DOGE |
| LINK | LINKUSDT | LINKUSDT | LINK | LINK |
| ONDO | ONDOUSDT | ONDOUSDT | ONDO | ONDO |
| OP | OPUSDT | OPUSDT | OP | OP |
| WIF | WIFUSDT | WIFUSDT | WIF | WIF |
| ARB | ARBUSDT | ARBUSDT | ARB | ARB |
- Bitget / HyperLiquid — trading exchanges (limit orders with maker fees)
- Binance / dYdX — price reference only
Requirements
- Go 1.25+
- WebSocket connectivity to all 4 exchanges
Quick Start
cd exchange-monitor-go
go build -o exchange-monitor .
# Edit .env to configure (token, threshold, etc.)
./exchange-monitor
Or use the startup script (auto-compiles if sources changed, cleans stale port):
./start.sh
Then open http://localhost:8888 for the Web dashboard.
Configuration (.env)
| Variable | Code Default | Description |
|---|---|---|
TELEGRAM_BOT_TOKEN |
— | Telegram bot token for notifications |
TELEGRAM_CHAT_ID |
— | Target chat ID for notifications |
TRADE_ENABLED |
false |
Enable real trading (1 to enable) |
TRADE_THRESHOLD |
0.15 |
Min net profit % to enter (after fees) |
TRADE_AMOUNT_USD |
10 |
USD per leg |
TRADE_COOLDOWN_MS |
30000 |
Cooldown between same-coin trades (ms) |
TEST_MODE |
false |
Simulate orders (no real API calls) |
MOCK_SLIPPAGE_PCT |
0.005 |
Simulated slippage per leg (%) |
BITGET_API_KEY / BITGET_API_SECRET / BITGET_PASSPHRASE |
— | Bitget API credentials (test mode skips) |
HL_PRIVATE_KEY / HL_ADDRESS |
— | HyperLiquid wallet credentials (test mode skips) |
Fee Model
All trades use maker (limit orders), no rebate. Only Bitget and HyperLiquid are used for trading:
| Exchange | Maker | Taker |
|---|---|---|
| Bitget | 0.020% | 0.040% |
| HyperLiquid | 0.015% | 0.035% |
Round trip (2 legs entry + 2 legs exit): 0.07% total fees.
Trading Logic
- Scanner runs every 500ms, checks all 6 coins for BG ↔ HL spread
- Entry when net profit ≥
TRADE_THRESHOLD(after full round-trip fees)- Uses scan-time prices directly (no re-read from store to avoid WS jitter)
- Synchronous execution in the scanner tick (no goroutine delay)
- Direction sanity check (0.1% tolerance) prevents entry on reversed spreads
- Scale-in adds another leg-worth when spread widens another 0.10%
- Exit conditions (whichever hits first):
- Spread converges to ≤ 0.02% → 价差收敛,止盈平仓
- Spread reverses below -0.02% → 价差反转,止盈平仓
- Position held over 30 minutes → 超时平仓
- Direction: BG → HL (buy BG, sell HL) or HL → BG (buy HL, sell BG)
Spread Window Monitoring
SpreadWindowTracker runs every scan tick and measures how long each coin's spread stays above the trade threshold:
- Records window start time when netProfit first hits threshold
- Tracks real peak netProfit during the window
- Logs window duration + peak when spread converges below threshold (sub-100ms windows filtered as noise)
- Covers both directions (BG→HL and HL→BG) independently
- Uses the same
netProfit()fee model as the scanner for exact consistency
Log output example:
[SpreadWindow] ONDO BG->HL exceeded threshold for 1.4s (peak net=+0.1520%)
[SpreadWindow] OP HL->BG exceeded threshold for 3.2s (peak net=+0.1310%)
Notifications
All notifications sent to Telegram (via TELEGRAM_BOT_TOKEN):
- 开仓 — entry notification with prices, direction, spread, amount
- 平仓 — exit notification with PnL breakdown, fees, convergence analysis
- 每小时 — summary of open positions (duration, amount)
- Uses HTML parse mode for bold formatting
Web Dashboard
Built-in HTTP server at :8888 with real-time SSE push (1-second refresh):
- Price table — live prices from all exchanges with bid-ask spread
- BG↔HL spread — per-coin arbitrage spread with chart
- Open positions — live PnL estimate, scaling level, duration
- Arb scan results — current arbitrage opportunities
- Trade history — past trades with detail view
- Connection status — exchange health (online / stale / offline)
- Charts rendered via Chart.js (loaded from CDN)
DB & Persistence
- SQLite at
data/trades.db - Tracks open positions across restarts
- Stores all closed trades with full PnL details
- Historical stats merged with in-memory session stats on startup
Signals
| Signal | Action |
|---|---|
Ctrl+C / SIGINT |
Graceful shutdown (closes all WS connections) |
SIGUSR1 |
Dump convergence statistics to trade_stats.txt |
Project Structure
exchange-monitor-go/
├── main.go # Entry point, WS startup, main loop
├── config.go # .env + config.json hierarchical config
├── types.go # PriceStore, TrackedCoin, ArbOpportunity
├── scanner.go # ScanBGHL — arbitrage scanner
├── trader.go # Position management, entry/exit/scale-in (pure trading logic)
├── dashboard.go # Web server + SSE + stats calc (display layer)
├── toaster.go # Telegram notifications
├── static.go # Embedded web static files
├── start.sh # Startup script (port check + build + run)
├── .env # Local configuration (TELEGRAM, API keys, thresholds)
├── exchange/
│ ├── connector.go # Generic WS connector with reconnect
│ ├── binance.go # Binance bookTicker WS
│ ├── hyperliquid.go # HyperLiquid webData2 WS
│ ├── hyperliquid_trade.go # HL REST trade API
│ ├── bitget.go # Bitget ticker WS
│ ├── bitget_trade.go # Bitget REST trade API
│ ├── dydx.go # dYdX v4_markets WS
│ ├── helpers.go # Package helpers
│ └── ping.go # Accessibility check tools
├── db/
│ ├── db.go # SQLite open/migrate
│ └── trade_repo.go # Trade record queries
└── web/static/
├── index.html # Dashboard HTML
├── app.js # SSE client + UI logic
└── style.css # Dashboard CSS
Disclaimer
This software is for educational/research purposes. Use at your own risk. Cryptocurrency trading involves substantial risk of loss.