mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
bbgo: add types.ExchangeOrderQueryService support for checking canceled orders
This commit is contained in:
parent
768428a7eb
commit
b3d58a9e05
|
@ -3,17 +3,21 @@ package bbgo
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/exchange/retry"
|
||||||
"github.com/c9s/bbgo/pkg/sigchan"
|
"github.com/c9s/bbgo/pkg/sigchan"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DefaultCancelOrderWaitTime = 20 * time.Millisecond
|
const DefaultCancelOrderWaitTime = 20 * time.Millisecond
|
||||||
|
const DefaultOrderCancelTimeout = 5 * time.Second
|
||||||
|
|
||||||
// ActiveOrderBook manages the local active order books.
|
// ActiveOrderBook manages the local active order books.
|
||||||
//
|
//
|
||||||
|
@ -35,6 +39,7 @@ type ActiveOrderBook struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
cancelOrderWaitTime time.Duration
|
cancelOrderWaitTime time.Duration
|
||||||
|
cancelOrderTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewActiveOrderBook(symbol string) *ActiveOrderBook {
|
func NewActiveOrderBook(symbol string) *ActiveOrderBook {
|
||||||
|
@ -44,6 +49,7 @@ func NewActiveOrderBook(symbol string) *ActiveOrderBook {
|
||||||
pendingOrderUpdates: types.NewSyncOrderMap(),
|
pendingOrderUpdates: types.NewSyncOrderMap(),
|
||||||
C: sigchan.New(1),
|
C: sigchan.New(1),
|
||||||
cancelOrderWaitTime: DefaultCancelOrderWaitTime,
|
cancelOrderWaitTime: DefaultCancelOrderWaitTime,
|
||||||
|
cancelOrderTimeout: DefaultOrderCancelTimeout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +180,7 @@ func (b *ActiveOrderBook) GracefulCancel(ctx context.Context, ex types.Exchange,
|
||||||
hasSymbol := b.Symbol != ""
|
hasSymbol := b.Symbol != ""
|
||||||
for _, o := range orders {
|
for _, o := range orders {
|
||||||
if hasSymbol && o.Symbol != b.Symbol {
|
if hasSymbol && o.Symbol != b.Symbol {
|
||||||
return errors.New("[ActiveOrderBook] cancel " + b.Symbol + " orderbook with different symbol: " + o.Symbol)
|
return fmt.Errorf("[ActiveOrderBook] canceling %s orderbook with different symbol: %s", b.Symbol, o.Symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,7 +192,6 @@ func (b *ActiveOrderBook) GracefulCancel(ctx context.Context, ex types.Exchange,
|
||||||
|
|
||||||
log.Debugf("[ActiveOrderBook] gracefully cancelling %s orders...", b.Symbol)
|
log.Debugf("[ActiveOrderBook] gracefully cancelling %s orders...", b.Symbol)
|
||||||
waitTime := b.cancelOrderWaitTime
|
waitTime := b.cancelOrderWaitTime
|
||||||
orderCancelTimeout := 5 * time.Second
|
|
||||||
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
// ensure every order is canceled
|
// ensure every order is canceled
|
||||||
|
@ -204,7 +209,7 @@ func (b *ActiveOrderBook) GracefulCancel(ctx context.Context, ex types.Exchange,
|
||||||
log.Debugf("[ActiveOrderBook] waiting %s for %d %s orders to be cancelled...", waitTime, len(orders), b.Symbol)
|
log.Debugf("[ActiveOrderBook] waiting %s for %d %s orders to be cancelled...", waitTime, len(orders), b.Symbol)
|
||||||
|
|
||||||
if cancelAll {
|
if cancelAll {
|
||||||
clear, err := b.waitAllClear(ctx, waitTime, orderCancelTimeout)
|
clear, err := b.waitAllClear(ctx, waitTime, b.cancelOrderTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, context.Canceled) {
|
if !errors.Is(err, context.Canceled) {
|
||||||
log.WithError(err).Errorf("order cancel error")
|
log.WithError(err).Errorf("order cancel error")
|
||||||
|
@ -230,6 +235,31 @@ func (b *ActiveOrderBook) GracefulCancel(ctx context.Context, ex types.Exchange,
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify the current open orders via the RESTful API
|
// verify the current open orders via the RESTful API
|
||||||
|
if orderQueryService, ok := ex.(types.ExchangeOrderQueryService); ok {
|
||||||
|
for idx, o := range orders {
|
||||||
|
retOrder, err := retry.QueryOrderUntilSuccessful(ctx, orderQueryService, types.OrderQuery{
|
||||||
|
Symbol: o.Symbol,
|
||||||
|
OrderID: strconv.FormatUint(o.OrderID, 10),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Errorf("unable to update order #%d", o.OrderID)
|
||||||
|
continue
|
||||||
|
} else if retOrder != nil {
|
||||||
|
b.Update(*retOrder)
|
||||||
|
|
||||||
|
orders[idx] = *retOrder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cancelAll {
|
||||||
|
orders = b.Orders()
|
||||||
|
} else {
|
||||||
|
// partial cancel
|
||||||
|
orders = filterCanceledOrders(orders)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
log.Warnf("[ActiveOrderBook] using open orders API to verify the active orders...")
|
log.Warnf("[ActiveOrderBook] using open orders API to verify the active orders...")
|
||||||
|
|
||||||
var symbolOrdersMap = categorizeOrderBySymbol(orders)
|
var symbolOrdersMap = categorizeOrderBySymbol(orders)
|
||||||
|
@ -260,6 +290,9 @@ func (b *ActiveOrderBook) GracefulCancel(ctx context.Context, ex types.Exchange,
|
||||||
// update order slice for the next try
|
// update order slice for the next try
|
||||||
orders = leftOrders
|
orders = leftOrders
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("[ActiveOrderBook] all %s orders are cancelled successfully in %s", b.Symbol, time.Since(startTime))
|
log.Debugf("[ActiveOrderBook] all %s orders are cancelled successfully in %s", b.Symbol, time.Since(startTime))
|
||||||
|
@ -489,3 +522,15 @@ func categorizeOrderBySymbol(orders types.OrderSlice) map[string]types.OrderSlic
|
||||||
|
|
||||||
return orderMap
|
return orderMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterCanceledOrders(orders types.OrderSlice) (ret types.OrderSlice) {
|
||||||
|
for _, o := range orders {
|
||||||
|
if o.Status == types.OrderStatusCanceled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, o)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user