From ed8bb94deaebd32899e26fa061bbcf759ad352c2 Mon Sep 17 00:00:00 2001 From: ZhouYongyou <128128010+zhouyongyou@users.noreply.github.com> Date: Sun, 2 Nov 2025 06:11:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20logger=EF=BC=9A=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=96=B0=E5=A2=9E=E7=9A=84=E4=B8=89=E5=80=8B=E5=8B=95?= =?UTF-8?q?=E4=BD=9C=E9=A1=9E=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新內容: 1. DecisionAction 註釋:添加 update_stop_loss, update_take_profit, partial_close 2. GetStatistics:partial_close 計入 TotalClosePositions 3. AnalyzePerformance 預填充邏輯:處理 partial_close(不刪除持倉記錄) 4. AnalyzePerformance 分析邏輯: - partial_close 正確判斷持倉方向 - 記錄部分平倉的盈虧統計 - 保留持倉記錄(因為還有剩餘倉位) 說明:partial_close 會記錄盈虧,但不刪除 openPositions, 因為還有剩餘倉位可能繼續交易 --- logger/decision_logger.go | 43 +++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/logger/decision_logger.go b/logger/decision_logger.go index efa5ab74..9891ce71 100644 --- a/logger/decision_logger.go +++ b/logger/decision_logger.go @@ -50,9 +50,9 @@ type PositionSnapshot struct { // DecisionAction 决策动作 type DecisionAction struct { - Action string `json:"action"` // open_long, open_short, close_long, close_short + Action string `json:"action"` // open_long, open_short, close_long, close_short, update_stop_loss, update_take_profit, partial_close Symbol string `json:"symbol"` // 币种 - Quantity float64 `json:"quantity"` // 数量 + Quantity float64 `json:"quantity"` // 数量(部分平仓时使用) Leverage int `json:"leverage"` // 杠杆(开仓时) Price float64 `json:"price"` // 执行价格 OrderID int64 `json:"order_id"` // 订单ID @@ -243,8 +243,9 @@ func (l *DecisionLogger) GetStatistics() (*Statistics, error) { switch action.Action { case "open_long", "open_short": stats.TotalOpenPositions++ - case "close_long", "close_short": + case "close_long", "close_short", "partial_close": stats.TotalClosePositions++ + // update_stop_loss 和 update_take_profit 不計入統計 } } } @@ -348,11 +349,22 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna symbol := action.Symbol side := "" - if action.Action == "open_long" || action.Action == "close_long" { + if action.Action == "open_long" || action.Action == "close_long" || action.Action == "partial_close" { side = "long" } else if action.Action == "open_short" || action.Action == "close_short" { side = "short" } + + // partial_close 需要根據持倉判斷方向 + if action.Action == "partial_close" && side == "" { + for key, pos := range openPositions { + if posSymbol, _ := pos["side"].(string); key == symbol+"_"+posSymbol { + side = posSymbol + break + } + } + } + posKey := symbol + "_" + side switch action.Action { @@ -368,6 +380,7 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna case "close_long", "close_short": // 移除已平仓记录 delete(openPositions, posKey) + // partial_close 不處理,保留持倉記錄 } } } @@ -382,11 +395,23 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna symbol := action.Symbol side := "" - if action.Action == "open_long" || action.Action == "close_long" { + if action.Action == "open_long" || action.Action == "close_long" || action.Action == "partial_close" { side = "long" } else if action.Action == "open_short" || action.Action == "close_short" { side = "short" } + + // partial_close 需要根據持倉判斷方向 + if action.Action == "partial_close" { + // 從 openPositions 中查找持倉方向 + for key, pos := range openPositions { + if posSymbol, _ := pos["side"].(string); key == symbol+"_"+posSymbol { + side = posSymbol + break + } + } + } + posKey := symbol + "_" + side // 使用symbol_side作为key,区分多空持仓 switch action.Action { @@ -400,7 +425,7 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna "leverage": action.Leverage, } - case "close_long", "close_short": + case "close_long", "close_short", "partial_close": // 查找对应的开仓记录(可能来自预填充或当前窗口) if openPos, exists := openPositions[posKey]; exists { openPrice := openPos["openPrice"].(float64) @@ -472,8 +497,10 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna stats.LosingTrades++ } - // 移除已平仓记录 - delete(openPositions, posKey) + // 移除已平仓记录(partial_close 不刪除,因為還有剩餘倉位) + if action.Action != "partial_close" { + delete(openPositions, posKey) + } } } }