mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-12 15:26:55 +08:00
fix(trader): harden API calls with timeouts, strict balance parsing, error context
- binance/bybit/gate: SDK default http.DefaultClient has no timeout; use a dedicated 30s-timeout client so a hung connection cannot stall the loop - bybit: stop mutating http.DefaultClient.Transport, which leaked the referer header into every other HTTP request in the process - add types.ParseFloatField: empty exchange fields stay zero, but malformed numeric values now surface as errors instead of silently becoming zero balances (applied to GetBalance across 8 exchanges) - wrap order/market-data errors in auto_trader_orders and okx cancel paths with symbol context; log per-order cancel failures in okx CancelAllOrders
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"nofx/hook"
|
||||
"nofx/logger"
|
||||
"strings"
|
||||
@@ -63,6 +64,9 @@ type FuturesTrader struct {
|
||||
// NewFuturesTrader creates futures trader
|
||||
func NewFuturesTrader(apiKey, secretKey string, userId string) *FuturesTrader {
|
||||
client := futures.NewClient(apiKey, secretKey)
|
||||
// The SDK defaults to http.DefaultClient, which has no timeout — a hung
|
||||
// connection would stall the trading loop indefinitely.
|
||||
client.HTTPClient = &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
hookRes := hook.HookExec[hook.NewBinanceTraderResult](hook.NEW_BINANCE_TRADER, userId, client)
|
||||
if hookRes != nil && hookRes.GetResult() != nil {
|
||||
|
||||
@@ -30,9 +30,17 @@ func (t *FuturesTrader) GetBalance() (map[string]interface{}, error) {
|
||||
}
|
||||
|
||||
result := make(map[string]interface{})
|
||||
result["totalWalletBalance"], _ = strconv.ParseFloat(account.TotalWalletBalance, 64)
|
||||
result["availableBalance"], _ = strconv.ParseFloat(account.AvailableBalance, 64)
|
||||
result["totalUnrealizedProfit"], _ = strconv.ParseFloat(account.TotalUnrealizedProfit, 64)
|
||||
for field, value := range map[string]string{
|
||||
"totalWalletBalance": account.TotalWalletBalance,
|
||||
"availableBalance": account.AvailableBalance,
|
||||
"totalUnrealizedProfit": account.TotalUnrealizedProfit,
|
||||
} {
|
||||
parsed, parseErr := types.ParseFloatField(field, value)
|
||||
if parseErr != nil {
|
||||
return nil, parseErr
|
||||
}
|
||||
result[field] = parsed
|
||||
}
|
||||
|
||||
logger.Infof("✓ Binance API returned: total balance=%s, available=%s, unrealized PnL=%s",
|
||||
account.TotalWalletBalance,
|
||||
|
||||
Reference in New Issue
Block a user