fix: retryClose saves trade record and persists to DB on success
This commit is contained in:
@@ -51,6 +51,15 @@ type ArbPosition struct {
|
||||
RealizedPnl float64
|
||||
ErrorLog string
|
||||
|
||||
// Exit metadata — saved when close is first attempted; reused by retryClose
|
||||
ExitDiffPct float64 // spread % at exit trigger
|
||||
ExitNetPnl float64 // net PnL % at exit trigger
|
||||
ExitLongPnl float64 // long leg PnL %
|
||||
ExitShortPnl float64 // short leg PnL %
|
||||
ExitTotalFees float64 // total fee %
|
||||
ExitConvergence string // convergence label
|
||||
ExitReasonText string // reason for exit
|
||||
|
||||
// Track all entry prices for weighted-average PnL across scale-ins (Issue #2)
|
||||
LongEntryPrices []float64 // all long entry prices (initial + scale-ins)
|
||||
ShortEntryPrices []float64 // all short entry prices (initial + scale-ins)
|
||||
@@ -534,6 +543,15 @@ func (t *Trader) checkExit(pos *ArbPosition, bgP, hlP, diffPct float64, notifier
|
||||
pos.LongLeg.ExitPrice = longCurrent
|
||||
pos.ShortLeg.ExitPrice = shortCurrent
|
||||
|
||||
// Save exit metadata for retryClose in case closeBothLegs fails
|
||||
pos.ExitDiffPct = diffPct
|
||||
pos.ExitNetPnl = netPnl
|
||||
pos.ExitLongPnl = longPnl
|
||||
pos.ExitShortPnl = shortPnl
|
||||
pos.ExitTotalFees = totalFees
|
||||
pos.ExitConvergence = convergenceLabel
|
||||
pos.ExitReasonText = exitReason
|
||||
|
||||
closeErr := t.closeBothLegs(pos)
|
||||
|
||||
if closeErr != "" {
|
||||
@@ -691,17 +709,41 @@ func (t *Trader) retryClose(pos *ArbPosition, bgP, hlP float64, notifier *Notifi
|
||||
|
||||
closeErr := t.closeBothLegs(pos)
|
||||
if closeErr == "" {
|
||||
// All legs finally closed — mark as done
|
||||
// All legs finally closed — record + persist
|
||||
pos.Status = "closed"
|
||||
pos.ExitedAt = time.Now()
|
||||
|
||||
elapsed := time.Since(pos.StartedAt)
|
||||
record := TradeRecord{
|
||||
Coin: pos.Coin,
|
||||
Direction: pos.Direction,
|
||||
EntrySpread: pos.EntrySpread,
|
||||
ExitSpread: pos.ExitDiffPct,
|
||||
PnlPct: pos.ExitNetPnl,
|
||||
Convergence: pos.ExitConvergence,
|
||||
Reason: pos.ExitReasonText,
|
||||
Duration: elapsed.Round(time.Second).String(),
|
||||
OpenedAt: pos.StartedAt,
|
||||
ClosedAt: pos.ExitedAt,
|
||||
ScaleLevels: pos.ScaleLevels,
|
||||
AmountUSD: pos.AmountUSD,
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
delete(t.positions, pos.Coin)
|
||||
t.lastTradeTime[pos.Coin] = time.Now()
|
||||
t.closedTrades = append(t.closedTrades, record)
|
||||
t.mu.Unlock()
|
||||
|
||||
if t.db != nil {
|
||||
t.persistTrade(pos, pos.ExitDiffPct, pos.ExitConvergence, pos.ExitReasonText,
|
||||
pos.ExitNetPnl, pos.ExitLongPnl, pos.ExitShortPnl, pos.ExitTotalFees)
|
||||
}
|
||||
|
||||
notifier.Send(fmt.Sprintf(
|
||||
"<b>[平仓重试成功]</b> %s/USDT %s\n"+
|
||||
" 之前失败: %s\n"+
|
||||
" 已成功关掉所有腿\n", pos.Coin, pos.Direction, pos.ErrorLog))
|
||||
" 已成功关掉所有腿 | 盈亏: %+.4f%%\n", pos.Coin, pos.Direction, pos.ErrorLog, pos.ExitNetPnl))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user