mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-02 02:21:19 +08:00
更新 logger:支持新增的三個動作類型
更新內容:
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,
因為還有剩餘倉位可能繼續交易
This commit is contained in:
@@ -50,9 +50,9 @@ type PositionSnapshot struct {
|
|||||||
|
|
||||||
// DecisionAction 决策动作
|
// DecisionAction 决策动作
|
||||||
type DecisionAction struct {
|
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"` // 币种
|
Symbol string `json:"symbol"` // 币种
|
||||||
Quantity float64 `json:"quantity"` // 数量
|
Quantity float64 `json:"quantity"` // 数量(部分平仓时使用)
|
||||||
Leverage int `json:"leverage"` // 杠杆(开仓时)
|
Leverage int `json:"leverage"` // 杠杆(开仓时)
|
||||||
Price float64 `json:"price"` // 执行价格
|
Price float64 `json:"price"` // 执行价格
|
||||||
OrderID int64 `json:"order_id"` // 订单ID
|
OrderID int64 `json:"order_id"` // 订单ID
|
||||||
@@ -243,8 +243,9 @@ func (l *DecisionLogger) GetStatistics() (*Statistics, error) {
|
|||||||
switch action.Action {
|
switch action.Action {
|
||||||
case "open_long", "open_short":
|
case "open_long", "open_short":
|
||||||
stats.TotalOpenPositions++
|
stats.TotalOpenPositions++
|
||||||
case "close_long", "close_short":
|
case "close_long", "close_short", "partial_close":
|
||||||
stats.TotalClosePositions++
|
stats.TotalClosePositions++
|
||||||
|
// update_stop_loss 和 update_take_profit 不計入統計
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,11 +349,22 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna
|
|||||||
|
|
||||||
symbol := action.Symbol
|
symbol := action.Symbol
|
||||||
side := ""
|
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"
|
side = "long"
|
||||||
} else if action.Action == "open_short" || action.Action == "close_short" {
|
} else if action.Action == "open_short" || action.Action == "close_short" {
|
||||||
side = "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
|
posKey := symbol + "_" + side
|
||||||
|
|
||||||
switch action.Action {
|
switch action.Action {
|
||||||
@@ -368,6 +380,7 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna
|
|||||||
case "close_long", "close_short":
|
case "close_long", "close_short":
|
||||||
// 移除已平仓记录
|
// 移除已平仓记录
|
||||||
delete(openPositions, posKey)
|
delete(openPositions, posKey)
|
||||||
|
// partial_close 不處理,保留持倉記錄
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -382,11 +395,23 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna
|
|||||||
|
|
||||||
symbol := action.Symbol
|
symbol := action.Symbol
|
||||||
side := ""
|
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"
|
side = "long"
|
||||||
} else if action.Action == "open_short" || action.Action == "close_short" {
|
} else if action.Action == "open_short" || action.Action == "close_short" {
|
||||||
side = "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,区分多空持仓
|
posKey := symbol + "_" + side // 使用symbol_side作为key,区分多空持仓
|
||||||
|
|
||||||
switch action.Action {
|
switch action.Action {
|
||||||
@@ -400,7 +425,7 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna
|
|||||||
"leverage": action.Leverage,
|
"leverage": action.Leverage,
|
||||||
}
|
}
|
||||||
|
|
||||||
case "close_long", "close_short":
|
case "close_long", "close_short", "partial_close":
|
||||||
// 查找对应的开仓记录(可能来自预填充或当前窗口)
|
// 查找对应的开仓记录(可能来自预填充或当前窗口)
|
||||||
if openPos, exists := openPositions[posKey]; exists {
|
if openPos, exists := openPositions[posKey]; exists {
|
||||||
openPrice := openPos["openPrice"].(float64)
|
openPrice := openPos["openPrice"].(float64)
|
||||||
@@ -472,8 +497,10 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna
|
|||||||
stats.LosingTrades++
|
stats.LosingTrades++
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移除已平仓记录
|
// 移除已平仓记录(partial_close 不刪除,因為還有剩餘倉位)
|
||||||
delete(openPositions, posKey)
|
if action.Action != "partial_close" {
|
||||||
|
delete(openPositions, posKey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user