fix: 修复部分平仓盈利计算错误

问题:部分平仓时,历史记录显示的是全仓位盈利,而非实际平仓部分的盈利

根本原因:
- AnalyzePerformance 使用开仓总数量计算部分平仓的盈利
- 应该使用 action.Quantity(实际平仓数量)而非 openPos["quantity"](总数量)

修复:
- 添加 actualQuantity 变量区分完整平仓和部分平仓
- partial_close 使用 action.Quantity
- 所有相关计算(PnL、PositionValue、MarginUsed)都使用 actualQuantity

影响范围:logger/decision_logger.go:428-465

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: tinkle-community <tinklefund@gmail.com>
This commit is contained in:
ZhouYongyou
2025-11-02 21:26:58 +08:00
parent 21f84824a0
commit 4c2fae9a33

View File

@@ -409,18 +409,24 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna
quantity := openPos["quantity"].(float64) quantity := openPos["quantity"].(float64)
leverage := openPos["leverage"].(int) leverage := openPos["leverage"].(int)
// 对于 partial_close使用实际平仓数量否则使用完整仓位数量
actualQuantity := quantity
if action.Action == "partial_close" {
actualQuantity = action.Quantity
}
// 计算实际盈亏USDT // 计算实际盈亏USDT
// 合约交易 PnL 计算:quantity × 价格差 // 合约交易 PnL 计算:actualQuantity × 价格差
// 注意:杠杆不影响绝对盈亏,只影响保证金需求 // 注意:杠杆不影响绝对盈亏,只影响保证金需求
var pnl float64 var pnl float64
if side == "long" { if side == "long" {
pnl = quantity * (action.Price - openPrice) pnl = actualQuantity * (action.Price - openPrice)
} else { } else {
pnl = quantity * (openPrice - action.Price) pnl = actualQuantity * (openPrice - action.Price)
} }
// 计算盈亏百分比(相对保证金) // 计算盈亏百分比(相对保证金)
positionValue := quantity * openPrice positionValue := actualQuantity * openPrice
marginUsed := positionValue / float64(leverage) marginUsed := positionValue / float64(leverage)
pnlPct := 0.0 pnlPct := 0.0
if marginUsed > 0 { if marginUsed > 0 {
@@ -431,7 +437,7 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna
outcome := TradeOutcome{ outcome := TradeOutcome{
Symbol: symbol, Symbol: symbol,
Side: side, Side: side,
Quantity: quantity, Quantity: actualQuantity,
Leverage: leverage, Leverage: leverage,
OpenPrice: openPrice, OpenPrice: openPrice,
ClosePrice: action.Price, ClosePrice: action.Price,