mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-14 16:26:57 +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:
@@ -53,7 +53,7 @@ func (at *AutoTrader) executeOpenLongWithRecord(decision *kernel.Decision, actio
|
||||
// Get current price
|
||||
marketData, err := market.GetWithExchange(decision.Symbol, at.exchange)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to get market data for %s: %w", decision.Symbol, err)
|
||||
}
|
||||
|
||||
// Get balance (needed for multiple checks)
|
||||
@@ -117,7 +117,7 @@ func (at *AutoTrader) executeOpenLongWithRecord(decision *kernel.Decision, actio
|
||||
// Open position
|
||||
order, err := at.trader.OpenLong(decision.Symbol, quantity, decision.Leverage)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to open long position for %s: %w", decision.Symbol, err)
|
||||
}
|
||||
|
||||
// Record order ID
|
||||
@@ -170,7 +170,7 @@ func (at *AutoTrader) executeOpenShortWithRecord(decision *kernel.Decision, acti
|
||||
// Get current price
|
||||
marketData, err := market.GetWithExchange(decision.Symbol, at.exchange)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to get market data for %s: %w", decision.Symbol, err)
|
||||
}
|
||||
|
||||
// Get balance (needed for multiple checks)
|
||||
@@ -234,7 +234,7 @@ func (at *AutoTrader) executeOpenShortWithRecord(decision *kernel.Decision, acti
|
||||
// Open position
|
||||
order, err := at.trader.OpenShort(decision.Symbol, quantity, decision.Leverage)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to open short position for %s: %w", decision.Symbol, err)
|
||||
}
|
||||
|
||||
// Record order ID
|
||||
@@ -269,7 +269,7 @@ func (at *AutoTrader) executeCloseLongWithRecord(decision *kernel.Decision, acti
|
||||
// Get current price
|
||||
marketData, err := market.GetWithExchange(decision.Symbol, at.exchange)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to get market data for %s: %w", decision.Symbol, err)
|
||||
}
|
||||
actionRecord.Price = marketData.CurrentPrice
|
||||
|
||||
@@ -311,7 +311,7 @@ func (at *AutoTrader) executeCloseLongWithRecord(decision *kernel.Decision, acti
|
||||
// Close position
|
||||
order, err := at.trader.CloseLong(decision.Symbol, 0) // 0 = close all
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to close long position for %s: %w", decision.Symbol, err)
|
||||
}
|
||||
|
||||
// Record order ID
|
||||
@@ -333,7 +333,7 @@ func (at *AutoTrader) executeCloseShortWithRecord(decision *kernel.Decision, act
|
||||
// Get current price
|
||||
marketData, err := market.GetWithExchange(decision.Symbol, at.exchange)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to get market data for %s: %w", decision.Symbol, err)
|
||||
}
|
||||
actionRecord.Price = marketData.CurrentPrice
|
||||
|
||||
@@ -375,7 +375,7 @@ func (at *AutoTrader) executeCloseShortWithRecord(decision *kernel.Decision, act
|
||||
// Close position
|
||||
order, err := at.trader.CloseShort(decision.Symbol, 0) // 0 = close all
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to close short position for %s: %w", decision.Symbol, err)
|
||||
}
|
||||
|
||||
// Record order ID
|
||||
|
||||
Reference in New Issue
Block a user