Merge pull request #1100 from c9s/bhwu/grid2/specify-client-order-id

FIX: [grid2] specify client order id explicitly
This commit is contained in:
gx578007 2023-03-13 18:51:27 +08:00 committed by GitHub
commit 4b540fce88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 56 deletions

View File

@ -11,6 +11,7 @@ import (
"time"
"github.com/cenkalti/backoff/v4"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
@ -485,15 +486,16 @@ func (s *Strategy) processFilledOrder(o types.Order) {
}
orderForm := types.SubmitOrder{
Symbol: s.Symbol,
Market: s.Market,
Type: types.OrderTypeLimit,
Price: newPrice,
Side: newSide,
TimeInForce: types.TimeInForceGTC,
Quantity: newQuantity,
Tag: orderTag,
GroupID: s.OrderGroupID,
Symbol: s.Symbol,
Market: s.Market,
Type: types.OrderTypeLimit,
Price: newPrice,
Side: newSide,
TimeInForce: types.TimeInForceGTC,
Quantity: newQuantity,
Tag: orderTag,
GroupID: s.OrderGroupID,
ClientOrderID: uuid.New().String(),
}
s.logger.Infof("SUBMIT GRID REVERSE ORDER: %s", orderForm.String())
@ -1242,15 +1244,16 @@ func (s *Strategy) generateGridOrders(totalQuote, totalBase, lastPrice fixedpoin
if usedBase.Add(quantity).Compare(totalBase) < 0 {
submitOrders = append(submitOrders, types.SubmitOrder{
Symbol: s.Symbol,
Type: types.OrderTypeLimit,
Side: types.SideTypeSell,
Price: sellPrice,
Quantity: quantity,
Market: s.Market,
TimeInForce: types.TimeInForceGTC,
Tag: orderTag,
GroupID: s.OrderGroupID,
Symbol: s.Symbol,
Type: types.OrderTypeLimit,
Side: types.SideTypeSell,
Price: sellPrice,
Quantity: quantity,
Market: s.Market,
TimeInForce: types.TimeInForceGTC,
Tag: orderTag,
GroupID: s.OrderGroupID,
ClientOrderID: uuid.New().String(),
})
usedBase = usedBase.Add(quantity)
} else {
@ -1259,15 +1262,16 @@ func (s *Strategy) generateGridOrders(totalQuote, totalBase, lastPrice fixedpoin
nextPin := pins[i-1]
nextPrice := fixedpoint.Value(nextPin)
submitOrders = append(submitOrders, types.SubmitOrder{
Symbol: s.Symbol,
Type: types.OrderTypeLimit,
Side: types.SideTypeBuy,
Price: nextPrice,
Quantity: quantity,
Market: s.Market,
TimeInForce: types.TimeInForceGTC,
Tag: orderTag,
GroupID: s.OrderGroupID,
Symbol: s.Symbol,
Type: types.OrderTypeLimit,
Side: types.SideTypeBuy,
Price: nextPrice,
Quantity: quantity,
Market: s.Market,
TimeInForce: types.TimeInForceGTC,
Tag: orderTag,
GroupID: s.OrderGroupID,
ClientOrderID: uuid.New().String(),
})
quoteQuantity := quantity.Mul(nextPrice)
usedQuote = usedQuote.Add(quoteQuantity)
@ -1292,15 +1296,16 @@ func (s *Strategy) generateGridOrders(totalQuote, totalBase, lastPrice fixedpoin
}
submitOrders = append(submitOrders, types.SubmitOrder{
Symbol: s.Symbol,
Type: types.OrderTypeLimit,
Side: types.SideTypeBuy,
Price: price,
Quantity: quantity,
Market: s.Market,
TimeInForce: types.TimeInForceGTC,
Tag: orderTag,
GroupID: s.OrderGroupID,
Symbol: s.Symbol,
Type: types.OrderTypeLimit,
Side: types.SideTypeBuy,
Price: price,
Quantity: quantity,
Market: s.Market,
TimeInForce: types.TimeInForceGTC,
Tag: orderTag,
GroupID: s.OrderGroupID,
ClientOrderID: uuid.New().String(),
})
usedQuote = usedQuote.Add(quoteQuantity)
}
@ -2140,4 +2145,4 @@ func queryOpenOrdersUntilSuccessful(ctx context.Context, ex types.Exchange, symb
err = generalBackoff(ctx, op)
return openOrders, err
}
}

View File

@ -22,6 +22,23 @@ func init() {
registerMetrics()
}
func equalOrdersIgnoreClientOrderID(a, b types.SubmitOrder) bool {
return a.Symbol == b.Symbol &&
a.Side == b.Side &&
a.Type == b.Type &&
a.Quantity == b.Quantity &&
a.Price == b.Price &&
a.AveragePrice == b.AveragePrice &&
a.StopPrice == b.StopPrice &&
a.Market == b.Market &&
a.TimeInForce == b.TimeInForce &&
a.GroupID == b.GroupID &&
a.MarginSideEffect == b.MarginSideEffect &&
a.ReduceOnly == b.ReduceOnly &&
a.ClosePosition == b.ClosePosition &&
a.Tag == b.Tag
}
func TestStrategy_checkRequiredInvestmentByQuantity(t *testing.T) {
s := &Strategy{
logger: logrus.NewEntry(logrus.New()),
@ -605,9 +622,12 @@ func TestStrategy_handleOrderFilled(t *testing.T) {
}
orderExecutor := gridmocks.NewMockOrderExecutor(mockCtrl)
orderExecutor.EXPECT().SubmitOrders(ctx, expectedSubmitOrder).Return([]types.Order{
{SubmitOrder: expectedSubmitOrder},
}, nil)
orderExecutor.EXPECT().SubmitOrders(ctx, gomock.Any()).DoAndReturn(func(ctx context.Context, order types.SubmitOrder) (types.OrderSlice, error) {
assert.True(t, equalOrdersIgnoreClientOrderID(expectedSubmitOrder, order), "%+v is not equal to %+v", order, expectedSubmitOrder)
return []types.Order{
{SubmitOrder: expectedSubmitOrder},
}, nil
})
s.orderExecutor = orderExecutor
s.handleOrderFilled(types.Order{
@ -670,9 +690,12 @@ func TestStrategy_handleOrderFilled(t *testing.T) {
}
orderExecutor := gridmocks.NewMockOrderExecutor(mockCtrl)
orderExecutor.EXPECT().SubmitOrders(ctx, expectedSubmitOrder).Return([]types.Order{
{SubmitOrder: expectedSubmitOrder},
}, nil)
orderExecutor.EXPECT().SubmitOrders(ctx, gomock.Any()).DoAndReturn(func(ctx context.Context, order types.SubmitOrder) (types.OrderSlice, error) {
assert.True(t, equalOrdersIgnoreClientOrderID(expectedSubmitOrder, order), "%+v is not equal to %+v", order, expectedSubmitOrder)
return []types.Order{
{SubmitOrder: expectedSubmitOrder},
}, nil
})
s.orderExecutor = orderExecutor
s.handleOrderFilled(types.Order{
@ -755,9 +778,12 @@ func TestStrategy_handleOrderFilled(t *testing.T) {
Market: s.Market,
Tag: orderTag,
}
orderExecutor.EXPECT().SubmitOrders(ctx, expectedSubmitOrder).Return([]types.Order{
{SubmitOrder: expectedSubmitOrder},
}, nil)
orderExecutor.EXPECT().SubmitOrders(ctx, gomock.Any()).DoAndReturn(func(ctx context.Context, order types.SubmitOrder) (types.OrderSlice, error) {
assert.True(t, equalOrdersIgnoreClientOrderID(expectedSubmitOrder, order), "%+v is not equal to %+v", order, expectedSubmitOrder)
return []types.Order{
{SubmitOrder: expectedSubmitOrder},
}, nil
})
expectedSubmitOrder2 := types.SubmitOrder{
Symbol: "BTCUSDT",
@ -769,9 +795,12 @@ func TestStrategy_handleOrderFilled(t *testing.T) {
Market: s.Market,
Tag: orderTag,
}
orderExecutor.EXPECT().SubmitOrders(ctx, expectedSubmitOrder2).Return([]types.Order{
{SubmitOrder: expectedSubmitOrder2},
}, nil)
orderExecutor.EXPECT().SubmitOrders(ctx, gomock.Any()).DoAndReturn(func(ctx context.Context, order types.SubmitOrder) (types.OrderSlice, error) {
assert.True(t, equalOrdersIgnoreClientOrderID(expectedSubmitOrder2, order), "%+v is not equal to %+v", order, expectedSubmitOrder2)
return []types.Order{
{SubmitOrder: expectedSubmitOrder2},
}, nil
})
s.orderExecutor = orderExecutor
@ -863,9 +892,12 @@ func TestStrategy_handleOrderFilled(t *testing.T) {
}
orderExecutor := gridmocks.NewMockOrderExecutor(mockCtrl)
orderExecutor.EXPECT().SubmitOrders(ctx, expectedSubmitOrder).Return([]types.Order{
{SubmitOrder: expectedSubmitOrder},
}, nil)
orderExecutor.EXPECT().SubmitOrders(ctx, gomock.Any()).DoAndReturn(func(ctx context.Context, order types.SubmitOrder) (types.OrderSlice, error) {
assert.True(t, equalOrdersIgnoreClientOrderID(expectedSubmitOrder, order), "%+v is not equal to %+v", order, expectedSubmitOrder)
return []types.Order{
{SubmitOrder: expectedSubmitOrder},
}, nil
})
expectedSubmitOrder2 := types.SubmitOrder{
Symbol: "BTCUSDT",
@ -878,9 +910,12 @@ func TestStrategy_handleOrderFilled(t *testing.T) {
Tag: orderTag,
}
orderExecutor.EXPECT().SubmitOrders(ctx, expectedSubmitOrder2).Return([]types.Order{
{SubmitOrder: expectedSubmitOrder2},
}, nil)
orderExecutor.EXPECT().SubmitOrders(ctx, gomock.Any()).DoAndReturn(func(ctx context.Context, order types.SubmitOrder) (types.OrderSlice, error) {
assert.True(t, equalOrdersIgnoreClientOrderID(expectedSubmitOrder2, order), "%+v is not equal to %+v", order, expectedSubmitOrder2)
return []types.Order{
{SubmitOrder: expectedSubmitOrder2},
}, nil
})
s.orderExecutor = orderExecutor
s.handleOrderFilled(types.Order{
@ -1142,4 +1177,4 @@ func Test_buildPinOrderMap(t *testing.T) {
_, err := s.buildPinOrderMap(s.grid, openOrders)
assert.Error(err)
})
}
}