From dff7282cc9f15e286e3ba01a5fffeea71906fbc1 Mon Sep 17 00:00:00 2001 From: Pete Barrow Date: Thu, 24 Sep 2020 11:07:18 +0100 Subject: [PATCH 1/2] Fixing incorrect iterating order through sell price levels. --- matching/orderbook_test.go | 40 ++++++++++++++++++++++++++++++++++++++ matching/side.go | 10 +++++----- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/matching/orderbook_test.go b/matching/orderbook_test.go index 47bf8a994a..ff956d1f80 100644 --- a/matching/orderbook_test.go +++ b/matching/orderbook_test.go @@ -2640,6 +2640,46 @@ func TestOrderBook_IndicativePriceAndVolume8(t *testing.T) { assert.Equal(t, len(cancels), 0) } +func TestOrderBook_UncrossTest1(t *testing.T) { + market := "testOrderbook" + book := getTestOrderBook(t, market) + defer book.Finish() + + logger := logging.NewTestLogger() + defer logger.Sync() + + // Switch to auction mode + book.EnterAuction() + + bo1 := getOrder(t, book, market, "BuyOrder01", types.Side_SIDE_BUY, 100, "party01", 5) + bo1.TimeInForce = types.Order_TIF_GFA + book.SubmitOrder(bo1) + + so1 := getOrder(t, book, market, "SellOrder01", types.Side_SIDE_SELL, 100, "party02", 5) + so1.TimeInForce = types.Order_TIF_GFA + book.SubmitOrder(so1) + + bo2 := getOrder(t, book, market, "BuyOrder02", types.Side_SIDE_BUY, 100, "party01", 5) + bo2.TimeInForce = types.Order_TIF_GFA + book.SubmitOrder(bo2) + + so2 := getOrder(t, book, market, "SellOrder02", types.Side_SIDE_SELL, 101, "party02", 5) + so2.TimeInForce = types.Order_TIF_GFA + book.SubmitOrder(so2) + + // Get indicative auction price and volume + price, volume, side := book.GetIndicativePriceAndVolume() + assert.Equal(t, price, uint64(100)) + assert.Equal(t, volume, uint64(5)) + assert.Equal(t, side, types.Side_SIDE_SELL) + + // Leave auction and uncross the book + uncrossedOrders, cancels, err := book.LeaveAuction() + assert.Nil(t, err) + assert.Equal(t, len(uncrossedOrders), 1) + assert.Equal(t, len(cancels), 2) +} + // this is a test for issue 2060 to ensure we process FOK orders properly func TestOrderBook_NetworkOrderSuccess(t *testing.T) { market := "testOrderbook" diff --git a/matching/side.go b/matching/side.go index bff095f5e1..60af871c63 100644 --- a/matching/side.go +++ b/matching/side.go @@ -177,8 +177,8 @@ func (s *OrderBookSide) ExtractOrders(price, volume uint64) ([]*types.Order, err } } } else { - for len(s.levels) > 0 { - pricelevel := s.levels[0] + for index := len(s.levels) - 1; index >= 0; index-- { + pricelevel := s.levels[index] for _, order := range pricelevel.orders { // Check the price is good and the total volume will not be exceeded if order.Price <= price && totalVolume+order.Remaining <= volume { @@ -193,9 +193,9 @@ func (s *OrderBookSide) ExtractOrders(price, volume uint64) ([]*types.Order, err return nil, ErrInvalidVolume } } - // Erase this price level which will be the start of the slice - s.levels[0] = nil - s.levels = s.levels[1:len(s.levels)] + // Erase this price level which will be the end of the slice + s.levels[index] = nil + s.levels = s.levels[:len(s.levels)-1] // Check if we have done enough if totalVolume == volume { From 26eb37f939d7720fdb9691b419e055e5840b81f2 Mon Sep 17 00:00:00 2001 From: Pete Barrow Date: Thu, 24 Sep 2020 12:16:23 +0100 Subject: [PATCH 2/2] Shortened variable name --- matching/side.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/matching/side.go b/matching/side.go index 60af871c63..2880a75c2b 100644 --- a/matching/side.go +++ b/matching/side.go @@ -150,8 +150,8 @@ func (s *OrderBookSide) ExtractOrders(price, volume uint64) ([]*types.Order, err var totalVolume uint64 if s.side == types.Side_SIDE_BUY { - for index := len(s.levels) - 1; index >= 0; index-- { - pricelevel := s.levels[index] + for i := len(s.levels) - 1; i >= 0; i-- { + pricelevel := s.levels[i] for _, order := range pricelevel.orders { // Check the price is good and the total volume will not be exceeded if order.Price >= price && totalVolume+order.Remaining <= volume { @@ -168,7 +168,7 @@ func (s *OrderBookSide) ExtractOrders(price, volume uint64) ([]*types.Order, err } } // Erase this price level which will be at the end of the slice - s.levels[index] = nil + s.levels[i] = nil s.levels = s.levels[:len(s.levels)-1] // Check if we have done enough @@ -177,8 +177,8 @@ func (s *OrderBookSide) ExtractOrders(price, volume uint64) ([]*types.Order, err } } } else { - for index := len(s.levels) - 1; index >= 0; index-- { - pricelevel := s.levels[index] + for i := len(s.levels) - 1; i >= 0; i-- { + pricelevel := s.levels[i] for _, order := range pricelevel.orders { // Check the price is good and the total volume will not be exceeded if order.Price <= price && totalVolume+order.Remaining <= volume { @@ -194,7 +194,7 @@ func (s *OrderBookSide) ExtractOrders(price, volume uint64) ([]*types.Order, err } } // Erase this price level which will be the end of the slice - s.levels[index] = nil + s.levels[i] = nil s.levels = s.levels[:len(s.levels)-1] // Check if we have done enough