feat: real trading mode, auto-stop after 5 trades, HL testnet support

- config.json: test_mode=false, ready for sim/testnet trading
- trader.go: auto-stop after 5 real trades, exchange response logging,
  Stop()/Start() API, shuttingDown flag for graceful stop
- dashboard.go: POST /api/stop + POST /api/start endpoints,
  trading status in SSE stats
- exchange/hyperliquid.go: switch HL WS to testnet endpoint
- exchange/hyperliquid_trade.go: switch REST to testnet endpoint,
  support base64 + 32-byte EVM private keys
- main.go: listen on trader.StopCh (graceful, no process exit)
- scanner.go: trim TrackedCoins to only 6 core coins (DOGE/LINK/ONDO/OP/WIF/ARB)
- .gitignore: ignore main binary
This commit is contained in:
jackyu66git
2026-05-04 14:31:52 +08:00
parent 5fa3e1bac8
commit e5ea78ffd2
8 changed files with 146 additions and 177 deletions
+21
View File
@@ -240,6 +240,8 @@ func (d *Dashboard) Run() {
mux.HandleFunc("GET /api/trade/", d.handleTradeDetail)
mux.HandleFunc("GET /api/connections", d.handleConnStatus) // P3-5
mux.HandleFunc("GET /events", d.handleSSE)
mux.HandleFunc("POST /api/stop", d.handleStop)
mux.HandleFunc("POST /api/start", d.handleStart)
server := &http.Server{
Addr: d.addr,
@@ -479,6 +481,15 @@ func (d *Dashboard) broadcastLoop() {
d.connMu.RUnlock()
stats["connections"] = connInfo
// Trading status
stats["trading"] = map[string]interface{}{
"active": !d.trader.IsShuttingDown(),
"mode": d.trader.ModeLabel(),
"test": d.trader.cfg.TestMode,
"target": d.trader.realTradesTarget,
"done": d.trader.realTradesDone,
}
// Per-exchange fund tracking
exFunds := d.trader.GetExchangeFunds()
exFundsMap := make(map[string]map[string]float64, len(exFunds))
@@ -708,6 +719,16 @@ func (d *Dashboard) handleSSE(w http.ResponseWriter, r *http.Request) {
}
}
func (d *Dashboard) handleStop(w http.ResponseWriter, r *http.Request) {
d.trader.Stop()
writeJSON(w, map[string]string{"status": "stopped", "message": "Trading stopped, positions closing"})
}
func (d *Dashboard) handleStart(w http.ResponseWriter, r *http.Request) {
d.trader.Start()
writeJSON(w, map[string]string{"status": "started", "message": "Trading resumed"})
}
func writeJSON(w http.ResponseWriter, v interface{}) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(v)