Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: [grid2] fix issue when recovering with finalizing orders #1612

Merged
merged 2 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion pkg/exchange/retry/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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,
Expand All @@ -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
}

Expand Down
5 changes: 5 additions & 0 deletions pkg/strategy/common/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package common

import (
"context"
"fmt"
"strconv"
"time"

Expand All @@ -26,6 +27,10 @@ func SyncActiveOrder(ctx context.Context, ex types.Exchange, orderQueryService t
return isOrderUpdated, err
}

if updatedOrder == nil {
return isOrderUpdated, fmt.Errorf("unexpected error, order object (%d) is a nil pointer, please check common.SyncActiveOrder()", orderID)
}

// 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) {
Expand Down
6 changes: 5 additions & 1 deletion pkg/strategy/dca2/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
31 changes: 27 additions & 4 deletions pkg/strategy/grid2/grid_recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
Loading