mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-15 00:36:56 +08:00
fix: 修復5個關鍵交易bug(保證金計算、部分平倉統計、止損止盈分離、雙向持倉)
## 修復內容 ### 1. 保證金計算錯誤(Critical) - 修正提示詞中的保證金公式(adaptive.txt, nof1.txt, default.txt) - 新增代碼級保證金驗證(auto_trader.go) - 防止開倉時保證金不足錯誤(code=-2019) ### 2. 部分平倉統計錯誤(Medium) - 修改統計邏輯:多次 partial_close 聚合為一筆交易 - 新增追蹤字段:remainingQuantity, accumulatedPnL - 只在完全平倉時計入 TotalTrades++ ### 3. 前端配置覆蓋問題(Medium) - 修正 TraderConfigModal.tsx 條件判斷 - 防止空字符串覆蓋用戶選擇的提示詞 ### 4/5. 動態止損/止盈刪除配對訂單(Critical) - 新增接口:CancelStopLossOrders, CancelTakeProfitOrders - 分離訂單取消邏輯(Binance, Hyperliquid, Aster) - 調整止損時不刪除止盈,反之亦然 ### 7. 雙向持倉模式初始化(Critical) - 新增 setDualSidePosition() 函數 - 在 NewFuturesTrader() 中初始化 Hedge Mode - 防止 code=-4061 錯誤(PositionSide 參數錯誤) ## 影響範圍 - 修改文件:10個 - 新增代碼:+480行 - 刪除代碼:-71行 ## 測試狀態 - ✅ 編譯通過(go build ./...) - ✅ 語法檢查通過 - ⚠️ 需要在測試環境運行驗證實際交易效果
This commit is contained in:
@@ -758,6 +758,32 @@ func (at *AutoTrader) executeOpenLongWithRecord(decision *decision.Decision, act
|
||||
return err
|
||||
}
|
||||
|
||||
// ⚠️ 保证金验证:防止保证金不足错误(code=-2019)
|
||||
// position_size_usd 是名义价值(包含杠杆),实际需要的保证金 = position_size_usd / leverage
|
||||
requiredMargin := decision.PositionSizeUSD / float64(decision.Leverage)
|
||||
|
||||
// 获取当前可用余额
|
||||
balance, err := at.trader.GetBalance()
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取账户余额失败: %w", err)
|
||||
}
|
||||
availableBalance := 0.0
|
||||
if avail, ok := balance["availableBalance"].(float64); ok {
|
||||
availableBalance = avail
|
||||
}
|
||||
|
||||
// 手续费估算(Taker费率 0.04%)
|
||||
estimatedFee := decision.PositionSizeUSD * 0.0004
|
||||
totalRequired := requiredMargin + estimatedFee
|
||||
|
||||
// 验证保证金充足(需要保证金 + 手续费 <= 可用余额)
|
||||
if totalRequired > availableBalance {
|
||||
return fmt.Errorf("❌ 保证金不足: 需要 %.2f USDT(保证金 %.2f + 手续费 %.2f),可用 %.2f USDT。建议降低仓位或杠杆",
|
||||
totalRequired, requiredMargin, estimatedFee, availableBalance)
|
||||
}
|
||||
|
||||
log.Printf(" ✓ 保证金检查通过: 需要 %.2f USDT,可用 %.2f USDT", totalRequired, availableBalance)
|
||||
|
||||
// 计算数量
|
||||
quantity := decision.PositionSizeUSD / marketData.CurrentPrice
|
||||
actionRecord.Quantity = quantity
|
||||
@@ -817,6 +843,32 @@ func (at *AutoTrader) executeOpenShortWithRecord(decision *decision.Decision, ac
|
||||
return err
|
||||
}
|
||||
|
||||
// ⚠️ 保证金验证:防止保证金不足错误(code=-2019)
|
||||
// position_size_usd 是名义价值(包含杠杆),实际需要的保证金 = position_size_usd / leverage
|
||||
requiredMargin := decision.PositionSizeUSD / float64(decision.Leverage)
|
||||
|
||||
// 获取当前可用余额
|
||||
balance, err := at.trader.GetBalance()
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取账户余额失败: %w", err)
|
||||
}
|
||||
availableBalance := 0.0
|
||||
if avail, ok := balance["availableBalance"].(float64); ok {
|
||||
availableBalance = avail
|
||||
}
|
||||
|
||||
// 手续费估算(Taker费率 0.04%)
|
||||
estimatedFee := decision.PositionSizeUSD * 0.0004
|
||||
totalRequired := requiredMargin + estimatedFee
|
||||
|
||||
// 验证保证金充足(需要保证金 + 手续费 <= 可用余额)
|
||||
if totalRequired > availableBalance {
|
||||
return fmt.Errorf("❌ 保证金不足: 需要 %.2f USDT(保证金 %.2f + 手续费 %.2f),可用 %.2f USDT。建议降低仓位或杠杆",
|
||||
totalRequired, requiredMargin, estimatedFee, availableBalance)
|
||||
}
|
||||
|
||||
log.Printf(" ✓ 保证金检查通过: 需要 %.2f USDT,可用 %.2f USDT", totalRequired, availableBalance)
|
||||
|
||||
// 计算数量
|
||||
quantity := decision.PositionSizeUSD / marketData.CurrentPrice
|
||||
actionRecord.Quantity = quantity
|
||||
@@ -953,8 +1005,8 @@ func (at *AutoTrader) executeUpdateStopLossWithRecord(decision *decision.Decisio
|
||||
return fmt.Errorf("空单止损必须高于当前价格 (当前: %.2f, 新止损: %.2f)", marketData.CurrentPrice, decision.NewStopLoss)
|
||||
}
|
||||
|
||||
// 取消旧的止损单(避免多个止损单共存)
|
||||
if err := at.trader.CancelStopOrders(decision.Symbol); err != nil {
|
||||
// 取消旧的止损单(只删除止损单,不影响止盈单)
|
||||
if err := at.trader.CancelStopLossOrders(decision.Symbol); err != nil {
|
||||
log.Printf(" ⚠ 取消旧止损单失败: %v", err)
|
||||
// 不中断执行,继续设置新止损
|
||||
}
|
||||
@@ -1015,8 +1067,8 @@ func (at *AutoTrader) executeUpdateTakeProfitWithRecord(decision *decision.Decis
|
||||
return fmt.Errorf("空单止盈必须低于当前价格 (当前: %.2f, 新止盈: %.2f)", marketData.CurrentPrice, decision.NewTakeProfit)
|
||||
}
|
||||
|
||||
// 取消旧的止盈单(避免多个止盈单共存)
|
||||
if err := at.trader.CancelStopOrders(decision.Symbol); err != nil {
|
||||
// 取消旧的止盈单(只删除止盈单,不影响止损单)
|
||||
if err := at.trader.CancelTakeProfitOrders(decision.Symbol); err != nil {
|
||||
log.Printf(" ⚠ 取消旧止盈单失败: %v", err)
|
||||
// 不中断执行,继续设置新止盈
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user