mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-04 11:30:58 +08:00
fix(binance): initialize dual-side position mode to prevent code=-4061 errors
## Problem
When opening positions with explicit `PositionSide` parameter (LONG/SHORT), Binance API returned **code=-4061** error:
```
"No need to change position side."
"code":-4061
```
**Root cause:**
- Binance accounts default to **single-side position mode** ("One-Way Mode")
- In this mode, `PositionSide` parameter is **not allowed**
- Code使用了 `PositionSide` 參數 (LONG/SHORT),但帳戶未啟用雙向持倉模式
**Position Mode Comparison:**
| Mode | PositionSide Required | Can Hold Long+Short Simultaneously |
|------|----------------------|------------------------------------|
| One-Way (default) | ❌ No | ❌ No |
| Hedge Mode | ✅ **Required** | ✅ Yes |
## Solution
### 1. Added setDualSidePosition() function
Automatically enables Hedge Mode during trader initialization:
```go
func (t *FuturesTrader) setDualSidePosition() error {
err := t.client.NewChangePositionModeService().
DualSide(true). // Enable Hedge Mode
Do(context.Background())
if err != nil {
// Ignore "No need to change" error (already in Hedge Mode)
if strings.Contains(err.Error(), "No need to change position side") {
log.Printf("✓ Account already in Hedge Mode")
return nil
}
return err
}
log.Printf("✓ Switched to Hedge Mode")
return nil
}
```
### 2. Called in NewFuturesTrader()
Runs automatically when creating trader instance:
```go
func NewFuturesTrader(apiKey, secretKey string) *FuturesTrader {
trader := &FuturesTrader{...}
// Initialize Hedge Mode
if err := trader.setDualSidePosition(); err != nil {
log.Printf("⚠️ Failed to set Hedge Mode: %v", err)
}
return trader
}
```
## Impact
- ✅ Prevents code=-4061 errors when opening positions
- ✅ Enables simultaneous long+short positions (if needed)
- ✅ Fails gracefully if account already in Hedge Mode
- ⚠️ **One-time change**: Once enabled, cannot revert to One-Way Mode with open positions
## Testing
- ✅ Compiles successfully
- ⚠️ Requires Binance testnet/mainnet validation:
- [ ] First initialization → switches to Hedge Mode
- [ ] Subsequent initializations → ignores "No need to change" error
- [ ] Open long position with PositionSide=LONG → succeeds
- [ ] Open short position with PositionSide=SHORT → succeeds
## Code Changes
```
trader/binance_futures.go:
- Line 3-12: Added strings import
- Line 33-47: Modified NewFuturesTrader() to call setDualSidePosition()
- Line 49-69: New function setDualSidePosition()
Total: +25 lines
```
## References
- Binance Futures API: https://binance-docs.github.io/apidocs/futures/en/#change-position-mode-trade
- Error code=-4061: "No need to change position side."
- PositionSide ENUM: BOTH (One-Way) | LONG | SHORT (Hedge Mode)
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -32,10 +33,40 @@ type FuturesTrader struct {
|
||||
// NewFuturesTrader 创建合约交易器
|
||||
func NewFuturesTrader(apiKey, secretKey string) *FuturesTrader {
|
||||
client := futures.NewClient(apiKey, secretKey)
|
||||
return &FuturesTrader{
|
||||
trader := &FuturesTrader{
|
||||
client: client,
|
||||
cacheDuration: 15 * time.Second, // 15秒缓存
|
||||
}
|
||||
|
||||
// 设置双向持仓模式(Hedge Mode)
|
||||
// 这是必需的,因为代码中使用了 PositionSide (LONG/SHORT)
|
||||
if err := trader.setDualSidePosition(); err != nil {
|
||||
log.Printf("⚠️ 设置双向持仓模式失败: %v (如果已是双向模式则忽略此警告)", err)
|
||||
}
|
||||
|
||||
return trader
|
||||
}
|
||||
|
||||
// setDualSidePosition 设置双向持仓模式(初始化时调用)
|
||||
func (t *FuturesTrader) setDualSidePosition() error {
|
||||
// 尝试设置双向持仓模式
|
||||
err := t.client.NewChangePositionModeService().
|
||||
DualSide(true). // true = 双向持仓(Hedge Mode)
|
||||
Do(context.Background())
|
||||
|
||||
if err != nil {
|
||||
// 如果错误信息包含"No need to change",说明已经是双向持仓模式
|
||||
if strings.Contains(err.Error(), "No need to change position side") {
|
||||
log.Printf(" ✓ 账户已是双向持仓模式(Hedge Mode)")
|
||||
return nil
|
||||
}
|
||||
// 其他错误则返回(但在调用方不会中断初始化)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf(" ✓ 账户已切换为双向持仓模式(Hedge Mode)")
|
||||
log.Printf(" ℹ️ 双向持仓模式允许同时持有多单和空单")
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBalance 获取账户余额(带缓存)
|
||||
|
||||
Reference in New Issue
Block a user