feat: async TryEntry with goroutine, non-blocking main loop
- TryEntry now spawns a goroutine for order placement - Main loop continues at 50-250ms even during entry - 'entering' map prevents duplicate entries on same coin - Async cleanup of entering state on completion
This commit is contained in:
@@ -118,6 +118,7 @@ type Trader struct {
|
||||
db *db.DB
|
||||
mu sync.Mutex
|
||||
positions map[string]*ArbPosition // coin -> position
|
||||
entering map[string]bool // coin -> being entered (async goroutine)
|
||||
lastTradeTime map[string]time.Time
|
||||
closedTrades []TradeRecord // history of closed trades (current session)
|
||||
|
||||
@@ -160,6 +161,7 @@ func NewTrader(cfg *Config, database *db.DB) *Trader {
|
||||
bitget: bt,
|
||||
hyperliquid: hl,
|
||||
positions: make(map[string]*ArbPosition),
|
||||
entering: make(map[string]bool),
|
||||
lastTradeTime: make(map[string]time.Time),
|
||||
}
|
||||
|
||||
@@ -235,6 +237,8 @@ func (t *Trader) Tick(store *PriceStore, notifier *Notifier) {
|
||||
}
|
||||
|
||||
// TryEntry opens initial position when threshold is met.
|
||||
// Returns true if entry was accepted (async goroutine will place orders).
|
||||
// Non-blocking — the main loop is not stalled by REST calls or the 300ms leg delay.
|
||||
func (t *Trader) TryEntry(opp *ArbOpportunity, store *PriceStore, notifier *Notifier) bool {
|
||||
if !t.IsConfigured() {
|
||||
return false
|
||||
@@ -252,13 +256,25 @@ func (t *Trader) TryEntry(opp *ArbOpportunity, store *PriceStore, notifier *Noti
|
||||
t.mu.Unlock()
|
||||
return false
|
||||
}
|
||||
if t.entering[opp.Coin] {
|
||||
t.mu.Unlock()
|
||||
return false
|
||||
}
|
||||
if lastTime, ok := t.lastTradeTime[opp.Coin]; ok && time.Since(lastTime) < 30*time.Second {
|
||||
t.mu.Unlock()
|
||||
return false
|
||||
}
|
||||
t.entering[opp.Coin] = true
|
||||
t.mu.Unlock()
|
||||
|
||||
return t.executeEntry(opp, store, notifier)
|
||||
// Async goroutine — placeOrder calls (REST or mock) don't block the main loop
|
||||
go func() {
|
||||
t.executeEntry(opp, store, notifier)
|
||||
t.mu.Lock()
|
||||
delete(t.entering, opp.Coin)
|
||||
t.mu.Unlock()
|
||||
}()
|
||||
return true
|
||||
}
|
||||
|
||||
// executeEntry places both legs using the scan-time prices from ArbOpportunity.
|
||||
|
||||
Reference in New Issue
Block a user