code.vegaprotocol.io/vega@v0.79.0/core/matching/order_status_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_test 17 18 import ( 19 "testing" 20 21 "code.vegaprotocol.io/vega/core/events" 22 "code.vegaprotocol.io/vega/core/types" 23 vgcrypto "code.vegaprotocol.io/vega/libs/crypto" 24 "code.vegaprotocol.io/vega/libs/num" 25 26 "github.com/stretchr/testify/assert" 27 ) 28 29 func TestOrderStatuses(t *testing.T) { 30 t.Run("FOK - stopped", testFOKStopped) 31 t.Run("FOK - filled", testFOKFilled) 32 33 t.Run("IOC - stopped", testIOCStopped) 34 t.Run("IOC - partially filled", testIOCPartiallyFilled) 35 t.Run("IOC - filled", testIOCFilled) 36 37 t.Run("GTC - active", testGTCActive) 38 t.Run("GTC - stopped not filled", testGTCStoppedNotFilled) 39 t.Run("GTC - cancelled not filled", testGTCCancelledNotFilled) 40 t.Run("GTC - active partially filled", testGTCActivePartiallyFilled) 41 t.Run("GTC - cancelled partially filled", testGTCCancelledPartiallyFilled) 42 t.Run("GTC - stopped partially filled", testGTCStoppedPartiallyFilled) 43 t.Run("GTC - filled", testGTCFilled) 44 45 t.Run("GTT - active", testGTTActive) 46 t.Run("GTT - cancelled not filled", testGTTCancelledNotFilled) 47 t.Run("GTT - stopped not filled", testGTTStoppedNotFilled) 48 t.Run("GTT - active partially filled", testGTTActivePartiallyFilled) 49 t.Run("GTT - cancelled partially filled", testGTTCancelledPartiallyFilled) 50 t.Run("GTT - stopped partially filled", testGTTStoppedPartiallyFilled) 51 t.Run("GTT - filled", testGTTFilled) 52 53 // the following test from the specs is not added as it is not possible to test through the order book. 54 // and it's not possible for an order to become expired once it's been filled as the order is removed 55 // from the book, and the book is setting up orders. 56 // | GTT | Yes | Yes | No | No | Filled | 57 } 58 59 func testFOKStopped(t *testing.T) { 60 market := "testMarket" 61 partyID := "p1" 62 book := getTestOrderBook(t, market) 63 defer book.Finish() 64 order := types.Order{ 65 Status: types.OrderStatusActive, 66 MarketID: market, 67 Party: partyID, 68 Side: types.SideSell, 69 Price: num.NewUint(100), 70 OriginalPrice: num.NewUint(100), 71 Size: 1, 72 Remaining: 1, 73 TimeInForce: types.OrderTimeInForceFOK, 74 Type: types.OrderTypeLimit, 75 } 76 confirm, err := book.ob.SubmitOrder(&order) 77 assert.NoError(t, err) 78 assert.Equal(t, 0, len(confirm.Trades)) 79 assert.Equal(t, types.OrderStatusStopped, order.Status) 80 } 81 82 func testFOKFilled(t *testing.T) { 83 market := "testMarket" 84 partyID1 := "p1" 85 partyID2 := "p2" 86 87 book := getTestOrderBook(t, market) 88 defer book.Finish() 89 90 // place a first order to sit in the book 91 order1 := types.Order{ 92 ID: "V0000000032-0000000009", 93 Status: types.OrderStatusActive, 94 MarketID: market, 95 Party: partyID1, 96 Side: types.SideSell, 97 Price: num.NewUint(100), 98 OriginalPrice: num.NewUint(100), 99 Size: 1, 100 Remaining: 1, 101 TimeInForce: types.OrderTimeInForceGTC, 102 Type: types.OrderTypeLimit, 103 } 104 _, err := book.ob.SubmitOrder(&order1) 105 assert.NoError(t, err) 106 107 // now place our fok order to be filled 108 order := types.Order{ 109 ID: "V0000000032-0000000010", 110 Status: types.OrderStatusActive, 111 MarketID: market, 112 Party: partyID2, 113 Side: types.SideBuy, 114 Price: num.NewUint(100), 115 OriginalPrice: num.NewUint(100), 116 Size: 1, 117 Remaining: 1, 118 TimeInForce: types.OrderTimeInForceFOK, 119 Type: types.OrderTypeLimit, 120 } 121 confirm, err := book.ob.SubmitOrder(&order) 122 assert.NoError(t, err) 123 assert.Equal(t, 1, len(confirm.Trades)) 124 assert.Equal(t, types.OrderStatusFilled, order.Status) 125 } 126 127 func testIOCStopped(t *testing.T) { 128 market := "testMarket" 129 partyID := "p1" 130 book := getTestOrderBook(t, market) 131 defer book.Finish() 132 order := types.Order{ 133 Status: types.OrderStatusActive, 134 MarketID: market, 135 Party: partyID, 136 Side: types.SideSell, 137 Price: num.NewUint(100), 138 OriginalPrice: num.NewUint(100), 139 Size: 1, 140 Remaining: 1, 141 TimeInForce: types.OrderTimeInForceIOC, 142 Type: types.OrderTypeLimit, 143 } 144 confirm, err := book.ob.SubmitOrder(&order) 145 assert.NoError(t, err) 146 assert.Equal(t, 0, len(confirm.Trades)) 147 assert.Equal(t, types.OrderStatusStopped, order.Status) 148 } 149 150 func testIOCPartiallyFilled(t *testing.T) { 151 market := "testMarket" 152 partyID1 := "p1" 153 partyID2 := "p2" 154 155 book := getTestOrderBook(t, market) 156 defer book.Finish() 157 158 // place a first order to sit in the book 159 order1 := types.Order{ 160 ID: "V0000000032-0000000009", 161 Status: types.OrderStatusActive, 162 MarketID: market, 163 Party: partyID1, 164 Side: types.SideSell, 165 Price: num.NewUint(100), 166 OriginalPrice: num.NewUint(100), 167 Size: 1, 168 Remaining: 1, 169 TimeInForce: types.OrderTimeInForceGTC, 170 Type: types.OrderTypeLimit, 171 } 172 _, err := book.ob.SubmitOrder(&order1) 173 assert.NoError(t, err) 174 175 // now place our IOC order to be filled 176 order := types.Order{ 177 ID: "V0000000032-0000000010", 178 Status: types.OrderStatusActive, 179 MarketID: market, 180 Party: partyID2, 181 Side: types.SideBuy, 182 Price: num.NewUint(100), 183 OriginalPrice: num.NewUint(100), 184 Size: 2, 185 Remaining: 2, 186 TimeInForce: types.OrderTimeInForceIOC, 187 Type: types.OrderTypeLimit, 188 } 189 confirm, err := book.ob.SubmitOrder(&order) 190 assert.NoError(t, err) 191 assert.Equal(t, 1, len(confirm.Trades)) 192 assert.Equal(t, types.OrderStatusPartiallyFilled, order.Status) 193 } 194 195 func testIOCFilled(t *testing.T) { 196 market := "testMarket" 197 partyID1 := "p1" 198 partyID2 := "p2" 199 200 book := getTestOrderBook(t, market) 201 defer book.Finish() 202 203 // place a first order to sit in the book 204 order1 := types.Order{ 205 ID: "V0000000032-0000000009", 206 Status: types.OrderStatusActive, 207 MarketID: market, 208 Party: partyID1, 209 Side: types.SideSell, 210 Price: num.NewUint(100), 211 OriginalPrice: num.NewUint(100), 212 Size: 1, 213 Remaining: 1, 214 TimeInForce: types.OrderTimeInForceGTC, 215 Type: types.OrderTypeLimit, 216 } 217 _, err := book.ob.SubmitOrder(&order1) 218 assert.NoError(t, err) 219 220 // now place our fok order to be filled 221 order := types.Order{ 222 ID: "V0000000032-0000000010", 223 Status: types.OrderStatusActive, 224 MarketID: market, 225 Party: partyID2, 226 Side: types.SideBuy, 227 Price: num.NewUint(100), 228 OriginalPrice: num.NewUint(100), 229 Size: 1, 230 Remaining: 1, 231 TimeInForce: types.OrderTimeInForceIOC, 232 Type: types.OrderTypeLimit, 233 } 234 confirm, err := book.ob.SubmitOrder(&order) 235 assert.NoError(t, err) 236 assert.Equal(t, 1, len(confirm.Trades)) 237 assert.Equal(t, types.OrderStatusFilled, order.Status) 238 } 239 240 func testGTCActive(t *testing.T) { 241 market := "testMarket" 242 partyID1 := "p1" 243 orderID := "v0000000000000-0000001" 244 245 book := getTestOrderBook(t, market) 246 defer book.Finish() 247 248 order1 := types.Order{ 249 Status: types.OrderStatusActive, 250 ID: orderID, 251 MarketID: market, 252 Party: partyID1, 253 Side: types.SideSell, 254 Price: num.NewUint(100), 255 OriginalPrice: num.NewUint(100), 256 Size: 10, 257 Remaining: 10, 258 TimeInForce: types.OrderTimeInForceGTC, 259 Type: types.OrderTypeLimit, 260 } 261 _, err := book.ob.SubmitOrder(&order1) 262 assert.NoError(t, err) 263 assert.Equal(t, types.OrderStatusActive, order1.Status) 264 } 265 266 func testGTCStoppedNotFilled(t *testing.T) { 267 market := "testMarket" 268 partyID1 := "p1" 269 orderID := vgcrypto.RandomHash() 270 271 book := getTestOrderBook(t, market) 272 defer book.Finish() 273 274 order1 := types.Order{ 275 Status: types.OrderStatusActive, 276 ID: orderID, 277 MarketID: market, 278 Party: partyID1, 279 Side: types.SideSell, 280 Price: num.NewUint(100), 281 OriginalPrice: num.NewUint(100), 282 Size: 10, 283 Remaining: 10, 284 TimeInForce: types.OrderTimeInForceGTC, 285 Type: types.OrderTypeLimit, 286 } 287 _, err := book.ob.SubmitOrder(&order1) 288 assert.NoError(t, err) 289 290 // then stop the order 291 rmOrders, err := book.ob.RemoveDistressedOrders([]events.MarketPosition{marketPositionFake{partyID1}}) 292 assert.NoError(t, err) 293 assert.Len(t, rmOrders, 1) 294 assert.Equal(t, types.OrderStatusStopped, rmOrders[0].Status) 295 } 296 297 func testGTCCancelledNotFilled(t *testing.T) { 298 market := "testMarket" 299 partyID1 := "p1" 300 orderID := vgcrypto.RandomHash() 301 302 book := getTestOrderBook(t, market) 303 defer book.Finish() 304 305 order1 := types.Order{ 306 Status: types.OrderStatusActive, 307 ID: orderID, 308 MarketID: market, 309 Party: partyID1, 310 Side: types.SideSell, 311 Price: num.NewUint(100), 312 OriginalPrice: num.NewUint(100), 313 Size: 10, 314 Remaining: 10, 315 TimeInForce: types.OrderTimeInForceGTC, 316 Type: types.OrderTypeLimit, 317 } 318 _, err := book.ob.SubmitOrder(&order1) 319 assert.NoError(t, err) 320 321 // then stop the order 322 confirm, err := book.ob.CancelOrder(&order1) 323 assert.NoError(t, err) 324 assert.Equal(t, types.OrderStatusCancelled, confirm.Order.Status) 325 } 326 327 func testGTCActivePartiallyFilled(t *testing.T) { 328 market := "testMarket" 329 partyID1 := "p1" 330 partyID2 := "p2" 331 orderID := vgcrypto.RandomHash() 332 333 book := getTestOrderBook(t, market) 334 defer book.Finish() 335 336 // place a first order to sit in the book, be partially filled, and stopped 337 order1 := types.Order{ 338 Status: types.OrderStatusActive, 339 ID: orderID, 340 MarketID: market, 341 Party: partyID1, 342 Side: types.SideSell, 343 Price: num.NewUint(100), 344 OriginalPrice: num.NewUint(100), 345 Size: 10, 346 Remaining: 10, 347 TimeInForce: types.OrderTimeInForceGTC, 348 Type: types.OrderTypeLimit, 349 } 350 _, err := book.ob.SubmitOrder(&order1) 351 assert.NoError(t, err) 352 353 // now place our order which will consume some of the first order 354 order := types.Order{ 355 ID: vgcrypto.RandomHash(), 356 Status: types.OrderStatusActive, 357 MarketID: market, 358 Party: partyID2, 359 Side: types.SideBuy, 360 Price: num.NewUint(100), 361 OriginalPrice: num.NewUint(100), 362 Size: 1, 363 Remaining: 1, 364 TimeInForce: types.OrderTimeInForceGTC, 365 Type: types.OrderTypeLimit, 366 } 367 confirm, err := book.ob.SubmitOrder(&order) 368 assert.NoError(t, err) 369 assert.Len(t, confirm.PassiveOrdersAffected, 1) 370 assert.Equal(t, types.OrderStatusActive, confirm.PassiveOrdersAffected[0].Status) 371 } 372 373 func testGTCCancelledPartiallyFilled(t *testing.T) { 374 market := "testMarket" 375 partyID1 := "p1" 376 partyID2 := "p2" 377 orderID := vgcrypto.RandomHash() 378 379 book := getTestOrderBook(t, market) 380 defer book.Finish() 381 382 // place a first order to sit in the book, be partially filled, and stopped 383 order1 := types.Order{ 384 Status: types.OrderStatusActive, 385 ID: orderID, 386 MarketID: market, 387 Party: partyID1, 388 Side: types.SideSell, 389 Price: num.NewUint(100), 390 OriginalPrice: num.NewUint(100), 391 Size: 10, 392 Remaining: 10, 393 TimeInForce: types.OrderTimeInForceGTC, 394 Type: types.OrderTypeLimit, 395 } 396 _, err := book.ob.SubmitOrder(&order1) 397 assert.NoError(t, err) 398 399 // now place our order which will consume some of the first order 400 order := types.Order{ 401 Status: types.OrderStatusActive, 402 MarketID: market, 403 Party: partyID2, 404 Side: types.SideBuy, 405 Price: num.NewUint(100), 406 OriginalPrice: num.NewUint(100), 407 Size: 1, 408 Remaining: 1, 409 TimeInForce: types.OrderTimeInForceGTC, 410 Type: types.OrderTypeLimit, 411 } 412 _, err = book.ob.SubmitOrder(&order) 413 assert.NoError(t, err) 414 415 // then stop the order 416 confirm, err := book.ob.CancelOrder(&order1) 417 assert.NoError(t, err) 418 assert.NoError(t, err) 419 assert.Equal(t, types.OrderStatusCancelled, confirm.Order.Status) 420 } 421 422 func testGTCStoppedPartiallyFilled(t *testing.T) { 423 market := "testMarket" 424 partyID1 := "p1" 425 partyID2 := "p2" 426 orderID := vgcrypto.RandomHash() 427 428 book := getTestOrderBook(t, market) 429 defer book.Finish() 430 431 // place a first order to sit in the book, be partially filled, and stopped 432 order1 := types.Order{ 433 Status: types.OrderStatusActive, 434 ID: orderID, 435 MarketID: market, 436 Party: partyID1, 437 Side: types.SideSell, 438 Price: num.NewUint(100), 439 OriginalPrice: num.NewUint(100), 440 Size: 10, 441 Remaining: 10, 442 TimeInForce: types.OrderTimeInForceGTC, 443 Type: types.OrderTypeLimit, 444 } 445 _, err := book.ob.SubmitOrder(&order1) 446 assert.NoError(t, err) 447 448 // now place our order which will consume some of the first order 449 order := types.Order{ 450 Status: types.OrderStatusActive, 451 MarketID: market, 452 Party: partyID2, 453 Side: types.SideBuy, 454 Price: num.NewUint(100), 455 OriginalPrice: num.NewUint(100), 456 Size: 1, 457 Remaining: 1, 458 TimeInForce: types.OrderTimeInForceGTC, 459 Type: types.OrderTypeLimit, 460 } 461 _, err = book.ob.SubmitOrder(&order) 462 assert.NoError(t, err) 463 464 // then stop the order 465 rmOrders, err := book.ob.RemoveDistressedOrders([]events.MarketPosition{marketPositionFake{partyID1}}) 466 assert.NoError(t, err) 467 assert.Len(t, rmOrders, 1) 468 assert.Equal(t, types.OrderStatusStopped, rmOrders[0].Status) 469 } 470 471 func testGTCFilled(t *testing.T) { 472 market := "testMarket" 473 partyID1 := "p1" 474 partyID2 := "p2" 475 476 book := getTestOrderBook(t, market) 477 defer book.Finish() 478 479 // place a first order to sit in the book 480 order1 := types.Order{ 481 ID: vgcrypto.RandomHash(), 482 Status: types.OrderStatusActive, 483 MarketID: market, 484 Party: partyID1, 485 Side: types.SideSell, 486 Price: num.NewUint(100), 487 OriginalPrice: num.NewUint(100), 488 Size: 1, 489 Remaining: 1, 490 TimeInForce: types.OrderTimeInForceGTC, 491 Type: types.OrderTypeLimit, 492 } 493 _, err := book.ob.SubmitOrder(&order1) 494 assert.NoError(t, err) 495 496 // now place our GTC order to be filled 497 order := types.Order{ 498 ID: vgcrypto.RandomHash(), 499 Status: types.OrderStatusActive, 500 MarketID: market, 501 Party: partyID2, 502 Side: types.SideBuy, 503 Price: num.NewUint(100), 504 OriginalPrice: num.NewUint(100), 505 Size: 1, 506 Remaining: 1, 507 TimeInForce: types.OrderTimeInForceGTC, 508 Type: types.OrderTypeLimit, 509 } 510 confirm, err := book.ob.SubmitOrder(&order) 511 assert.NoError(t, err) 512 assert.Equal(t, 1, len(confirm.Trades)) 513 assert.Equal(t, types.OrderStatusFilled, order.Status) 514 } 515 516 func testGTTActive(t *testing.T) { 517 market := "testMarket" 518 partyID1 := "p1" 519 orderID := vgcrypto.RandomHash() 520 521 book := getTestOrderBook(t, market) 522 defer book.Finish() 523 524 order1 := types.Order{ 525 Status: types.OrderStatusActive, 526 ID: orderID, 527 MarketID: market, 528 Party: partyID1, 529 Side: types.SideSell, 530 Price: num.NewUint(100), 531 OriginalPrice: num.NewUint(100), 532 Size: 10, 533 Remaining: 10, 534 TimeInForce: types.OrderTimeInForceGTT, 535 Type: types.OrderTypeLimit, 536 ExpiresAt: 10, 537 } 538 _, err := book.ob.SubmitOrder(&order1) 539 assert.NoError(t, err) 540 assert.Equal(t, types.OrderStatusActive, order1.Status) 541 } 542 543 func testGTTStoppedNotFilled(t *testing.T) { 544 market := "testMarket" 545 partyID1 := "p1" 546 orderID := vgcrypto.RandomHash() 547 548 book := getTestOrderBook(t, market) 549 defer book.Finish() 550 551 order1 := types.Order{ 552 Status: types.OrderStatusActive, 553 ID: orderID, 554 MarketID: market, 555 Party: partyID1, 556 Side: types.SideSell, 557 Price: num.NewUint(100), 558 OriginalPrice: num.NewUint(100), 559 Size: 10, 560 Remaining: 10, 561 TimeInForce: types.OrderTimeInForceGTT, 562 Type: types.OrderTypeLimit, 563 ExpiresAt: 10, 564 } 565 _, err := book.ob.SubmitOrder(&order1) 566 assert.NoError(t, err) 567 568 // then stop the order 569 rmOrders, err := book.ob.RemoveDistressedOrders([]events.MarketPosition{marketPositionFake{partyID1}}) 570 assert.NoError(t, err) 571 assert.Len(t, rmOrders, 1) 572 assert.Equal(t, types.OrderStatusStopped, rmOrders[0].Status) 573 } 574 575 func testGTTCancelledNotFilled(t *testing.T) { 576 market := "testMarket" 577 partyID1 := "p1" 578 orderID := vgcrypto.RandomHash() 579 580 book := getTestOrderBook(t, market) 581 defer book.Finish() 582 583 order1 := types.Order{ 584 Status: types.OrderStatusActive, 585 ID: orderID, 586 MarketID: market, 587 Party: partyID1, 588 Side: types.SideSell, 589 Price: num.NewUint(100), 590 OriginalPrice: num.NewUint(100), 591 Size: 10, 592 Remaining: 10, 593 TimeInForce: types.OrderTimeInForceGTT, 594 Type: types.OrderTypeLimit, 595 ExpiresAt: 10, 596 } 597 _, err := book.ob.SubmitOrder(&order1) 598 assert.NoError(t, err) 599 600 // then stop the order 601 confirm, err := book.ob.CancelOrder(&order1) 602 assert.NoError(t, err) 603 assert.Equal(t, types.OrderStatusCancelled, confirm.Order.Status) 604 } 605 606 func testGTTActivePartiallyFilled(t *testing.T) { 607 market := "testMarket" 608 partyID1 := "p1" 609 partyID2 := "p2" 610 orderID := vgcrypto.RandomHash() 611 612 book := getTestOrderBook(t, market) 613 defer book.Finish() 614 615 // place a first order to sit in the book, be partially filled 616 order1 := types.Order{ 617 Status: types.OrderStatusActive, 618 ID: orderID, 619 MarketID: market, 620 Party: partyID1, 621 Side: types.SideSell, 622 Price: num.NewUint(100), 623 OriginalPrice: num.NewUint(100), 624 Size: 10, 625 Remaining: 10, 626 TimeInForce: types.OrderTimeInForceGTT, 627 Type: types.OrderTypeLimit, 628 ExpiresAt: 10, 629 } 630 _, err := book.ob.SubmitOrder(&order1) 631 assert.NoError(t, err) 632 633 // now place our order which will consume some of the first order 634 order := types.Order{ 635 ID: vgcrypto.RandomHash(), 636 Status: types.OrderStatusActive, 637 MarketID: market, 638 Party: partyID2, 639 Side: types.SideBuy, 640 Price: num.NewUint(100), 641 OriginalPrice: num.NewUint(100), 642 Size: 1, 643 Remaining: 1, 644 TimeInForce: types.OrderTimeInForceGTT, 645 Type: types.OrderTypeLimit, 646 ExpiresAt: 10, 647 } 648 confirm, err := book.ob.SubmitOrder(&order) 649 assert.NoError(t, err) 650 assert.Len(t, confirm.PassiveOrdersAffected, 1) 651 assert.Equal(t, types.OrderStatusActive, confirm.PassiveOrdersAffected[0].Status) 652 } 653 654 func testGTTCancelledPartiallyFilled(t *testing.T) { 655 market := "testMarket" 656 partyID1 := "p1" 657 partyID2 := "p2" 658 orderID := vgcrypto.RandomHash() 659 660 book := getTestOrderBook(t, market) 661 defer book.Finish() 662 663 // place a first order to sit in the book, be partially filled, and cancelled 664 order1 := types.Order{ 665 Status: types.OrderStatusActive, 666 ID: orderID, 667 MarketID: market, 668 Party: partyID1, 669 Side: types.SideSell, 670 Price: num.NewUint(100), 671 OriginalPrice: num.NewUint(100), 672 Size: 10, 673 Remaining: 10, 674 TimeInForce: types.OrderTimeInForceGTT, 675 Type: types.OrderTypeLimit, 676 ExpiresAt: 10, 677 } 678 _, err := book.ob.SubmitOrder(&order1) 679 assert.NoError(t, err) 680 681 // now place our order which will consume some of the first order 682 order := types.Order{ 683 ID: vgcrypto.RandomHash(), 684 Status: types.OrderStatusActive, 685 MarketID: market, 686 Party: partyID2, 687 Side: types.SideBuy, 688 Price: num.NewUint(100), 689 OriginalPrice: num.NewUint(100), 690 Size: 1, 691 Remaining: 1, 692 TimeInForce: types.OrderTimeInForceGTT, 693 Type: types.OrderTypeLimit, 694 ExpiresAt: 10, 695 } 696 _, err = book.ob.SubmitOrder(&order) 697 assert.NoError(t, err) 698 699 // then stop the order 700 confirm, err := book.ob.CancelOrder(&order1) 701 assert.NoError(t, err) 702 assert.NoError(t, err) 703 assert.Equal(t, types.OrderStatusCancelled, confirm.Order.Status) 704 } 705 706 func testGTTStoppedPartiallyFilled(t *testing.T) { 707 market := "testMarket" 708 partyID1 := "p1" 709 partyID2 := "p2" 710 orderID := vgcrypto.RandomHash() 711 712 book := getTestOrderBook(t, market) 713 defer book.Finish() 714 715 // place a first order to sit in the book, be partially filled, and stopped 716 order1 := types.Order{ 717 Status: types.OrderStatusActive, 718 ID: orderID, 719 MarketID: market, 720 Party: partyID1, 721 Side: types.SideSell, 722 Price: num.NewUint(100), 723 OriginalPrice: num.NewUint(100), 724 Size: 10, 725 Remaining: 10, 726 TimeInForce: types.OrderTimeInForceGTT, 727 Type: types.OrderTypeLimit, 728 ExpiresAt: 10, 729 } 730 _, err := book.ob.SubmitOrder(&order1) 731 assert.NoError(t, err) 732 733 // now place our order which will consume some of the first order 734 order := types.Order{ 735 ID: vgcrypto.RandomHash(), 736 Status: types.OrderStatusActive, 737 MarketID: market, 738 Party: partyID2, 739 Side: types.SideBuy, 740 Price: num.NewUint(100), 741 OriginalPrice: num.NewUint(100), 742 Size: 1, 743 Remaining: 1, 744 TimeInForce: types.OrderTimeInForceGTT, 745 Type: types.OrderTypeLimit, 746 ExpiresAt: 10, 747 } 748 _, err = book.ob.SubmitOrder(&order) 749 assert.NoError(t, err) 750 751 // then stop the order 752 rmOrders, err := book.ob.RemoveDistressedOrders([]events.MarketPosition{marketPositionFake{partyID1}}) 753 assert.NoError(t, err) 754 assert.Len(t, rmOrders, 1) 755 assert.Equal(t, types.OrderStatusStopped, rmOrders[0].Status) 756 } 757 758 func testGTTFilled(t *testing.T) { 759 market := "testMarket" 760 partyID1 := "p1" 761 partyID2 := "p2" 762 763 book := getTestOrderBook(t, market) 764 defer book.Finish() 765 766 // place a first order to sit in the book 767 order1 := types.Order{ 768 ID: vgcrypto.RandomHash(), 769 Status: types.OrderStatusActive, 770 MarketID: market, 771 Party: partyID1, 772 Side: types.SideSell, 773 Price: num.NewUint(100), 774 OriginalPrice: num.NewUint(100), 775 Size: 1, 776 Remaining: 1, 777 TimeInForce: types.OrderTimeInForceGTT, 778 Type: types.OrderTypeLimit, 779 ExpiresAt: 10, 780 } 781 _, err := book.ob.SubmitOrder(&order1) 782 assert.NoError(t, err) 783 784 // now place our GTT order to be filled 785 order := types.Order{ 786 ID: vgcrypto.RandomHash(), 787 Status: types.OrderStatusActive, 788 MarketID: market, 789 Party: partyID2, 790 Side: types.SideBuy, 791 Price: num.NewUint(100), 792 OriginalPrice: num.NewUint(100), 793 Size: 1, 794 Remaining: 1, 795 TimeInForce: types.OrderTimeInForceGTT, 796 Type: types.OrderTypeLimit, 797 ExpiresAt: 10, 798 } 799 confirm, err := book.ob.SubmitOrder(&order) 800 assert.NoError(t, err) 801 assert.Equal(t, 1, len(confirm.Trades)) 802 assert.Equal(t, types.OrderStatusFilled, order.Status) 803 } 804 805 type marketPositionFake struct { 806 party string 807 } 808 809 func (m marketPositionFake) AverageEntryPrice() *num.Uint { return num.UintZero() } 810 func (m marketPositionFake) Party() string { return m.party } 811 func (m marketPositionFake) Size() int64 { return 0 } 812 func (m marketPositionFake) Buy() int64 { return 0 } 813 func (m marketPositionFake) Sell() int64 { return 0 } 814 func (m marketPositionFake) Price() *num.Uint { return num.UintZero() } 815 func (m marketPositionFake) BuySumProduct() *num.Uint { return num.UintZero() } 816 func (m marketPositionFake) SellSumProduct() *num.Uint { return num.UintZero() } 817 func (m marketPositionFake) VWBuy() *num.Uint { return num.UintZero() } 818 func (m marketPositionFake) VWSell() *num.Uint { return num.UintZero() }