217 lines
9.8 KiB
Markdown
217 lines
9.8 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
cd exchange-monitor-go
|
|
go build -o exchange-monitor .
|
|
# Edit config.json to set parameters
|
|
./exchange-monitor
|
|
```
|
|
|
|
Then open [http://localhost:8888](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:** `.env` vars > `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
|
|
|
|
1. **Scanner** runs every `scan_interval_ms`, checks all coins for BG ↔ HL spread
|
|
2. **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** — `TryEntry` returns immediately, `executeEntry` runs in background
|
|
- Reversal tolerance check prevents entry on flipped spreads
|
|
- `entering` map prevents duplicate entries on same coin
|
|
3. **Scale-in** adds another leg-worth when spread widens another `scale_step_pct` (default 0.10%)
|
|
4. **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`** → **超时平仓**
|
|
5. **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.
|