FIX: fix issue when recovering with finalizing orders

This commit is contained in:
kbearXD 2024-04-02 18:39:26 +08:00 committed by c9s
parent 23f6dd91c9
commit f8d7447e8e
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
4 changed files with 50 additions and 6 deletions

View File

@ -9,6 +9,8 @@ import (
"github.com/cenkalti/backoff/v4"
"github.com/c9s/bbgo/pkg/exchange/max"
maxapi "github.com/c9s/bbgo/pkg/exchange/max/maxapi"
"github.com/c9s/bbgo/pkg/types"
)
@ -51,6 +53,7 @@ func QueryOrderUntilCanceled(
func QueryOrderUntilFilled(
ctx context.Context, queryOrderService types.ExchangeOrderQueryService, symbol string, orderId uint64,
) (o *types.Order, err error) {
_, isMax := queryOrderService.(*max.Exchange)
var op = func() (err2 error) {
o, err2 = queryOrderService.QueryOrder(ctx, types.OrderQuery{
Symbol: symbol,
@ -67,7 +70,16 @@ func QueryOrderUntilFilled(
// for final status return nil error to stop the retry
switch o.Status {
case types.OrderStatusFilled, types.OrderStatusCanceled:
case types.OrderStatusFilled:
if isMax {
// for MAX exchange, the order state done is filled but finalizing is not filled
if o.OriginalStatus == string(maxapi.OrderStateDone) {
return nil
}
} else {
return nil
}
case types.OrderStatusCanceled:
return nil
}

View File

@ -2,6 +2,7 @@ package common
import (
"context"
"fmt"
"strconv"
"time"
@ -26,6 +27,10 @@ func SyncActiveOrder(ctx context.Context, ex types.Exchange, orderQueryService t
return isOrderUpdated, err
}
if updatedOrder == nil {
return isOrderUpdated, fmt.Errorf("updatedOrder is nil and there is no error, please check it")
}
// maxapi.OrderStateFinalizing does not mean the fee is calculated
// we should only consider order state done for MAX
if isMax && updatedOrder.OriginalStatus != string(maxapi.OrderStateDone) {

View File

@ -82,7 +82,11 @@ func (s *Strategy) runState(ctx context.Context) {
// s.logger.Infof("[DCA] triggerNextState current state: %d", s.state)
s.triggerNextState()
case nextState := <-s.nextStateC:
// s.logger.Infof("[DCA] currenct state: %d, next state: %d", s.state, nextState)
// next state == current state -> skip
if nextState == s.state {
continue
}
// check the next state is valid
validNextState, exist := stateTransition[s.state]
if !exist {

View File

@ -72,13 +72,36 @@ func (s *Strategy) recoverByScanningTrades(ctx context.Context, session *bbgo.Ex
// add open orders into avtive maker orders
s.addOrdersToActiveOrderBook(openOrders)
// following is for MAX
if isMax {
var doneOrders []types.Order
for _, filledOrder := range filledOrders {
if filledOrder.OriginalStatus != string(maxapi.OrderStateDone) {
order, err := retry.QueryOrderUntilFilled(ctx, s.orderQueryService, filledOrder.Symbol, filledOrder.OrderID)
if err != nil {
return errors.Wrap(err, "unable to query orders until filled, please check it")
}
if order == nil {
return fmt.Errorf("after QueryOrderUntilFilled, order and error are both nil. Please check it")
}
doneOrders = append(doneOrders, *order)
} else {
doneOrders = append(doneOrders, filledOrder)
}
}
if len(filledOrders) != len(doneOrders) {
return fmt.Errorf("num of filled orders (%d) and num of done orders (%d) should be the same", len(filledOrders), len(doneOrders))
}
filledOrders = doneOrders
}
// emit the filled orders
activeOrderBook := s.orderExecutor.ActiveMakerOrders()
for _, filledOrder := range filledOrders {
if isMax && filledOrder.OriginalStatus != string(maxapi.OrderStateDone) {
activeOrderBook.Add(filledOrder)
continue
}
activeOrderBook.EmitFilled(filledOrder)
}