code.vegaprotocol.io/vega@v0.79.0/core/matching/amends_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package matching
    17  
    18  import (
    19  	"testing"
    20  
    21  	"code.vegaprotocol.io/vega/core/types"
    22  	"code.vegaprotocol.io/vega/libs/num"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  )
    26  
    27  func TestOrderBookAmends_simpleAmend(t *testing.T) {
    28  	market := "market"
    29  	book := getTestOrderBook(t, market)
    30  	defer book.Finish()
    31  	order := types.Order{
    32  		MarketID:      market,
    33  		Party:         "A",
    34  		Side:          types.SideBuy,
    35  		Price:         num.NewUint(100),
    36  		OriginalPrice: num.NewUint(100),
    37  		Size:          2,
    38  		Remaining:     2,
    39  		TimeInForce:   types.OrderTimeInForceGTC,
    40  		Type:          types.OrderTypeLimit,
    41  	}
    42  	confirm, err := book.SubmitOrder(&order)
    43  	assert.NoError(t, err)
    44  	assert.Equal(t, 0, len(confirm.Trades))
    45  	assert.Equal(t, uint64(2), book.getVolumeAtLevel(100, types.SideBuy))
    46  
    47  	amend := types.Order{
    48  		MarketID:      market,
    49  		Party:         "A",
    50  		Side:          types.SideBuy,
    51  		Price:         num.NewUint(100),
    52  		OriginalPrice: num.NewUint(100),
    53  		Size:          1,
    54  		Remaining:     1,
    55  		TimeInForce:   types.OrderTimeInForceGTC,
    56  		Type:          types.OrderTypeLimit,
    57  	}
    58  	err = book.AmendOrder(&order, &amend)
    59  	assert.NoError(t, err)
    60  	assert.Equal(t, 1, int(book.getVolumeAtLevel(100, types.SideBuy)))
    61  }
    62  
    63  func TestOrderBookAmends_invalidPartyID(t *testing.T) {
    64  	market := "market"
    65  	book := getTestOrderBook(t, market)
    66  	defer book.Finish()
    67  	order := types.Order{
    68  		MarketID:      market,
    69  		Party:         "A",
    70  		Side:          types.SideBuy,
    71  		Price:         num.NewUint(100),
    72  		OriginalPrice: num.NewUint(100),
    73  		Size:          2,
    74  		Remaining:     2,
    75  		TimeInForce:   types.OrderTimeInForceGTC,
    76  		Type:          types.OrderTypeLimit,
    77  	}
    78  	confirm, err := book.SubmitOrder(&order)
    79  	assert.NoError(t, err)
    80  	assert.Equal(t, 0, len(confirm.Trades))
    81  	assert.Equal(t, uint64(2), book.getVolumeAtLevel(100, types.SideBuy))
    82  
    83  	amend := types.Order{
    84  		MarketID:      market,
    85  		Party:         "B",
    86  		Side:          types.SideBuy,
    87  		Price:         num.NewUint(100),
    88  		OriginalPrice: num.NewUint(100),
    89  		Size:          1,
    90  		Remaining:     1,
    91  		TimeInForce:   types.OrderTimeInForceGTC,
    92  		Type:          types.OrderTypeLimit,
    93  	}
    94  	err = book.AmendOrder(&order, &amend)
    95  	assert.Error(t, types.ErrOrderAmendFailure, err)
    96  	assert.Equal(t, uint64(2), book.getVolumeAtLevel(100, types.SideBuy))
    97  }
    98  
    99  func TestOrderBookAmends_invalidPriceAmend(t *testing.T) {
   100  	market := "market"
   101  	book := getTestOrderBook(t, market)
   102  	defer book.Finish()
   103  	order := types.Order{
   104  		MarketID:      market,
   105  		Party:         "A",
   106  		Side:          types.SideBuy,
   107  		Price:         num.NewUint(100),
   108  		OriginalPrice: num.NewUint(100),
   109  		Size:          2,
   110  		Remaining:     2,
   111  		TimeInForce:   types.OrderTimeInForceGTC,
   112  		Type:          types.OrderTypeLimit,
   113  	}
   114  	confirm, err := book.SubmitOrder(&order)
   115  	assert.NoError(t, err)
   116  	assert.Equal(t, 0, len(confirm.Trades))
   117  	assert.Equal(t, uint64(2), book.getVolumeAtLevel(100, types.SideBuy))
   118  
   119  	amend := types.Order{
   120  		MarketID:      market,
   121  		Party:         "A",
   122  		Side:          types.SideBuy,
   123  		Price:         num.NewUint(101),
   124  		OriginalPrice: num.NewUint(101),
   125  		Size:          1,
   126  		Remaining:     1,
   127  		TimeInForce:   types.OrderTimeInForceGTC,
   128  		Type:          types.OrderTypeLimit,
   129  	}
   130  	err = book.AmendOrder(&order, &amend)
   131  	assert.Error(t, types.ErrOrderAmendFailure, err)
   132  	assert.Equal(t, uint64(2), book.getVolumeAtLevel(100, types.SideBuy))
   133  }
   134  
   135  func TestOrderBookAmends_invalidSize(t *testing.T) {
   136  	market := "market"
   137  	book := getTestOrderBook(t, market)
   138  	defer book.Finish()
   139  	order := types.Order{
   140  		MarketID:      market,
   141  		Party:         "A",
   142  		Side:          types.SideBuy,
   143  		Price:         num.NewUint(100),
   144  		OriginalPrice: num.NewUint(100),
   145  		Size:          2,
   146  		Remaining:     2,
   147  		TimeInForce:   types.OrderTimeInForceGTC,
   148  		Type:          types.OrderTypeLimit,
   149  	}
   150  	confirm, err := book.SubmitOrder(&order)
   151  	assert.NoError(t, err)
   152  	assert.Equal(t, 0, len(confirm.Trades))
   153  	assert.Equal(t, uint64(2), book.getVolumeAtLevel(100, types.SideBuy))
   154  
   155  	amend := types.Order{
   156  		MarketID:      market,
   157  		Party:         "A",
   158  		Side:          types.SideBuy,
   159  		Price:         num.NewUint(100),
   160  		OriginalPrice: num.NewUint(100),
   161  		Size:          5,
   162  		Remaining:     5,
   163  		TimeInForce:   types.OrderTimeInForceGTC,
   164  		Type:          types.OrderTypeLimit,
   165  	}
   166  	err = book.AmendOrder(&order, &amend)
   167  	assert.Error(t, types.ErrOrderAmendFailure, err)
   168  	assert.Equal(t, uint64(2), book.getVolumeAtLevel(100, types.SideBuy))
   169  }
   170  
   171  func TestOrderBookAmends_invalidSize2(t *testing.T) {
   172  	market := "market"
   173  	book := getTestOrderBook(t, market)
   174  	defer book.Finish()
   175  	order := types.Order{
   176  		MarketID:      market,
   177  		Party:         "A",
   178  		Side:          types.SideBuy,
   179  		Price:         num.NewUint(100),
   180  		OriginalPrice: num.NewUint(100),
   181  		Size:          48,
   182  		Remaining:     4,
   183  		TimeInForce:   types.OrderTimeInForceGTC,
   184  		Type:          types.OrderTypeLimit,
   185  	}
   186  	confirm, err := book.SubmitOrder(&order)
   187  	assert.NoError(t, err)
   188  	assert.Equal(t, 0, len(confirm.Trades))
   189  	assert.Equal(t, uint64(4), book.getVolumeAtLevel(100, types.SideBuy))
   190  
   191  	amend := types.Order{
   192  		MarketID:      market,
   193  		Party:         "A",
   194  		Side:          types.SideBuy,
   195  		Price:         num.NewUint(100),
   196  		OriginalPrice: num.NewUint(100),
   197  		Size:          45,
   198  		Remaining:     1,
   199  		TimeInForce:   types.OrderTimeInForceGTC,
   200  		Type:          types.OrderTypeLimit,
   201  	}
   202  
   203  	err = book.AmendOrder(&order, &amend)
   204  	assert.NoError(t, err)
   205  	assert.Equal(t, int(1), int(book.getVolumeAtLevel(100, types.SideBuy)))
   206  }
   207  
   208  func TestOrderBookAmends_reduceToZero(t *testing.T) {
   209  	market := "market"
   210  	book := getTestOrderBook(t, market)
   211  	defer book.Finish()
   212  	order := types.Order{
   213  		MarketID:      market,
   214  		Party:         "A",
   215  		Side:          types.SideBuy,
   216  		Price:         num.NewUint(100),
   217  		OriginalPrice: num.NewUint(100),
   218  		Size:          2,
   219  		Remaining:     2,
   220  		TimeInForce:   types.OrderTimeInForceGTC,
   221  		Type:          types.OrderTypeLimit,
   222  	}
   223  	confirm, err := book.SubmitOrder(&order)
   224  	assert.NoError(t, err)
   225  	assert.Equal(t, 0, len(confirm.Trades))
   226  	assert.Equal(t, uint64(2), book.getVolumeAtLevel(100, types.SideBuy))
   227  
   228  	amend := types.Order{
   229  		MarketID:      market,
   230  		Party:         "A",
   231  		Side:          types.SideBuy,
   232  		Price:         num.NewUint(100),
   233  		OriginalPrice: num.NewUint(100),
   234  		Size:          0,
   235  		Remaining:     0,
   236  		TimeInForce:   types.OrderTimeInForceGTC,
   237  		Type:          types.OrderTypeLimit,
   238  	}
   239  	err = book.AmendOrder(&order, &amend)
   240  	assert.Error(t, types.ErrOrderAmendFailure, err)
   241  	assert.Equal(t, uint64(2), book.getVolumeAtLevel(100, types.SideBuy))
   242  }
   243  
   244  func TestOrderBookAmends_invalidSizeDueToPartialFill(t *testing.T) {
   245  	market := "market"
   246  	book := getTestOrderBook(t, market)
   247  	defer book.Finish()
   248  	order := types.Order{
   249  		MarketID:      market,
   250  		Party:         "A",
   251  		Side:          types.SideBuy,
   252  		Price:         num.NewUint(100),
   253  		OriginalPrice: num.NewUint(100),
   254  		Size:          10,
   255  		Remaining:     10,
   256  		TimeInForce:   types.OrderTimeInForceGTC,
   257  		Type:          types.OrderTypeLimit,
   258  	}
   259  	confirm, err := book.SubmitOrder(&order)
   260  	assert.NoError(t, err)
   261  	assert.Equal(t, 0, len(confirm.Trades))
   262  	assert.Equal(t, uint64(10), book.getVolumeAtLevel(100, types.SideBuy))
   263  
   264  	order2 := types.Order{
   265  		MarketID:      market,
   266  		Party:         "B",
   267  		Side:          types.SideSell,
   268  		Price:         num.NewUint(100),
   269  		OriginalPrice: num.NewUint(100),
   270  		Size:          5,
   271  		Remaining:     5,
   272  		TimeInForce:   types.OrderTimeInForceGTC,
   273  		Type:          types.OrderTypeLimit,
   274  	}
   275  	confirm, err = book.SubmitOrder(&order2)
   276  	assert.NoError(t, err)
   277  	assert.Equal(t, 1, len(confirm.Trades))
   278  	assert.Equal(t, uint64(5), book.getVolumeAtLevel(100, types.SideBuy))
   279  
   280  	amend := types.Order{
   281  		MarketID:      market,
   282  		Party:         "B",
   283  		Side:          types.SideBuy,
   284  		Price:         num.NewUint(100),
   285  		OriginalPrice: num.NewUint(100),
   286  		Size:          6,
   287  		Remaining:     6,
   288  		TimeInForce:   types.OrderTimeInForceGTC,
   289  		Type:          types.OrderTypeLimit,
   290  	}
   291  	err = book.AmendOrder(&order, &amend)
   292  	assert.Error(t, types.ErrOrderAmendFailure, err)
   293  	assert.Equal(t, uint64(5), book.getVolumeAtLevel(100, types.SideBuy))
   294  }
   295  
   296  func TestOrderBookAmends_validSizeDueToPartialFill(t *testing.T) {
   297  	market := "market"
   298  	book := getTestOrderBook(t, market)
   299  	defer book.Finish()
   300  	order := types.Order{
   301  		MarketID:      market,
   302  		Party:         "A",
   303  		Side:          types.SideBuy,
   304  		Price:         num.NewUint(100),
   305  		OriginalPrice: num.NewUint(100),
   306  		Size:          10,
   307  		Remaining:     10,
   308  		TimeInForce:   types.OrderTimeInForceGTC,
   309  		Type:          types.OrderTypeLimit,
   310  	}
   311  	confirm, err := book.SubmitOrder(&order)
   312  	assert.NoError(t, err)
   313  	assert.Equal(t, 0, len(confirm.Trades))
   314  	assert.Equal(t, uint64(10), book.getVolumeAtLevel(100, types.SideBuy))
   315  
   316  	order2 := types.Order{
   317  		MarketID:      market,
   318  		Party:         "B",
   319  		Side:          types.SideSell,
   320  		Price:         num.NewUint(100),
   321  		OriginalPrice: num.NewUint(100),
   322  		Size:          5,
   323  		Remaining:     5,
   324  		TimeInForce:   types.OrderTimeInForceGTC,
   325  		Type:          types.OrderTypeLimit,
   326  	}
   327  	confirm, err = book.SubmitOrder(&order2)
   328  	assert.NoError(t, err)
   329  	assert.Equal(t, 1, len(confirm.Trades))
   330  	assert.Equal(t, uint64(5), book.getVolumeAtLevel(100, types.SideBuy))
   331  
   332  	amend := types.Order{
   333  		MarketID:      market,
   334  		Party:         "A",
   335  		Side:          types.SideBuy,
   336  		Price:         num.NewUint(100),
   337  		OriginalPrice: num.NewUint(100),
   338  		Size:          3,
   339  		Remaining:     3,
   340  		TimeInForce:   types.OrderTimeInForceGTC,
   341  		Type:          types.OrderTypeLimit,
   342  	}
   343  	err = book.AmendOrder(&order, &amend)
   344  	assert.Error(t, types.ErrOrderAmendFailure, err)
   345  	assert.Equal(t, uint64(3), book.getVolumeAtLevel(100, types.SideBuy))
   346  }
   347  
   348  func TestOrderBookAmends_noOrderToAmend(t *testing.T) {
   349  	market := "market"
   350  	book := getTestOrderBook(t, market)
   351  	defer book.Finish()
   352  
   353  	amend := types.Order{
   354  		MarketID:      market,
   355  		Party:         "A",
   356  		Side:          types.SideBuy,
   357  		Price:         num.NewUint(100),
   358  		OriginalPrice: num.NewUint(100),
   359  		Size:          1,
   360  		Remaining:     1,
   361  		TimeInForce:   types.OrderTimeInForceGTC,
   362  		Type:          types.OrderTypeLimit,
   363  	}
   364  	assert.Panics(t, func() {
   365  		book.AmendOrder(nil, &amend)
   366  	})
   367  }