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 }