code.vegaprotocol.io/vega@v0.79.0/core/execution/future/event_generation_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 future_test
    17  
    18  import (
    19  	"context"
    20  	"testing"
    21  	"time"
    22  
    23  	"code.vegaprotocol.io/vega/core/events"
    24  	"code.vegaprotocol.io/vega/core/subscribers"
    25  	"code.vegaprotocol.io/vega/core/types"
    26  	vgcrypto "code.vegaprotocol.io/vega/libs/crypto"
    27  	"code.vegaprotocol.io/vega/libs/num"
    28  
    29  	"github.com/golang/mock/gomock"
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  func startMarketInAuction(t *testing.T, ctx context.Context, now *time.Time) *testMarket {
    35  	t.Helper()
    36  
    37  	pmt := &types.PriceMonitoringTrigger{
    38  		Horizon:          60,
    39  		HorizonDec:       num.DecimalFromFloat(60),
    40  		Probability:      num.DecimalFromFloat(.95),
    41  		AuctionExtension: 60,
    42  	}
    43  	pMonitorSettings := &types.PriceMonitoringSettings{
    44  		Parameters: &types.PriceMonitoringParameters{
    45  			Triggers: []*types.PriceMonitoringTrigger{
    46  				pmt,
    47  			},
    48  		},
    49  	}
    50  
    51  	tm := getTestMarket(t, *now, pMonitorSettings, nil)
    52  
    53  	addAccountWithAmount(tm, "party-A", 1000)
    54  	addAccountWithAmount(tm, "party-B", 100000000)
    55  	addAccountWithAmount(tm, "party-C", 100000000)
    56  	tm.broker.EXPECT().Send(gomock.Any()).AnyTimes()
    57  
    58  	tm.market.OnMarketAuctionMinimumDurationUpdate(context.Background(), 10*time.Second)
    59  	// Start the opening auction
    60  	tm.mas.StartOpeningAuction(*now, &types.AuctionDuration{Duration: 10})
    61  	tm.mas.AuctionStarted(ctx, *now)
    62  	tm.market.EnterAuction(ctx)
    63  
    64  	// Reset the event counter
    65  	clearEvents(tm)
    66  
    67  	return tm
    68  }
    69  
    70  func leaveAuction(t *testing.T, tm *testMarket, ctx context.Context, now *time.Time) {
    71  	t.Helper()
    72  	// Leave auction to force the order to be removed
    73  	*now = now.Add(time.Second * 20)
    74  	require.Greater(t, tm.market.GetMarketData().IndicativeVolume, uint64(0), "can't leave opening auction with no trades")
    75  	tm.market.LeaveAuctionWithIDGen(ctx, *now, newTestIDGenerator())
    76  }
    77  
    78  func processEventsWithCounter(t *testing.T, tm *testMarket, mdb *subscribers.MarketDepthBuilder) {
    79  	t.Helper()
    80  	for _, event := range tm.orderEvents {
    81  		mdb.Push(event)
    82  	}
    83  	for _, evt := range tm.events {
    84  		if co, ok := evt.(*events.CancelledOrders); ok {
    85  			mdb.Push(co)
    86  		}
    87  	}
    88  	needToQuit := false
    89  	orders := mdb.GetAllOrders(tm.market.GetID())
    90  	for _, order := range orders {
    91  		if !tm.market.ValidateOrder(order) {
    92  			needToQuit = true
    93  		}
    94  	}
    95  
    96  	if !checkConsistency(t, tm, mdb) {
    97  		/*// We had an error, lets dump all the events
    98  		for i, event := range tm.orderEvents {
    99  			switch te := event.(type) {
   100  			case subscribers.OE:
   101  				fmt.Println("Event:", i, te.Order())
   102  			}
   103  		}*/
   104  		needToQuit = true
   105  	}
   106  
   107  	if needToQuit {
   108  		require.Equal(t, true, false)
   109  	}
   110  }
   111  
   112  func processEvents(t *testing.T, tm *testMarket, mdb *subscribers.MarketDepthBuilder) {
   113  	t.Helper()
   114  	processEventsWithCounter(t, tm, mdb)
   115  }
   116  
   117  func clearEvents(tm *testMarket) {
   118  	// Reset the event counter
   119  	tm.eventCount = 0
   120  	tm.orderEventCount = 0
   121  	tm.events = nil
   122  	tm.orderEvents = nil
   123  }
   124  
   125  // Check that the orders in the matching engine are the same as the orders in the market depth.
   126  func checkConsistency(t *testing.T, tm *testMarket, mdb *subscribers.MarketDepthBuilder) bool {
   127  	t.Helper()
   128  	correct := true
   129  	// Do we have the same number of orders in each?
   130  	if !assert.Equal(t, tm.market.GetOrdersOnBookCount(), mdb.GetOrderCount(tm.market.GetID())) {
   131  		correct = false
   132  	}
   133  	// Do we have the same volume in each?
   134  	if !assert.Equal(t, tm.market.GetVolumeOnBook(), mdb.GetTotalVolume(tm.market.GetID())) {
   135  		correct = false
   136  	}
   137  	// Do we have the same best bid price?
   138  	if !assert.True(t, tm.market.GetMarketData().BestBidPrice.EQ(mdb.GetBestBidPrice(tm.market.GetID()))) {
   139  		correct = false
   140  	}
   141  	// Do we have the same best ask price?
   142  	if !assert.True(t, tm.market.GetMarketData().BestOfferPrice.EQ(mdb.GetBestAskPrice(tm.market.GetID()))) {
   143  		correct = false
   144  	}
   145  
   146  	// Check volume at each level is correct
   147  	bestBid := tm.market.GetMarketData().BestBidPrice.Clone()
   148  	bestAsk := tm.market.GetMarketData().BestOfferPrice.Clone()
   149  
   150  	if !assert.Equal(t, tm.market.GetMarketData().BestBidVolume, mdb.GetVolumeAtPrice(tm.market.GetID(), types.SideBuy, bestBid.Uint64())) {
   151  		correct = false
   152  	}
   153  
   154  	if !assert.Equal(t, tm.market.GetMarketData().BestOfferVolume, mdb.GetVolumeAtPrice(tm.market.GetID(), types.SideSell, bestAsk.Uint64())) {
   155  		correct = false
   156  	}
   157  
   158  	return correct
   159  }
   160  
   161  func TestEvents_LeavingAuctionCancelsGFAOrders(t *testing.T) {
   162  	now := time.Unix(10, 0)
   163  	ctx := context.Background()
   164  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   165  	tm := startMarketInAuction(t, ctx, &now)
   166  
   167  	o0 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order0", types.SideBuy, "party-B", 1, 20)
   168  	o0conf, err := tm.market.SubmitOrder(ctx, o0)
   169  	require.NotNil(t, o0conf)
   170  	require.NoError(t, err)
   171  
   172  	o00 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order00", types.SideSell, "party-C", 1, 20)
   173  	o00conf, err := tm.market.SubmitOrder(ctx, o00)
   174  	require.NotNil(t, o00conf)
   175  	require.NoError(t, err)
   176  
   177  	// Add a GFA order
   178  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFA, "Order01", types.SideBuy, "party-A", 10, 10)
   179  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   180  	require.NotNil(t, o1conf)
   181  	require.NoError(t, err)
   182  
   183  	// Leave auction to force the order to be removed
   184  	leaveAuction(t, tm, ctx, &now)
   185  
   186  	// Check we have 5 events (2 additional orders submitted and filled)
   187  	assert.Equal(t, uint64(5), tm.orderEventCount)
   188  
   189  	processEvents(t, tm, mdb)
   190  	assert.Equal(t, int64(0), mdb.GetOrderCount(tm.market.GetID()))
   191  }
   192  
   193  func TestEvents_EnteringAuctionCancelsGFNOrders(t *testing.T) {
   194  	now := time.Unix(10, 0)
   195  	ctx := context.Background()
   196  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   197  	tm := startMarketInAuction(t, ctx, &now)
   198  
   199  	auxParty := "aux"
   200  	addAccount(t, tm, auxParty)
   201  	auxOrder1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy", types.SideBuy, auxParty, 1, 1)
   202  	conf, err := tm.market.SubmitOrder(ctx, auxOrder1)
   203  	require.NotNil(t, conf)
   204  	require.NoError(t, err)
   205  
   206  	auxOrder2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell", types.SideSell, auxParty, 1, 100001)
   207  	conf, err = tm.market.SubmitOrder(ctx, auxOrder2)
   208  	require.NotNil(t, conf)
   209  	require.NoError(t, err)
   210  
   211  	auxOrder3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy2", types.SideBuy, auxParty, 1, 10)
   212  	conf, err = tm.market.SubmitOrder(ctx, auxOrder3)
   213  	require.NotNil(t, conf)
   214  	require.NoError(t, err)
   215  
   216  	auxOrder4 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell2", types.SideSell, auxParty, 1, 10)
   217  	conf, err = tm.market.SubmitOrder(ctx, auxOrder4)
   218  	require.NotNil(t, conf)
   219  	require.NoError(t, err)
   220  
   221  	leaveAuction(t, tm, ctx, &now)
   222  
   223  	md := tm.market.GetMarketData()
   224  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode)
   225  
   226  	assert.Equal(t, int64(2), tm.market.GetOrdersOnBookCount())
   227  
   228  	// Add a GFN order
   229  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFN, "Order01", types.SideBuy, "party-A", 10, 10)
   230  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   231  	require.NotNil(t, o1conf)
   232  	require.NoError(t, err)
   233  
   234  	// Fill some of it to set the mark price
   235  	o4 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order04", types.SideSell, "party-B", 1, 10)
   236  	o4conf, err := tm.market.SubmitOrder(ctx, o4)
   237  	require.NotNil(t, o4conf)
   238  	require.NoError(t, err)
   239  
   240  	// Move the mark price super high to force a price auction
   241  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 1, 100000)
   242  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   243  	require.NotNil(t, o2conf)
   244  	require.NoError(t, err)
   245  
   246  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideSell, "party-C", 1, 100000)
   247  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   248  	require.NotNil(t, o3conf)
   249  	require.NoError(t, err)
   250  
   251  	// Check we are in a price auction
   252  	assert.Equal(t, types.AuctionTriggerPrice, tm.market.GetMarketData().Trigger)
   253  
   254  	// Check we have the right amount of events
   255  	assert.Equal(t, uint64(11), tm.orderEventCount)
   256  
   257  	assert.Equal(t, int64(4), tm.market.GetOrdersOnBookCount())
   258  
   259  	processEvents(t, tm, mdb)
   260  	assert.Equal(t, int64(4), mdb.GetOrderCount(tm.market.GetID()))
   261  }
   262  
   263  func TestEvents_CloseOutParty(t *testing.T) {
   264  	t.Skip("TODO fix this - this test seems to trigger price auction (price range is 501-1010 IIRC)")
   265  	now := time.Unix(10, 0)
   266  	ctx := context.Background()
   267  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   268  	tm := startMarketInAuction(t, ctx, &now)
   269  
   270  	auxParty := "aux"
   271  	addAccount(t, tm, auxParty)
   272  	auxOrder1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy", types.SideBuy, auxParty, 1, 1)
   273  	conf, err := tm.market.SubmitOrder(ctx, auxOrder1)
   274  	require.NotNil(t, conf)
   275  	require.NoError(t, err)
   276  
   277  	auxOrder2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell", types.SideSell, auxParty, 1, 101)
   278  	conf, err = tm.market.SubmitOrder(ctx, auxOrder2)
   279  	require.NotNil(t, conf)
   280  	require.NoError(t, err)
   281  
   282  	leaveAuction(t, tm, ctx, &now)
   283  
   284  	md := tm.market.GetMarketData()
   285  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode)
   286  
   287  	assert.Equal(t, int64(2), tm.market.GetOrdersOnBookCount())
   288  
   289  	// Add a GFN order
   290  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFN, "Order01", types.SideSell, "party-A", 10, 2)
   291  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   292  	require.NotNil(t, o1conf)
   293  	require.NoError(t, err)
   294  	md = tm.market.GetMarketData()
   295  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode)
   296  
   297  	// Fill some of it to set the mark price
   298  	o4 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order04", types.SideBuy, "party-B", 10, 2)
   299  	o4conf, err := tm.market.SubmitOrder(ctx, o4)
   300  	require.NotNil(t, o4conf)
   301  	require.NoError(t, err)
   302  
   303  	// assert.Equal(t, int64(2), tm.market.GetOrdersOnBookCount())
   304  	assert.Equal(t, int64(3), tm.market.GetOrdersOnBookCount())
   305  
   306  	o5 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order05", types.SideBuy, "party-A", 1, 10)
   307  	o5conf, err := tm.market.SubmitOrder(ctx, o5)
   308  	require.NotNil(t, o5conf)
   309  	require.NoError(t, err)
   310  
   311  	// assert.Equal(t, int64(3), tm.market.GetOrdersOnBookCount())
   312  	assert.Equal(t, int64(4), tm.market.GetOrdersOnBookCount())
   313  
   314  	// Move price high to force a closed out
   315  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 1, 100)
   316  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   317  	require.NotNil(t, o2conf)
   318  	require.NoError(t, err)
   319  
   320  	// assert.Equal(t, int64(4), tm.market.GetOrdersOnBookCount())
   321  	assert.Equal(t, int64(5), tm.market.GetOrdersOnBookCount())
   322  
   323  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideSell, "party-C", 100, 100)
   324  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   325  	require.NotNil(t, o3conf)
   326  	require.NoError(t, err)
   327  
   328  	md = tm.market.GetMarketData()
   329  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode, "market not continuous: %s (trigger: %s)", md.MarketTradingMode, md.Trigger)
   330  
   331  	// Check we have the right amount of events
   332  	assert.Equal(t, uint64(14), tm.orderEventCount)
   333  	assert.Equal(t, int64(3), tm.market.GetOrdersOnBookCount())
   334  
   335  	processEvents(t, tm, mdb)
   336  	assert.Equal(t, int64(3), mdb.GetOrderCount(tm.market.GetID()))
   337  	assert.Equal(t, uint64(1), mdb.GetOrderCountAtPrice(tm.market.GetID(), types.SideSell, 100))
   338  	assert.Equal(t, uint64(89), mdb.GetVolumeAtPrice(tm.market.GetID(), types.SideSell, 100))
   339  }
   340  
   341  func TestEvents_CloseOutPartyWithPeggedOrder(t *testing.T) {
   342  	t.Skip("there's some weird magic going on here...")
   343  	now := time.Unix(10, 0)
   344  	ctx := context.Background()
   345  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   346  	tm := startMarketInAuction(t, ctx, &now)
   347  
   348  	auxParty := "aux"
   349  	addAccount(t, tm, auxParty)
   350  	auxOrder1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy", types.SideBuy, auxParty, 1, 1)
   351  	conf, err := tm.market.SubmitOrder(ctx, auxOrder1)
   352  	require.NotNil(t, conf)
   353  	require.NoError(t, err)
   354  
   355  	auxOrder2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell", types.SideSell, auxParty, 1, 101)
   356  	conf, err = tm.market.SubmitOrder(ctx, auxOrder2)
   357  	require.NotNil(t, conf)
   358  	require.NoError(t, err)
   359  
   360  	leaveAuction(t, tm, ctx, &now)
   361  
   362  	md := tm.market.GetMarketData()
   363  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode)
   364  
   365  	assert.Equal(t, int64(2), tm.market.GetOrdersOnBookCount())
   366  
   367  	// Add a GFN order
   368  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFN, "Order01", types.SideSell, "party-A", 10, 2)
   369  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   370  	require.NotNil(t, o1conf)
   371  	require.NoError(t, err)
   372  
   373  	// Fill some of it to set the mark price
   374  	o4 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order04", types.SideBuy, "party-B", 10, 2)
   375  	o4conf, err := tm.market.SubmitOrder(ctx, o4)
   376  	require.NotNil(t, o4conf)
   377  	require.NoError(t, err)
   378  
   379  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 1, 100)
   380  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   381  	require.NotNil(t, o2conf)
   382  	require.NoError(t, err)
   383  
   384  	o6 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order06", types.SideBuy, "party-B", 1, 99)
   385  	o6conf, err := tm.market.SubmitOrder(ctx, o6)
   386  	require.NotNil(t, o6conf)
   387  	require.NoError(t, err)
   388  
   389  	// Place the pegged order
   390  	o5 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order05", types.SideBuy, "party-A", 1, 0)
   391  	o5.PeggedOrder = newPeggedOrder(types.PeggedReferenceBestBid, 1)
   392  	o5conf, err := tm.market.SubmitOrder(ctx, o5)
   393  	require.NotNil(t, o5conf)
   394  	require.NoError(t, err)
   395  
   396  	o7 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order07", types.SideBuy, "party-A", 1, 0)
   397  	o7.PeggedOrder = newPeggedOrder(types.PeggedReferenceBestBid, 1)
   398  	o7conf, err := tm.market.SubmitOrder(ctx, o7)
   399  	require.NotNil(t, o7conf)
   400  	require.NoError(t, err)
   401  
   402  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideSell, "party-C", 100, 100)
   403  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   404  	require.NotNil(t, o3conf)
   405  	require.NoError(t, err)
   406  
   407  	md = tm.market.GetMarketData()
   408  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode)
   409  
   410  	// Check we have the right amount of events
   411  	// assert.Equal(t, uint64(15), tm.orderEventCount)
   412  	assert.Equal(t, uint64(17), tm.orderEventCount)
   413  	assert.Equal(t, int64(4), tm.market.GetOrdersOnBookCount())
   414  
   415  	processEvents(t, tm, mdb)
   416  	assert.Equal(t, int64(4), mdb.GetOrderCount(tm.market.GetID()))
   417  	assert.Equal(t, uint64(1), mdb.GetOrderCountAtPrice(tm.market.GetID(), types.SideSell, 100))
   418  	assert.Equal(t, uint64(89), mdb.GetVolumeAtPrice(tm.market.GetID(), types.SideSell, 100))
   419  	assert.Equal(t, 0, tm.market.GetPeggedOrderCount())
   420  	assert.Equal(t, 0, tm.market.GetParkedOrderCount())
   421  }
   422  
   423  func TestEvents_PeggedOrderNotAbleToRepriceDueToMargin(t *testing.T) {
   424  	now := time.Unix(10, 0)
   425  	ctx := context.Background()
   426  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   427  	tm := startMarketInAuction(t, ctx, &now)
   428  
   429  	o0 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFA, "Order0", types.SideSell, "party-C", 1, 100)
   430  	o0conf, err := tm.market.SubmitOrder(ctx, o0)
   431  	require.NotNil(t, o0conf)
   432  	require.NoError(t, err)
   433  
   434  	o00 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFA, "Order00", types.SideBuy, "party-B", 1, 100)
   435  	o00conf, err := tm.market.SubmitOrder(ctx, o00)
   436  	require.NotNil(t, o00conf)
   437  	require.NoError(t, err)
   438  
   439  	leaveAuction(t, tm, ctx, &now)
   440  
   441  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order01", types.SideSell, "party-C", 1, 200)
   442  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   443  	require.NotNil(t, o1conf)
   444  	require.NoError(t, err)
   445  
   446  	// Fill some of it to set the mark price
   447  	o4 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order04", types.SideBuy, "party-B", 1, 100)
   448  	o4conf, err := tm.market.SubmitOrder(ctx, o4)
   449  	require.NotNil(t, o4conf)
   450  	require.NoError(t, err)
   451  
   452  	// Place the pegged order
   453  	o5 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order05", types.SideBuy, "party-A", 50, 0)
   454  	o5.PeggedOrder = newPeggedOrder(types.PeggedReferenceBestBid, 1)
   455  	o5conf, err := tm.market.SubmitOrder(ctx, o5)
   456  	require.NotNil(t, o5conf)
   457  	require.NoError(t, err)
   458  
   459  	// Move the best bid price up so that the pegged order cannot be repriced
   460  	o7 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order07", types.SideBuy, "party-B", 2, 200)
   461  	o7conf, err := tm.market.SubmitOrder(ctx, o7)
   462  	require.NotNil(t, o7conf)
   463  	require.NoError(t, err)
   464  
   465  	// Check we have the right amount of events
   466  	assert.Equal(t, uint64(9), tm.orderEventCount)
   467  	assert.Equal(t, int64(3), tm.market.GetOrdersOnBookCount())
   468  
   469  	processEvents(t, tm, mdb)
   470  	assert.Equal(t, int64(3), mdb.GetOrderCount(tm.market.GetID()))
   471  	assert.Equal(t, 1, tm.market.GetPeggedOrderCount())
   472  	assert.Equal(t, 1, tm.market.GetParkedOrderCount())
   473  }
   474  
   475  func TestEvents_EnteringAuctionParksAllPegs(t *testing.T) {
   476  	t.Skip("More weird magic vomiting in my face...")
   477  	now := time.Unix(10, 0)
   478  	ctx := context.Background()
   479  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   480  	tm := startMarketInAuction(t, ctx, &now)
   481  
   482  	auxParty := "aux"
   483  	addAccount(t, tm, auxParty)
   484  	auxOrder1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy", types.SideBuy, auxParty, 1, 1)
   485  	conf, err := tm.market.SubmitOrder(ctx, auxOrder1)
   486  	require.NotNil(t, conf)
   487  	require.NoError(t, err)
   488  
   489  	auxOrder2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell", types.SideSell, auxParty, 1, 1000001)
   490  	conf, err = tm.market.SubmitOrder(ctx, auxOrder2)
   491  	require.NotNil(t, conf)
   492  	require.NoError(t, err)
   493  
   494  	leaveAuction(t, tm, ctx, &now)
   495  
   496  	md := tm.market.GetMarketData()
   497  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode)
   498  
   499  	assert.Equal(t, int64(2), tm.market.GetOrdersOnBookCount())
   500  
   501  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order01", types.SideBuy, "party-C", 2, 10)
   502  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   503  	require.NotNil(t, o1conf)
   504  	require.NoError(t, err)
   505  
   506  	o5 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order05", types.SideSell, "party-B", 1, 10)
   507  	o5conf, err := tm.market.SubmitOrder(ctx, o5)
   508  	require.NotNil(t, o5conf)
   509  	require.NoError(t, err)
   510  
   511  	o4 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order04", types.SideBuy, "party-B", 1, 0)
   512  	o4.PeggedOrder = newPeggedOrder(types.PeggedReferenceBestBid, 1)
   513  	o4conf, err := tm.market.SubmitOrder(ctx, o4)
   514  	require.NotNil(t, o4conf)
   515  	require.NoError(t, err)
   516  
   517  	// Move the mark price super high to force a price auction
   518  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 1, 1000000)
   519  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   520  	require.NotNil(t, o2conf)
   521  	require.NoError(t, err)
   522  
   523  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideSell, "party-C", 1, 1000000)
   524  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   525  	require.NotNil(t, o3conf)
   526  	require.NoError(t, err)
   527  
   528  	// Check we are in a price auction
   529  	assert.Equal(t, types.AuctionTriggerPrice, tm.market.GetMarketData().Trigger)
   530  
   531  	// Check we have the right amount of events
   532  	assert.Equal(t, uint64(10), tm.orderEventCount)
   533  	assert.Equal(t, int64(5), tm.market.GetOrdersOnBookCount())
   534  
   535  	processEvents(t, tm, mdb)
   536  	assert.Equal(t, int64(5), mdb.GetOrderCount(tm.market.GetID()))
   537  	assert.Equal(t, 5, mdb.GetPriceLevels(tm.market.GetID()))
   538  }
   539  
   540  func TestEvents_SelfTrading(t *testing.T) {
   541  	t.Skip("Are these all broken??")
   542  	now := time.Unix(10, 0)
   543  	ctx := context.Background()
   544  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   545  	tm := startMarketInAuction(t, ctx, &now)
   546  
   547  	auxParty := "aux"
   548  	addAccount(t, tm, auxParty)
   549  	auxOrder1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy", types.SideBuy, auxParty, 1, 1)
   550  	conf, err := tm.market.SubmitOrder(ctx, auxOrder1)
   551  	require.NotNil(t, conf)
   552  	require.NoError(t, err)
   553  
   554  	auxOrder2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell", types.SideSell, auxParty, 1, 101)
   555  	conf, err = tm.market.SubmitOrder(ctx, auxOrder2)
   556  	require.NotNil(t, conf)
   557  	require.NoError(t, err)
   558  
   559  	leaveAuction(t, tm, ctx, &now)
   560  
   561  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order01", types.SideBuy, "party-C", 1, 10)
   562  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   563  	require.NotNil(t, o1conf)
   564  	require.NoError(t, err)
   565  
   566  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 1, 10)
   567  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   568  	require.NotNil(t, o2conf)
   569  	require.NoError(t, err)
   570  
   571  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideSell, "party-B", 2, 10)
   572  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   573  	require.NotNil(t, o3conf)
   574  	require.NoError(t, err)
   575  
   576  	// Check we have the right amount of events
   577  	assert.Equal(t, uint64(6), tm.orderEventCount)
   578  	assert.Equal(t, int64(3), tm.market.GetOrdersOnBookCount())
   579  
   580  	processEvents(t, tm, mdb)
   581  	assert.Equal(t, int64(3), mdb.GetOrderCount(tm.market.GetID()))
   582  	assert.Equal(t, 3, mdb.GetPriceLevels(tm.market.GetID()))
   583  }
   584  
   585  func TestEvents_Amending(t *testing.T) {
   586  	now := time.Unix(10, 0)
   587  	ctx := context.Background()
   588  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   589  	tm := startMarketInAuction(t, ctx, &now)
   590  
   591  	o0 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFA, "Order0", types.SideSell, "party-C", 1, 100)
   592  	o0conf, err := tm.market.SubmitOrder(ctx, o0)
   593  	require.NotNil(t, o0conf)
   594  	require.NoError(t, err)
   595  
   596  	o00 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFA, "Order00", types.SideBuy, "party-B", 1, 100)
   597  	o00conf, err := tm.market.SubmitOrder(ctx, o00)
   598  	require.NotNil(t, o00conf)
   599  	require.NoError(t, err)
   600  
   601  	leaveAuction(t, tm, ctx, &now)
   602  
   603  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order01", types.SideBuy, "party-C", 1, 10)
   604  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   605  	require.NotNil(t, o1conf)
   606  	require.NoError(t, err)
   607  
   608  	amendment := &types.OrderAmendment{
   609  		OrderID:  o1.ID,
   610  		MarketID: o1.MarketID,
   611  		Price:    num.NewUint(11),
   612  	}
   613  
   614  	amendConf, err := tm.market.AmendOrder(ctx, amendment, o1.Party, vgcrypto.RandomHash())
   615  	assert.NotNil(t, amendConf)
   616  	assert.NoError(t, err)
   617  
   618  	amendment.Price = num.NewUint(9)
   619  	amendConf, err = tm.market.AmendOrder(ctx, amendment, o1.Party, vgcrypto.RandomHash())
   620  	assert.NotNil(t, amendConf)
   621  	assert.NoError(t, err)
   622  
   623  	amendment.Price = nil
   624  	amendment.SizeDelta = 3
   625  	amendConf, err = tm.market.AmendOrder(ctx, amendment, o1.Party, vgcrypto.RandomHash())
   626  	assert.NotNil(t, amendConf)
   627  	assert.NoError(t, err)
   628  
   629  	amendment.SizeDelta = -2
   630  	amendConf, err = tm.market.AmendOrder(ctx, amendment, o1.Party, vgcrypto.RandomHash())
   631  	assert.NotNil(t, amendConf)
   632  	assert.NoError(t, err)
   633  
   634  	amendment.SizeDelta = 1
   635  	amendment.Price = num.NewUint(10)
   636  	amendConf, err = tm.market.AmendOrder(ctx, amendment, o1.Party, vgcrypto.RandomHash())
   637  	assert.NotNil(t, amendConf)
   638  	assert.NoError(t, err)
   639  
   640  	// Check we have the right amount of events
   641  	assert.Equal(t, uint64(10), tm.orderEventCount)
   642  	assert.Equal(t, int64(1), tm.market.GetOrdersOnBookCount())
   643  
   644  	processEvents(t, tm, mdb)
   645  	assert.Equal(t, int64(1), mdb.GetOrderCount(tm.market.GetID()))
   646  	assert.Equal(t, 1, mdb.GetPriceLevels(tm.market.GetID()))
   647  }
   648  
   649  func TestEvents_MovingPegsAround(t *testing.T) {
   650  	t.Skip("yeah.. tests of doom")
   651  	now := time.Unix(10, 0)
   652  	ctx := context.Background()
   653  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   654  	tm := startMarketInAuction(t, ctx, &now)
   655  
   656  	auxParty := "aux"
   657  	addAccount(t, tm, auxParty)
   658  	auxOrder1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy", types.SideBuy, auxParty, 1, 1)
   659  	conf, err := tm.market.SubmitOrder(ctx, auxOrder1)
   660  	require.NotNil(t, conf)
   661  	require.NoError(t, err)
   662  
   663  	auxOrder2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell", types.SideSell, auxParty, 1, 101)
   664  	conf, err = tm.market.SubmitOrder(ctx, auxOrder2)
   665  	require.NotNil(t, conf)
   666  	require.NoError(t, err)
   667  
   668  	leaveAuction(t, tm, ctx, &now)
   669  
   670  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order01", types.SideSell, "party-C", 1, 20)
   671  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   672  	require.NotNil(t, o1conf)
   673  	require.NoError(t, err)
   674  
   675  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 1, 10)
   676  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   677  	require.NotNil(t, o2conf)
   678  	require.NoError(t, err)
   679  
   680  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideBuy, "party-A", 1, 0)
   681  	o3.PeggedOrder = newPeggedOrder(types.PeggedReferenceBestBid, 1)
   682  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   683  	require.NotNil(t, o3conf)
   684  	require.NoError(t, err)
   685  
   686  	amendment := &types.OrderAmendment{
   687  		OrderID:  o2.ID,
   688  		MarketID: o2.MarketID,
   689  		Price:    num.NewUint(8),
   690  	}
   691  
   692  	amendConf, err := tm.market.AmendOrder(ctx, amendment, o2.Party, vgcrypto.RandomHash())
   693  	assert.NotNil(t, amendConf)
   694  	assert.NoError(t, err)
   695  
   696  	amendment.Price = num.NewUint(18)
   697  	amendConf, err = tm.market.AmendOrder(ctx, amendment, o2.Party, vgcrypto.RandomHash())
   698  	assert.NotNil(t, amendConf)
   699  	assert.NoError(t, err)
   700  
   701  	amendment.Price = num.NewUint(22)
   702  	amendConf, err = tm.market.AmendOrder(ctx, amendment, o2.Party, vgcrypto.RandomHash())
   703  	assert.NotNil(t, amendConf)
   704  	assert.NoError(t, err)
   705  
   706  	// Check we have the right amount of events
   707  	assert.Equal(t, uint64(12), tm.orderEventCount)
   708  	assert.Equal(t, int64(2), tm.market.GetOrdersOnBookCount())
   709  
   710  	processEvents(t, tm, mdb)
   711  	assert.Equal(t, int64(2), mdb.GetOrderCount(tm.market.GetID()))
   712  	assert.Equal(t, 2, mdb.GetPriceLevels(tm.market.GetID()))
   713  }
   714  
   715  func TestEvents_MovingPegsAround2(t *testing.T) {
   716  	t.Skip("tests are doomed")
   717  	now := time.Unix(10, 0)
   718  	ctx := context.Background()
   719  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   720  	tm := startMarketInAuction(t, ctx, &now)
   721  
   722  	auxParty := "aux"
   723  	addAccount(t, tm, auxParty)
   724  	auxOrder1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy", types.SideBuy, auxParty, 1, 1)
   725  	conf, err := tm.market.SubmitOrder(ctx, auxOrder1)
   726  	require.NotNil(t, conf)
   727  	require.NoError(t, err)
   728  
   729  	auxOrder2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell", types.SideSell, auxParty, 1, 101)
   730  	conf, err = tm.market.SubmitOrder(ctx, auxOrder2)
   731  	require.NotNil(t, conf)
   732  	require.NoError(t, err)
   733  
   734  	leaveAuction(t, tm, ctx, &now)
   735  
   736  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order01", types.SideSell, "party-C", 2, 20)
   737  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   738  	require.NotNil(t, o1conf)
   739  	require.NoError(t, err)
   740  
   741  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 1, 10)
   742  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   743  	require.NotNil(t, o2conf)
   744  	require.NoError(t, err)
   745  
   746  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideBuy, "party-A", 1, 0)
   747  	o3.PeggedOrder = newPeggedOrder(types.PeggedReferenceBestBid, 1)
   748  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   749  	require.NotNil(t, o3conf)
   750  	require.NoError(t, err)
   751  
   752  	amendment := &types.OrderAmendment{
   753  		OrderID:  o1.ID,
   754  		MarketID: o1.MarketID,
   755  		Price:    num.NewUint(9),
   756  	}
   757  
   758  	amendConf, err := tm.market.AmendOrder(ctx, amendment, o1.Party, vgcrypto.RandomHash())
   759  	assert.NotNil(t, amendConf)
   760  	assert.NoError(t, err)
   761  
   762  	// Check we have the right amount of events
   763  	assert.Equal(t, uint64(8), tm.orderEventCount)
   764  	assert.Equal(t, int64(2), tm.market.GetOrdersOnBookCount())
   765  
   766  	processEvents(t, tm, mdb)
   767  	assert.Equal(t, int64(2), mdb.GetOrderCount(tm.market.GetID()))
   768  	assert.Equal(t, 2, mdb.GetPriceLevels(tm.market.GetID()))
   769  }
   770  
   771  func TestEvents_AmendOrderToSelfTrade(t *testing.T) {
   772  	t.Skip("The pony comes...")
   773  	now := time.Unix(10, 0)
   774  	ctx := context.Background()
   775  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   776  	tm := startMarketInAuction(t, ctx, &now)
   777  
   778  	auxParty := "aux"
   779  	addAccount(t, tm, auxParty)
   780  	auxOrder1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy", types.SideBuy, auxParty, 1, 1)
   781  	conf, err := tm.market.SubmitOrder(ctx, auxOrder1)
   782  	require.NotNil(t, conf)
   783  	require.NoError(t, err)
   784  
   785  	auxOrder2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell", types.SideSell, auxParty, 1, 101)
   786  	conf, err = tm.market.SubmitOrder(ctx, auxOrder2)
   787  	require.NotNil(t, conf)
   788  	require.NoError(t, err)
   789  
   790  	leaveAuction(t, tm, ctx, &now)
   791  
   792  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order01", types.SideBuy, "party-C", 1, 10)
   793  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   794  	require.NotNil(t, o1conf)
   795  	require.NoError(t, err)
   796  
   797  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 1, 10)
   798  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   799  	require.NotNil(t, o2conf)
   800  	require.NoError(t, err)
   801  
   802  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideSell, "party-B", 2, 11)
   803  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   804  	require.NotNil(t, o3conf)
   805  	require.NoError(t, err)
   806  
   807  	amendment := &types.OrderAmendment{
   808  		OrderID:  o3.ID,
   809  		MarketID: o3.MarketID,
   810  		Price:    num.NewUint(10),
   811  	}
   812  
   813  	amendConf, err := tm.market.AmendOrder(ctx, amendment, o3.Party, vgcrypto.RandomHash())
   814  	assert.NotNil(t, amendConf)
   815  	assert.NoError(t, err)
   816  
   817  	// Check we have the right amount of events
   818  	assert.Equal(t, uint64(7), tm.orderEventCount)
   819  	assert.Equal(t, int64(3), tm.market.GetOrdersOnBookCount())
   820  
   821  	processEvents(t, tm, mdb)
   822  	assert.Equal(t, int64(3), mdb.GetOrderCount(tm.market.GetID()))
   823  	assert.Equal(t, 3, mdb.GetPriceLevels(tm.market.GetID()))
   824  }
   825  
   826  func TestEvents_AmendOrderToIncreaseSizeAndPartiallyFill(t *testing.T) {
   827  	t.Skip("The end is upon us")
   828  	now := time.Unix(10, 0)
   829  	ctx := context.Background()
   830  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   831  	tm := startMarketInAuction(t, ctx, &now)
   832  
   833  	auxParty := "aux"
   834  	addAccount(t, tm, auxParty)
   835  	auxOrder1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderBuy", types.SideBuy, auxParty, 1, 1)
   836  	conf, err := tm.market.SubmitOrder(ctx, auxOrder1)
   837  	require.NotNil(t, conf)
   838  	require.NoError(t, err)
   839  
   840  	auxOrder2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "AuxOrderSell", types.SideSell, auxParty, 1, 101)
   841  	conf, err = tm.market.SubmitOrder(ctx, auxOrder2)
   842  	require.NotNil(t, conf)
   843  	require.NoError(t, err)
   844  
   845  	leaveAuction(t, tm, ctx, &now)
   846  
   847  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order01", types.SideBuy, "party-C", 5, 10)
   848  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   849  	require.NotNil(t, o1conf)
   850  	require.NoError(t, err)
   851  
   852  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 5, 11)
   853  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   854  	require.NotNil(t, o2conf)
   855  	require.NoError(t, err)
   856  
   857  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideSell, "party-A", 1, 12)
   858  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   859  	require.NotNil(t, o3conf)
   860  	require.NoError(t, err)
   861  
   862  	amendment := &types.OrderAmendment{
   863  		OrderID:   o3.ID,
   864  		MarketID:  o3.MarketID,
   865  		Price:     num.NewUint(11),
   866  		SizeDelta: 5,
   867  	}
   868  
   869  	amendConf, err := tm.market.AmendOrder(ctx, amendment, o3.Party, vgcrypto.RandomHash())
   870  	assert.NotNil(t, amendConf)
   871  	assert.NoError(t, err)
   872  
   873  	// Check we have the right amount of events
   874  	assert.Equal(t, uint64(7), tm.orderEventCount)
   875  	assert.Equal(t, int64(4), tm.market.GetOrdersOnBookCount())
   876  
   877  	processEvents(t, tm, mdb)
   878  	assert.Equal(t, int64(4), mdb.GetOrderCount(tm.market.GetID()))
   879  	assert.Equal(t, 4, mdb.GetPriceLevels(tm.market.GetID()))
   880  }
   881  
   882  func TestEvents_CloseOutPartyWithNotEnoughLiquidity(t *testing.T) {
   883  	t.Skip("Jehova!!!")
   884  	now := time.Unix(10, 0)
   885  	ctx := context.Background()
   886  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   887  	tm := startMarketInAuction(t, ctx, &now)
   888  
   889  	// place some orders on the book for when we leave auction
   890  	addAccountWithAmount(tm, "party-X", 100000000)
   891  	addAccountWithAmount(tm, "party-Y", 100000000)
   892  
   893  	orders := []*types.Order{
   894  		getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFA, "auctionOrder1", types.SideSell, "party-X", 5, 1),
   895  		getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFA, "auctionOrder2", types.SideBuy, "party-Y", 5, 1),
   896  		getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "auctionOrder3", types.SideSell, "party-X", 10, 3),
   897  		getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "auctionOrder4", types.SideBuy, "party-Y", 10, 2),
   898  	}
   899  	for _, o := range orders {
   900  		_, err := tm.market.SubmitOrder(ctx, o)
   901  		assert.NoError(t, err)
   902  	}
   903  	// move time forwards 20 seconds, so the opening auction can end
   904  	now = now.Add(time.Second * 20)
   905  	tm.market.OnTick(ctx, now)
   906  	// leaveAuction(tm, ctx, &now)
   907  
   908  	// Add a GFN order
   909  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFN, "Order01", types.SideSell, "party-A", 30, 1)
   910  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   911  	require.NotNil(t, o1conf)
   912  	require.NoError(t, err)
   913  
   914  	// Fill some of it to set the mark price
   915  	o4 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order04", types.SideBuy, "party-B", 30, 1)
   916  	o4conf, err := tm.market.SubmitOrder(ctx, o4)
   917  	require.NotNil(t, o4conf)
   918  	require.NoError(t, err)
   919  
   920  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideBuy, "party-B", 1, 100)
   921  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   922  	require.NotNil(t, o2conf)
   923  	require.NoError(t, err)
   924  
   925  	o6 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order06", types.SideBuy, "party-B", 1, 99)
   926  	o6conf, err := tm.market.SubmitOrder(ctx, o6)
   927  	require.NotNil(t, o6conf)
   928  	require.NoError(t, err)
   929  
   930  	// Place the pegged order
   931  	o5 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order05", types.SideBuy, "party-A", 1, 0)
   932  	o5.PeggedOrder = newPeggedOrder(types.PeggedReferenceBestBid, 1)
   933  	o5conf, err := tm.market.SubmitOrder(ctx, o5)
   934  	require.NotNil(t, o5conf)
   935  	require.NoError(t, err)
   936  
   937  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideSell, "party-C", 10, 100)
   938  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
   939  	require.NotNil(t, o3conf)
   940  	require.NoError(t, err)
   941  
   942  	// Check we have the right amount of events
   943  	assert.Equal(t, uint64(15), tm.orderEventCount)
   944  	assert.Equal(t, int64(5), tm.market.GetOrdersOnBookCount())
   945  
   946  	processEvents(t, tm, mdb)
   947  	assert.Equal(t, int64(5), mdb.GetOrderCount(tm.market.GetID()))
   948  	assert.Equal(t, uint64(1), mdb.GetOrderCountAtPrice(tm.market.GetID(), types.SideSell, 100))
   949  	assert.Equal(t, uint64(10), mdb.GetVolumeAtPrice(tm.market.GetID(), types.SideSell, 100))
   950  	assert.Equal(t, 1, tm.market.GetPeggedOrderCount())
   951  	assert.Equal(t, 1, tm.market.GetParkedOrderCount())
   952  }
   953  
   954  func TestEvents_PeggedOrders(t *testing.T) {
   955  	t.Skip("Multi-coloured skittles and an astronaut")
   956  	now := time.Unix(10, 0)
   957  	ctx := context.Background()
   958  	mdb := subscribers.NewMarketDepthBuilder(ctx, nil, true)
   959  	tm := startMarketInAuction(t, ctx, &now)
   960  	// place some orders on the book for when we leave auction
   961  	addAccountWithAmount(tm, "party-X", 100000000)
   962  	addAccountWithAmount(tm, "party-Y", 100000000)
   963  
   964  	orders := []*types.Order{
   965  		getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFA, "auctionOrder1", types.SideSell, "party-X", 5, 100),
   966  		getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFA, "auctionOrder2", types.SideBuy, "party-Y", 5, 100),
   967  		getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "auctionOrder3", types.SideSell, "party-X", 10, 103),
   968  		getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "auctionOrder4", types.SideBuy, "party-Y", 10, 102),
   969  	}
   970  	for _, o := range orders {
   971  		_, err := tm.market.SubmitOrder(ctx, o)
   972  		assert.NoError(t, err)
   973  	}
   974  	// move time forwards 20 seconds, so the opening auction can end
   975  	now = now.Add(time.Second * 20)
   976  	tm.market.OnTick(ctx, now)
   977  	// leaveAuction(tm, ctx, &now)
   978  
   979  	o1 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGFN, "Order01", types.SideBuy, "party-B", 2, 100)
   980  	o1conf, err := tm.market.SubmitOrder(ctx, o1)
   981  	require.NotNil(t, o1conf)
   982  	require.NoError(t, err)
   983  
   984  	o4 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order04", types.SideBuy, "party-B", 2, 98)
   985  	o4conf, err := tm.market.SubmitOrder(ctx, o4)
   986  	require.NotNil(t, o4conf)
   987  	require.NoError(t, err)
   988  
   989  	o2 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order02", types.SideSell, "party-C", 2, 110)
   990  	o2conf, err := tm.market.SubmitOrder(ctx, o2)
   991  	require.NotNil(t, o2conf)
   992  	require.NoError(t, err)
   993  
   994  	o6 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order06", types.SideSell, "party-C", 2, 112)
   995  	o6conf, err := tm.market.SubmitOrder(ctx, o6)
   996  	require.NotNil(t, o6conf)
   997  	require.NoError(t, err)
   998  
   999  	// Place the pegged order
  1000  	o5 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order05", types.SideBuy, "party-A", 1, 0)
  1001  	o5.PeggedOrder = newPeggedOrder(types.PeggedReferenceBestBid, 1)
  1002  	o5conf, err := tm.market.SubmitOrder(ctx, o5)
  1003  	require.NotNil(t, o5conf)
  1004  	require.NoError(t, err)
  1005  
  1006  	o7 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order07", types.SideBuy, "party-A", 1, 0)
  1007  	o7.PeggedOrder = newPeggedOrder(types.PeggedReferenceBestBid, 99)
  1008  	o7conf, err := tm.market.SubmitOrder(ctx, o7)
  1009  	require.NotNil(t, o7conf)
  1010  	require.NoError(t, err)
  1011  
  1012  	// Now cause the best bid to drop and cause a reprice
  1013  	o3 := getMarketOrder(tm, now, types.OrderTypeLimit, types.OrderTimeInForceGTC, "Order03", types.SideSell, "party-C", 2, 100)
  1014  	o3conf, err := tm.market.SubmitOrder(ctx, o3)
  1015  	require.NotNil(t, o3conf)
  1016  	require.NoError(t, err)
  1017  
  1018  	// Check we have the right amount of events
  1019  	assert.Equal(t, uint64(15), tm.orderEventCount)
  1020  	assert.Equal(t, int64(8), tm.market.GetOrdersOnBookCount())
  1021  
  1022  	processEvents(t, tm, mdb)
  1023  	assert.Equal(t, 2, tm.market.GetPeggedOrderCount())
  1024  	assert.Equal(t, 0, tm.market.GetParkedOrderCount()) // ??
  1025  }