Merge pull request #1374 from c9s/feature/grid2/fix

FIX: retry to get open orders only for 5 times and do not sync orders…
This commit is contained in:
kbearXD 2023-10-30 17:26:38 +08:00 committed by GitHub
commit 3491b93c53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 13 deletions

View File

@ -5,10 +5,9 @@ import (
"errors"
"strconv"
backoff2 "github.com/cenkalti/backoff/v4"
"github.com/cenkalti/backoff/v4"
"github.com/c9s/bbgo/pkg/types"
"github.com/c9s/bbgo/pkg/util/backoff"
)
type advancedOrderCancelService interface {
@ -18,7 +17,7 @@ type advancedOrderCancelService interface {
}
func QueryOrderUntilFilled(ctx context.Context, queryOrderService types.ExchangeOrderQueryService, symbol string, orderId uint64) (o *types.Order, err error) {
err = backoff.RetryGeneral(ctx, func() (err2 error) {
var op = func() (err2 error) {
o, err2 = queryOrderService.QueryOrder(ctx, types.OrderQuery{
Symbol: symbol,
OrderID: strconv.FormatUint(orderId, 10),
@ -33,20 +32,30 @@ func QueryOrderUntilFilled(ctx context.Context, queryOrderService types.Exchange
}
return err2
})
}
err = GeneralBackoff(ctx, op)
return o, err
}
func GeneralBackoff(ctx context.Context, op backoff2.Operation) (err error) {
err = backoff2.Retry(op, backoff2.WithContext(
backoff2.WithMaxRetries(
backoff2.NewExponentialBackOff(),
func GeneralBackoff(ctx context.Context, op backoff.Operation) (err error) {
err = backoff.Retry(op, backoff.WithContext(
backoff.WithMaxRetries(
backoff.NewExponentialBackOff(),
101),
ctx))
return err
}
func GeneralLiteBackoff(ctx context.Context, op backoff.Operation) (err error) {
err = backoff.Retry(op, backoff.WithContext(
backoff.WithMaxRetries(
backoff.NewExponentialBackOff(),
5),
ctx))
return err
}
func QueryOpenOrdersUntilSuccessful(ctx context.Context, ex types.Exchange, symbol string) (openOrders []types.Order, err error) {
var op = func() (err2 error) {
openOrders, err2 = ex.QueryOpenOrders(ctx, symbol)
@ -57,6 +66,16 @@ func QueryOpenOrdersUntilSuccessful(ctx context.Context, ex types.Exchange, symb
return openOrders, err
}
func QueryOpenOrdersUntilSuccessfulLite(ctx context.Context, ex types.Exchange, symbol string) (openOrders []types.Order, err error) {
var op = func() (err2 error) {
openOrders, err2 = ex.QueryOpenOrders(ctx, symbol)
return err2
}
err = GeneralLiteBackoff(ctx, op)
return openOrders, err
}
func QueryOrderUntilSuccessful(ctx context.Context, query types.ExchangeOrderQueryService, opts types.OrderQuery) (order *types.Order, err error) {
var op = func() (err2 error) {
order, err2 = query.QueryOrder(ctx, opts)

View File

@ -89,9 +89,10 @@ func (s *Strategy) recoverActiveOrdersPeriodically(ctx context.Context) {
func syncActiveOrders(ctx context.Context, opts SyncActiveOrdersOpts) error {
opts.logger.Infof("[ActiveOrderRecover] syncActiveOrders")
notAddNonExistingOpenOrdersAfter := time.Now().Add(-5 * time.Minute)
// only sync orders which is updated over 3 min, because we may receive from websocket and handle it twice
syncBefore := time.Now().Add(-3 * time.Minute)
openOrders, err := retry.QueryOpenOrdersUntilSuccessful(ctx, opts.exchange, opts.activeOrderBook.Symbol)
openOrders, err := retry.QueryOpenOrdersUntilSuccessfulLite(ctx, opts.exchange, opts.activeOrderBook.Symbol)
if err != nil {
opts.logger.WithError(err).Error("[ActiveOrderRecover] failed to query open orders, skip this time")
return errors.Wrapf(err, "[ActiveOrderRecover] failed to query open orders, skip this time")
@ -116,6 +117,10 @@ func syncActiveOrders(ctx context.Context, opts SyncActiveOrdersOpts) error {
delete(openOrdersMap, activeOrder.OrderID)
} else {
opts.logger.Infof("found active order #%d is not in the open orders, updating...", activeOrder.OrderID)
if activeOrder.UpdateTime.After(syncBefore) {
opts.logger.Infof("active order #%d is updated in 3 min, skip updating...", activeOrder.OrderID)
continue
}
// sleep 100ms to avoid DDOS
time.Sleep(100 * time.Millisecond)
@ -130,8 +135,10 @@ func syncActiveOrders(ctx context.Context, opts SyncActiveOrdersOpts) error {
// update open orders not in active orders
for _, openOrder := range openOrdersMap {
// we don't add open orders into active orderbook if updated in 5 min
if openOrder.UpdateTime.After(notAddNonExistingOpenOrdersAfter) {
opts.logger.Infof("found open order #%d is not in active orderbook, updating...", openOrder.OrderID)
// we don't add open orders into active orderbook if updated in 3 min, because we may receive message from websocket and add it twice.
if openOrder.UpdateTime.After(syncBefore) {
opts.logger.Infof("open order #%d is updated in 3 min, skip updating...", openOrder.OrderID)
continue
}

View File

@ -54,7 +54,7 @@ func (s *Strategy) recover(ctx context.Context) error {
activeOrderBook := s.orderExecutor.ActiveMakerOrders()
activeOrders := activeOrderBook.Orders()
openOrders, err := retry.QueryOpenOrdersUntilSuccessful(ctx, s.session.Exchange, s.Symbol)
openOrders, err := retry.QueryOpenOrdersUntilSuccessfulLite(ctx, s.session.Exchange, s.Symbol)
if err != nil {
return err
}