fix: async entry race condition — 'entering' status prevents premature exit

During async executeEntry goroutine, the 300ms sleep between legs
left the position vulnerable to checkExit() from the main loop.
Added intermediate Status='entering' that checkExit/checkScaleIn
skip ('entering' != 'open'), switched to 'open' only after both
legs are placed.
This commit is contained in:
jackyu66git
2026-05-03 22:40:48 +08:00
parent 29f2072e90
commit 721abc02a9
+3 -2
View File
@@ -47,7 +47,7 @@ type ArbPosition struct {
LastScaleAt time.Time // when we last scaled in LastScaleAt time.Time // when we last scaled in
StartedAt time.Time StartedAt time.Time
ExitedAt time.Time ExitedAt time.Time
Status string // "open", "closed" Status string // "entering", "open", "closed"
RealizedPnl float64 RealizedPnl float64
ErrorLog string ErrorLog string
@@ -311,7 +311,7 @@ func (t *Trader) executeEntry(opp *ArbOpportunity, store *PriceStore, notifier *
Coin: opp.Coin, Coin: opp.Coin,
AmountUSD: t.cfg.TradeAmountUSD, AmountUSD: t.cfg.TradeAmountUSD,
StartedAt: time.Now(), StartedAt: time.Now(),
Status: "open", Status: "entering", // prevent checkExit/checkScaleIn during leg placement
ScaleLevels: 0, ScaleLevels: 0,
} }
@@ -361,6 +361,7 @@ func (t *Trader) executeEntry(opp *ArbOpportunity, store *PriceStore, notifier *
} }
pos.LastScaleAt = time.Now() pos.LastScaleAt = time.Now()
pos.Status = "open" // both legs placed, ready for Tick/exit logic
log.Printf("[Trader] %s: Opened %s | Long %s @ %.2f Short %s @ %.2f | $%.0f", log.Printf("[Trader] %s: Opened %s | Long %s @ %.2f Short %s @ %.2f | $%.0f",
pos.Coin, pos.Direction, pos.LongLeg.Exchange, pos.LongLeg.EntryPrice, pos.Coin, pos.Direction, pos.LongLeg.Exchange, pos.LongLeg.EntryPrice,