From 51e38cf00215ad38a4fd204faf317a54ff0b6130 Mon Sep 17 00:00:00 2001 From: edwin Date: Wed, 6 Mar 2024 11:36:47 +0800 Subject: [PATCH 1/2] pkg/exchange: support market order on bitget unfilled order conversion --- pkg/exchange/bitget/convert.go | 13 ++++-- pkg/exchange/bitget/convert_test.go | 63 ++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/pkg/exchange/bitget/convert.go b/pkg/exchange/bitget/convert.go index f36da9165..2dda16d7a 100644 --- a/pkg/exchange/bitget/convert.go +++ b/pkg/exchange/bitget/convert.go @@ -189,10 +189,17 @@ func unfilledOrderToGlobalOrder(order v2.UnfilledOrder) (*types.Order, error) { qty := order.Size price := order.PriceAvg - // The market order will be executed immediately, so this check is used to handle corner cases. + // 2023/11/05 The market order will be executed immediately, so this check is used to handle corner cases. + // 2024/03/06 After placing a Market Order, we can retrieve it through the unfilledOrder API, so we still need to + // handle the Market Order status. if orderType == types.OrderTypeMarket { - qty = order.BaseVolume - log.Warnf("!!! The price(%f) and quantity(%f) are not verified for market orders, because we only receive limit orders in the test environment !!!", price.Float64(), qty.Float64()) + price = order.PriceAvg + if side == types.SideTypeBuy { + qty, err = processMarketBuyQuantity(order.BaseVolume, order.QuoteVolume, order.PriceAvg, order.Size, order.Status) + if err != nil { + return nil, err + } + } } return &types.Order{ diff --git a/pkg/exchange/bitget/convert_test.go b/pkg/exchange/bitget/convert_test.go index dfab65af6..5aac971df 100644 --- a/pkg/exchange/bitget/convert_test.go +++ b/pkg/exchange/bitget/convert_test.go @@ -227,7 +227,7 @@ func Test_unfilledOrderToGlobalOrder(t *testing.T) { } ) - t.Run("succeeds", func(t *testing.T) { + t.Run("succeeds with limit order", func(t *testing.T) { order, err := unfilledOrderToGlobalOrder(unfilledOrder) assert.NoError(err) assert.Equal(&types.Order{ @@ -251,6 +251,67 @@ func Test_unfilledOrderToGlobalOrder(t *testing.T) { }, order) }) + t.Run("succeeds with market buy order", func(t *testing.T) { + unfilledOrder2 := unfilledOrder + unfilledOrder2.OrderType = v2.OrderTypeMarket + unfilledOrder2.Side = v2.SideTypeBuy + unfilledOrder2.Size = unfilledOrder2.PriceAvg.Mul(unfilledOrder2.Size) + unfilledOrder2.PriceAvg = fixedpoint.Zero + unfilledOrder2.Status = v2.OrderStatusNew + + order, err := unfilledOrderToGlobalOrder(unfilledOrder2) + assert.NoError(err) + assert.Equal(&types.Order{ + SubmitOrder: types.SubmitOrder{ + ClientOrderID: "74b86af3-6098-479c-acac-bfb074c067f3", + Symbol: "BTCUSDT", + Side: types.SideTypeBuy, + Type: types.OrderTypeMarket, + Quantity: fixedpoint.Zero, + Price: fixedpoint.Zero, + TimeInForce: types.TimeInForceGTC, + }, + Exchange: types.ExchangeBitget, + OrderID: uint64(orderId), + UUID: strconv.FormatInt(int64(orderId), 10), + Status: types.OrderStatusNew, + ExecutedQuantity: fixedpoint.Zero, + IsWorking: true, + CreationTime: types.Time(types.NewMillisecondTimestampFromInt(1660704288118).Time()), + UpdateTime: types.Time(types.NewMillisecondTimestampFromInt(1660704288118).Time()), + }, order) + }) + + t.Run("succeeds with market sell order", func(t *testing.T) { + unfilledOrder2 := unfilledOrder + unfilledOrder2.OrderType = v2.OrderTypeMarket + unfilledOrder2.Side = v2.SideTypeSell + unfilledOrder2.PriceAvg = fixedpoint.Zero + unfilledOrder2.Status = v2.OrderStatusNew + + order, err := unfilledOrderToGlobalOrder(unfilledOrder2) + assert.NoError(err) + assert.Equal(&types.Order{ + SubmitOrder: types.SubmitOrder{ + ClientOrderID: "74b86af3-6098-479c-acac-bfb074c067f3", + Symbol: "BTCUSDT", + Side: types.SideTypeSell, + Type: types.OrderTypeMarket, + Quantity: fixedpoint.NewFromInt(5), + Price: fixedpoint.Zero, + TimeInForce: types.TimeInForceGTC, + }, + Exchange: types.ExchangeBitget, + OrderID: uint64(orderId), + UUID: strconv.FormatInt(int64(orderId), 10), + Status: types.OrderStatusNew, + ExecutedQuantity: fixedpoint.Zero, + IsWorking: true, + CreationTime: types.Time(types.NewMillisecondTimestampFromInt(1660704288118).Time()), + UpdateTime: types.Time(types.NewMillisecondTimestampFromInt(1660704288118).Time()), + }, order) + }) + t.Run("failed to convert side", func(t *testing.T) { newOrder := unfilledOrder newOrder.Side = "xxx" From 91445807f6c6a62b21adadc3b852acc938e71f06 Mon Sep 17 00:00:00 2001 From: edwin Date: Wed, 6 Mar 2024 14:24:58 +0800 Subject: [PATCH 2/2] pkg/exchange: add more comments --- pkg/exchange/bitget/exchange.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/exchange/bitget/exchange.go b/pkg/exchange/bitget/exchange.go index 254cbd519..bdda2c656 100644 --- a/pkg/exchange/bitget/exchange.go +++ b/pkg/exchange/bitget/exchange.go @@ -362,10 +362,12 @@ func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (cr debugf("unfilled order response for order#%s: %+v", orderId, ordersResp) if len(ordersResp) == 1 { + // 2023/11/05 The market order will be executed immediately, so we cannot retrieve it through the NewGetUnfilledOrdersRequest API. + // Try to get the order from the NewGetHistoryOrdersRequest API. + // 2024/03/06 After placing a Market Order, we can retrieve it through the unfilledOrder API, so we still need to + // handle the Market Order status. return unfilledOrderToGlobalOrder(ordersResp[0]) } else if len(ordersResp) == 0 { - // The market order will be executed immediately, so we cannot retrieve it through the NewGetUnfilledOrdersRequest API. - // Try to get the order from the NewGetHistoryOrdersRequest API. ordersResp, err := e.v2client.NewGetHistoryOrdersRequest().OrderId(orderId).Do(ctx) if err != nil { return nil, fmt.Errorf("failed to query history order by order id: %s, err: %w", orderId, err)