Exchange Monitor Go
Cross-exchange perpetual futures arbitrage monitoring and automated trading system. Tracks Bitget ↔ HyperLiquid spread in real time, executes simulated trades at configurable thresholds.
Architecture
┌──────────────┐
│ Bitget │◄──── ticker WS (trading exchange)
└──────────────┘
PriceStore ─────────┼──────────────┤
│ HyperLiquid │◄──── webData2 WS (trading exchange)
└──────────────┘
│
┌─────────▼─────────┐
│ ScanBGHL (200ms) │
│ BG ↔ HL only │
└─────────┬─────────┘
│
┌───────────────▼────────────────┐
│ Trader │
│ TryEntry (async goroutine) │
│ → placeOrder (REST/mock) │
│ Tick / Exit / Scale-in │
│ Config-driven thresholds │
└───────────────┬────────────────┘
│
┌─────────▼─────────┐
│ SpreadWindowTracker│
│ (opportunity life) │
└─────────┬─────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
┌─────▼─────┐ ┌────────▼───────┐ ┌─────▼─────┐
│ Notifier │ │ Dashboard │ │ DB │
│ Telegram │ │ :8888 │ │ SQLite │
│ │ │ Stats calc │ │ trades.db │
│ │ │ Blacklist UI │ │ │
└───────────┘ └────────────────┘ └───────────┘
Tracked Coins
| Coin | Bitget | HyperLiquid |
|---|---|---|
| DOGE | DOGEUSDT | DOGE |
| LINK | LINKUSDT | LINK |
| ONDO | ONDOUSDT | ONDO |
| OP | OPUSDT | OP |
| WIF | WIFUSDT | WIF |
| ARB | ARBUSDT | ARB |
Note: Binance and dYdX have been removed — only Bitget and HyperLiquid are monitored.
Requirements
- Go 1.25+
- WebSocket connectivity to Bitget and HyperLiquid
Quick Start
cd exchange-monitor-go
go build -o exchange-monitor .
# Edit config.json to set parameters
./exchange-monitor
Then open http://localhost:8888 for the Web dashboard.
Configuration
config.json (all trading parameters)
All numerical parameters are defined in config.json — no need to edit Go source:
| Parameter | Default | Description |
|---|---|---|
test_mode |
true |
Simulate orders with mock fills (no real API calls) |
trade_enabled |
true |
Enable automated trading |
scan_interval_ms |
200 |
Scanner loop interval (ms) |
arb_threshold |
0.03 |
Min net profit % to trigger alert |
trade_threshold |
0.10 |
Min net profit % to execute trade |
trade_amount_usd |
5 |
USD per leg (per order) |
trade_cooldown_ms |
30000 |
Cooldown between same-coin trades (ms) |
max_positions |
5 |
Maximum concurrent open positions |
initial_capital |
1000 |
Starting capital in USD (for PnL %) |
mock_slippage_pct |
0.005 |
Simulated slippage per leg (%) |
blacklist_duration_sec |
3600 |
Coin blacklist duration (seconds) |
taker_fee_bitget |
0.060 |
Bitget taker fee rate (%) |
taker_fee_hyperliquid |
0.045 |
HyperLiquid taker fee rate (%) |
take_profit_pct |
0.20 |
Net profit % threshold for take-profit |
spread_reverse_exit_pct |
0 |
Spread convergence/reversal exit (0 = exit when ≤ 0) |
position_timeout_sec |
1800 |
Max position hold time before auto-close (30 min) |
leg_delay_ms |
300 |
Delay between placing long and short legs |
reversal_tolerance_pct |
0.1 |
Price movement tolerance for entry sanity check |
scale_step_pct |
0.10 |
Spread widening % to trigger each scale-in level |
scale_cooldown_sec |
5 |
Minimum seconds between scale-ins |
.env (secrets only)
Secrets (API keys) go in .env — never checked into git:
| Variable | Description |
|---|---|
TELEGRAM_BOT_TOKEN |
Telegram bot token for notifications |
TELEGRAM_CHAT_ID |
Target chat ID for notifications |
BITGET_API_KEY |
Bitget API key (skipped if test_mode) |
BITGET_API_SECRET |
Bitget API secret |
BITGET_PASSPHRASE |
Bitget passphrase |
HL_PRIVATE_KEY |
HyperLiquid ed25519 private key hex |
HL_ADDRESS |
HyperLiquid wallet address |
Priority:
.envvars >config.json> code defaults.
Fee Model
All trades use taker (market orders). Only Bitget and HyperLiquid:
| Exchange | Taker Fee |
|---|---|
| Bitget | configurable (taker_fee_bitget, default 0.060%) |
| HyperLiquid | configurable (taker_fee_hyperliquid, default 0.045%) |
Round trip (2 legs entry + 2 legs exit): configurable, default 0.21% total fees.
Trading Logic
- Scanner runs every
scan_interval_ms, checks all coins for BG ↔ HL spread - Entry when net profit ≥
trade_threshold(after full round-trip fees)- Uses scan-time prices directly (no re-read to avoid WS jitter)
- Async goroutine —
TryEntryreturns immediately,executeEntryruns in background - Reversal tolerance check prevents entry on flipped spreads
enteringmap prevents duplicate entries on same coin
- Scale-in adds another leg-worth when spread widens another
scale_step_pct(default 0.10%) - Exit conditions (whichever hits first):
- Net profit ≥
take_profit_pct→ 利润止盈(大盈利退出) - Spread narrowed to ≤ 0.02% + netPnl > 0 → 价差收敛止盈(小盈利退出)
- Spread flipped negative → 价差反转平仓(紧急止损)
- Position held >
position_timeout_sec→ 超时平仓
- Net profit ≥
- Direction: BG → HL (buy BG, sell HL) or HL → BG (buy HL, sell BG)
Blacklist Mechanism
- Positions held open for > 10 minutes without converging are auto-closed and blacklisted
- Blacklisted coins are skipped for
blacklist_duration_sec(default 1 hour) - Blacklist state visible on the dashboard
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 net profit first hits threshold
- Tracks real peak net profit during the window
- Logs window duration + peak when spread converges below threshold
- Covers both directions (BG→HL and HL→BG) independently
Web Dashboard
Built-in HTTP server at :8888 with real-time SSE push (1-second refresh):
- Price table — live prices from both exchanges
- BG↔HL spread — per-coin arbitrage spread
- Open positions — live PnL estimate, scaling level, duration, sorting by coin
- Trade history — past trades with detail view
- Blacklist — currently blacklisted coins and remaining time
- Connection status — exchange health (online / stale / offline)
DB & Persistence
- SQLite at current directory (auto-deleted on each restart in test mode)
- Tracks open positions across restarts (
restoreOpenPositions) - Stores all closed trades with full PnL details
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 # config.json + .env hierarchical config
├── config.json # All trading parameters (editable)
├── types.go # PriceStore, TrackedCoin, ArbOpportunity
├── scanner.go # ScanBGHL — arbitrage scanner
├── trader.go # Position management, entry/exit/scale-in
├── dashboard.go # Web server + SSE + stats calc
├── toaster.go # Telegram notifications
├── static.go # Embedded web static files
├── .env # Secrets only (API keys)
├── exchange/
│ ├── connector.go # Generic WS connector with reconnect
│ ├── hyperliquid.go # HyperLiquid webData2 WS
│ ├── hyperliquid_trade.go # HL REST trade API
│ ├── bitget.go # Bitget ticker WS (TextPing for stability)
│ ├── bitget_trade.go # Bitget REST trade API
│ ├── 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.