bbgo_origin/pkg/strategy/grid2/active_order_recover.go

99 lines
2.4 KiB
Go
Raw Normal View History

2023-10-02 03:56:15 +00:00
package grid2
import (
"context"
"time"
"github.com/c9s/bbgo/pkg/exchange/retry"
"github.com/c9s/bbgo/pkg/strategy/common"
"github.com/c9s/bbgo/pkg/types"
"github.com/c9s/bbgo/pkg/util"
2023-10-02 03:56:15 +00:00
)
2023-10-23 05:17:20 +00:00
func (s *Strategy) initializeRecoverC() bool {
2023-10-16 08:02:43 +00:00
s.mu.Lock()
defer s.mu.Unlock()
2023-10-17 08:13:05 +00:00
isInitialize := false
2023-10-16 08:02:43 +00:00
2023-10-23 05:17:20 +00:00
if s.recoverC == nil {
2023-10-17 08:13:05 +00:00
s.logger.Info("initializing recover channel")
2023-10-23 05:17:20 +00:00
s.recoverC = make(chan struct{}, 1)
2023-10-16 08:02:43 +00:00
} else {
2023-10-17 08:13:05 +00:00
s.logger.Info("recover channel is already initialized, trigger active orders recover")
isInitialize = true
select {
2023-10-23 05:17:20 +00:00
case s.recoverC <- struct{}{}:
2023-10-17 08:13:05 +00:00
s.logger.Info("trigger active orders recover")
default:
s.logger.Info("activeOrdersRecoverC is full")
}
2023-10-16 08:02:43 +00:00
}
2023-10-17 08:13:05 +00:00
return isInitialize
2023-10-16 08:02:43 +00:00
}
func (s *Strategy) recoverActiveOrdersPeriodically(ctx context.Context) {
2023-10-17 08:13:05 +00:00
// every time we activeOrdersRecoverC receive signal, do active orders recover
2023-10-23 05:17:20 +00:00
if isInitialize := s.initializeRecoverC(); isInitialize {
2023-10-16 08:02:43 +00:00
return
}
2023-10-02 03:56:15 +00:00
// make ticker's interval random in 25 min ~ 35 min
interval := util.MillisecondsJitter(25*time.Minute, 10*60*1000)
s.logger.Infof("[ActiveOrderRecover] interval: %s", interval)
2023-10-02 03:56:15 +00:00
metricsLabel := s.newPrometheusLabels()
orderQueryService, ok := s.session.Exchange.(types.ExchangeOrderQueryService)
if !ok {
s.logger.Errorf("exchange %s doesn't support ExchangeOrderQueryService, please check it", s.session.ExchangeName)
return
}
opts := common.SyncActiveOrdersOpts{
Logger: s.logger,
Exchange: s.session.Exchange,
OrderQueryService: orderQueryService,
ActiveOrderBook: s.orderExecutor.ActiveMakerOrders(),
}
ticker := time.NewTicker(interval)
defer ticker.Stop()
2023-11-07 02:56:19 +00:00
var lastRecoverTime time.Time
2023-10-02 03:56:15 +00:00
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
2023-11-07 02:56:19 +00:00
s.recoverC <- struct{}{}
case <-s.recoverC:
if !time.Now().After(lastRecoverTime.Add(10 * time.Minute)) {
continue
}
openOrders, err := retry.QueryOpenOrdersUntilSuccessfulLite(ctx, s.session.Exchange, s.Symbol)
2023-11-07 09:00:29 +00:00
if err != nil {
s.logger.WithError(err).Error("[ActiveOrderRecover] failed to query open orders, skip this time")
2023-11-07 09:00:29 +00:00
continue
}
if metricsNumOfOpenOrders != nil {
metricsNumOfOpenOrders.With(metricsLabel).Set(float64(len(openOrders)))
2023-10-02 03:56:15 +00:00
}
opts.OpenOrders = openOrders
if err := common.SyncActiveOrders(ctx, opts); err != nil {
log.WithError(err).Errorf("unable to sync active orders")
} else {
lastRecoverTime = time.Now()
}
}
2023-10-02 03:56:15 +00:00
}
}