code.vegaprotocol.io/vega@v0.79.0/core/types/matching.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 types 17 18 import ( 19 "errors" 20 "fmt" 21 "time" 22 23 "code.vegaprotocol.io/vega/libs/num" 24 "code.vegaprotocol.io/vega/libs/ptr" 25 "code.vegaprotocol.io/vega/libs/stringer" 26 proto "code.vegaprotocol.io/vega/protos/vega" 27 ) 28 29 type Order struct { 30 ID string 31 MarketID string 32 Party string 33 Side Side 34 Price *num.Uint 35 OriginalPrice *num.Uint 36 Size uint64 37 Remaining uint64 38 TimeInForce OrderTimeInForce 39 Type OrderType 40 CreatedAt int64 41 Status OrderStatus 42 ExpiresAt int64 43 Reference string 44 Reason OrderError 45 UpdatedAt int64 46 Version uint64 47 BatchID uint64 48 PeggedOrder *PeggedOrder 49 PostOnly bool 50 ReduceOnly bool 51 extraRemaining uint64 52 IcebergOrder *IcebergOrder 53 GeneratedOffbook bool 54 } 55 56 func (o *Order) ReduceOnlyAdjustRemaining(extraSize uint64) { 57 if !o.ReduceOnly { 58 panic("order.ReduceOnlyAdjustSize shall be call only on reduce-only orders") 59 } 60 61 o.extraRemaining = extraSize 62 o.Remaining -= extraSize 63 } 64 65 func (o *Order) ClearUpExtraRemaining() { 66 // ignore for non reduce only 67 if !o.ReduceOnly { 68 return 69 } 70 71 o.Remaining += o.extraRemaining 72 o.extraRemaining = 0 73 } 74 75 // TrueRemaining is the full remaining size of an order. If this is an iceberg order 76 // it will return the visible peak + the hidden volume. 77 func (o *Order) TrueRemaining() uint64 { 78 rem := o.Remaining 79 if o.IcebergOrder != nil { 80 rem += o.IcebergOrder.ReservedRemaining 81 } 82 return rem 83 } 84 85 // IcebergNeedsRefresh returns whether the given iceberg order's visible peak has 86 // dropped below the minimum visible size, and there is hidden volume available to 87 // restore it. 88 func (o *Order) IcebergNeedsRefresh() bool { 89 if o.IcebergOrder == nil { 90 // not an iceberg 91 return false 92 } 93 94 if o.IcebergOrder.ReservedRemaining == 0 { 95 // nothing to refresh with 96 return false 97 } 98 99 if o.Remaining >= o.IcebergOrder.MinimumVisibleSize { 100 // not under the minimum 101 return false 102 } 103 104 return true 105 } 106 107 // SetIcebergPeaks will restore the given iceberg orders visible size with 108 // some of its hidden volume. 109 func (o *Order) SetIcebergPeaks() { 110 if o.IcebergOrder == nil { 111 return 112 } 113 114 if o.Remaining > o.IcebergOrder.PeakSize && o.IcebergOrder.ReservedRemaining == 0 { 115 // iceberg is at full volume and so set its visible amount to its peak size 116 peak := num.MinV(o.Remaining, o.IcebergOrder.PeakSize) 117 o.IcebergOrder.ReservedRemaining = o.Remaining - peak 118 o.Remaining = peak 119 return 120 } 121 122 // calculate the refill amount 123 refill := o.IcebergOrder.PeakSize - o.Remaining 124 refill = num.MinV(refill, o.IcebergOrder.ReservedRemaining) 125 126 o.Remaining += refill 127 o.IcebergOrder.ReservedRemaining -= refill 128 } 129 130 func (o Order) IntoSubmission() *OrderSubmission { 131 sub := &OrderSubmission{ 132 MarketID: o.MarketID, 133 Size: o.Size, 134 Side: o.Side, 135 TimeInForce: o.TimeInForce, 136 ExpiresAt: o.ExpiresAt, 137 Type: o.Type, 138 Reference: o.Reference, 139 PostOnly: o.PostOnly, 140 ReduceOnly: o.ReduceOnly, 141 } 142 if o.IcebergOrder != nil { 143 sub.IcebergOrder = &IcebergOrder{ 144 PeakSize: o.IcebergOrder.PeakSize, 145 MinimumVisibleSize: o.IcebergOrder.MinimumVisibleSize, 146 } 147 } 148 if o.Price != nil { 149 sub.Price = o.Price.Clone() 150 } 151 if o.PeggedOrder != nil { 152 sub.PeggedOrder = o.PeggedOrder.Clone() 153 } 154 155 return sub 156 } 157 158 func (o Order) Clone() *Order { 159 cpy := o 160 if o.Price != nil { 161 cpy.Price = o.Price.Clone() 162 } else { 163 cpy.Price = num.UintZero() 164 } 165 // this isn't really needed, to original order is about to be replaced, or the original price is getting reassinged 166 // but in case something goes wrong, we don't want a pointer to this field in 2 places 167 if o.OriginalPrice != nil { 168 cpy.OriginalPrice = o.OriginalPrice.Clone() 169 } 170 if o.PeggedOrder != nil { 171 cpy.PeggedOrder = o.PeggedOrder.Clone() 172 } 173 if o.IcebergOrder != nil { 174 cpy.IcebergOrder = o.IcebergOrder.Clone() 175 } 176 return &cpy 177 } 178 179 func (o Order) String() string { 180 return fmt.Sprintf( 181 "ID(%s) marketID(%s) party(%s) side(%s) price(%s) size(%v) remaining(%v) timeInForce(%s) type(%s) status(%s) reference(%s) reason(%s) version(%v) batchID(%v) createdAt(%v) updatedAt(%v) expiresAt(%v) originalPrice(%s) peggedOrder(%s) postOnly(%v) reduceOnly(%v) iceberg(%s)", 182 o.ID, 183 o.MarketID, 184 o.Party, 185 o.Side.String(), 186 num.UintToString(o.Price), 187 o.Size, 188 o.Remaining, 189 o.TimeInForce.String(), 190 o.Type.String(), 191 o.Status.String(), 192 o.Reference, 193 o.Reason.String(), 194 o.Version, 195 o.BatchID, 196 o.CreatedAt, 197 o.UpdatedAt, 198 o.ExpiresAt, 199 stringer.PtrToString(o.OriginalPrice), 200 stringer.PtrToString(o.PeggedOrder), 201 o.PostOnly, 202 o.ReduceOnly, 203 stringer.PtrToString(o.IcebergOrder), 204 ) 205 } 206 207 type Orders []*Order 208 209 func (o Orders) IntoProto() []*proto.Order { 210 out := make([]*proto.Order, 0, len(o)) 211 for _, v := range o { 212 out = append(out, v.IntoProto()) 213 } 214 return out 215 } 216 217 func (o *Order) IntoProto() *proto.Order { 218 var pegged *proto.PeggedOrder 219 if o.PeggedOrder != nil { 220 pegged = o.PeggedOrder.IntoProto() 221 } 222 var reason *OrderError 223 if o.Reason != OrderErrorUnspecified { 224 reason = ptr.From(o.Reason) 225 } 226 227 var iceberg *proto.IcebergOrder 228 if o.IcebergOrder != nil { 229 iceberg = o.IcebergOrder.IntoProto() 230 } 231 232 return &proto.Order{ 233 Id: o.ID, 234 MarketId: o.MarketID, 235 PartyId: o.Party, 236 Side: o.Side, 237 Price: num.UintToString(o.Price), 238 Size: o.Size, 239 Remaining: o.Remaining, 240 TimeInForce: o.TimeInForce, 241 Type: o.Type, 242 CreatedAt: o.CreatedAt, 243 Status: o.Status, 244 ExpiresAt: o.ExpiresAt, 245 Reference: o.Reference, 246 Reason: reason, 247 UpdatedAt: o.UpdatedAt, 248 Version: o.Version, 249 BatchId: o.BatchID, 250 PeggedOrder: pegged, 251 PostOnly: o.PostOnly, 252 ReduceOnly: o.ReduceOnly, 253 IcebergOrder: iceberg, 254 } 255 } 256 257 func OrderFromProto(o *proto.Order) (*Order, error) { 258 var iceberg *IcebergOrder 259 if o.IcebergOrder != nil { 260 var err error 261 iceberg, err = NewIcebergOrderFromProto(o.IcebergOrder) 262 if err != nil { 263 return nil, err 264 } 265 } 266 var pegged *PeggedOrder 267 if o.PeggedOrder != nil { 268 var err error 269 pegged, err = NewPeggedOrderFromProto(o.PeggedOrder) 270 if err != nil { 271 return nil, err 272 } 273 } 274 price := num.UintZero() 275 if len(o.Price) > 0 { 276 var overflowed bool 277 price, overflowed = num.UintFromString(o.Price, 10) 278 if overflowed { 279 return nil, errors.New("invalid price") 280 } 281 } 282 reason := OrderErrorUnspecified 283 if o.Reason != nil { 284 reason = *o.Reason 285 } 286 return &Order{ 287 ID: o.Id, 288 MarketID: o.MarketId, 289 Party: o.PartyId, 290 Side: o.Side, 291 Price: price, 292 Size: o.Size, 293 Remaining: o.Remaining, 294 TimeInForce: o.TimeInForce, 295 Type: o.Type, 296 CreatedAt: o.CreatedAt, 297 Status: o.Status, 298 ExpiresAt: o.ExpiresAt, 299 Reference: o.Reference, 300 Reason: reason, 301 UpdatedAt: o.UpdatedAt, 302 Version: o.Version, 303 BatchID: o.BatchId, 304 PeggedOrder: pegged, 305 PostOnly: o.PostOnly, 306 ReduceOnly: o.ReduceOnly, 307 IcebergOrder: iceberg, 308 }, nil 309 } 310 311 // Create sets the creation time (CreatedAt) to t and returns the 312 // updated order. 313 func (o *Order) Create(t int64) *Order { 314 o.CreatedAt = t 315 return o 316 } 317 318 // Update sets the modification time (UpdatedAt) to t and returns the 319 // updated order. 320 func (o *Order) Update(t time.Time) *Order { 321 o.UpdatedAt = t.UnixNano() 322 return o 323 } 324 325 // IsPersistent returns true if the order is persistent. 326 // A persistent order is a Limit type order that might be 327 // matched in the future. 328 func (o *Order) IsPersistent() bool { 329 return (o.TimeInForce == OrderTimeInForceGTC || 330 o.TimeInForce == OrderTimeInForceGTT || 331 o.TimeInForce == OrderTimeInForceGFN || 332 o.TimeInForce == OrderTimeInForceGFA) && 333 o.Type == OrderTypeLimit && 334 o.Remaining > 0 335 } 336 337 func (o *Order) IsExpireable() bool { 338 return (o.TimeInForce == OrderTimeInForceGFN || 339 o.TimeInForce == OrderTimeInForceGTT || 340 o.TimeInForce == OrderTimeInForceGFA) && 341 o.ExpiresAt > 0 342 } 343 344 // IsFinished returns true if an order 345 // is in any state different to ACTIVE and PARKED 346 // Basically any order which is never gonna 347 // trade anymore. 348 func (o *Order) IsFinished() bool { 349 return o.Status != OrderStatusActive && o.Status != OrderStatusParked 350 } 351 352 func (o *Order) HasTraded() bool { 353 return o.Size != o.Remaining 354 } 355 356 func (o *Order) applyOrderAmendmentSizeIceberg(delta int64) { 357 // handle increase in size 358 if delta > 0 { 359 o.Size += uint64(delta) 360 o.IcebergOrder.ReservedRemaining += uint64(delta) 361 return 362 } 363 364 // handle decrease in size 365 dec := uint64(-delta) 366 o.Size -= dec 367 368 if o.IcebergOrder.ReservedRemaining >= dec { 369 o.IcebergOrder.ReservedRemaining -= dec 370 return 371 } 372 373 diff := dec - o.IcebergOrder.ReservedRemaining 374 if o.Remaining > diff { 375 o.Remaining -= dec - o.IcebergOrder.ReservedRemaining 376 } else { 377 o.Remaining = 0 378 } 379 o.IcebergOrder.ReservedRemaining = 0 380 } 381 382 func (o *Order) amendSize(size uint64) { 383 o.amendSizeWithDelta(int64(size) - int64(o.Size)) 384 } 385 386 // amendSizeWithDelta update the orders size/remaining fields based on the size 387 // an direction of the given delta. 388 func (o *Order) amendSizeWithDelta(delta int64) { 389 if o.IcebergOrder != nil { 390 o.applyOrderAmendmentSizeIceberg(delta) 391 return 392 } 393 394 // handle size increase 395 if delta > 0 { 396 o.Size += uint64(delta) 397 o.Remaining += uint64(delta) 398 return 399 } 400 401 // handle size decrease 402 dec := uint64(-delta) 403 o.Size -= dec 404 if o.Remaining > dec { 405 o.Remaining -= dec 406 } else { 407 o.Remaining = 0 408 } 409 } 410 411 // ApplyOrderAmendment assumes the amendment have been validated before. 412 func (o *Order) ApplyOrderAmendment(amendment *OrderAmendment, updatedAtNano int64, priceFactor num.Decimal) (order *Order, err error) { 413 order = o.Clone() 414 order.UpdatedAt = updatedAtNano 415 order.Version++ 416 417 if o.PeggedOrder != nil { 418 order.PeggedOrder = &PeggedOrder{ 419 Reference: o.PeggedOrder.Reference, 420 Offset: o.PeggedOrder.Offset, 421 } 422 } 423 424 var amendPrice *num.Uint 425 if amendment.Price != nil { 426 amendPrice, _ = num.UintFromDecimal(amendment.Price.ToDecimal().Mul(priceFactor)) 427 } 428 // apply price changes 429 if amendment.Price != nil && o.Price.NEQ(amendPrice) { 430 order.Price = amendPrice.Clone() 431 order.OriginalPrice = amendment.Price.Clone() 432 } 433 434 if amendment.Size != nil { 435 order.amendSize(*amendment.Size) 436 } 437 438 if delta := amendment.SizeDelta; delta != 0 { 439 order.amendSizeWithDelta(delta) 440 } 441 442 // apply tif 443 if amendment.TimeInForce != OrderTimeInForceUnspecified { 444 order.TimeInForce = amendment.TimeInForce 445 if amendment.TimeInForce != OrderTimeInForceGTT { 446 order.ExpiresAt = 0 447 } 448 } 449 if amendment.ExpiresAt != nil { 450 order.ExpiresAt = *amendment.ExpiresAt 451 } 452 453 // apply pegged order values 454 if order.PeggedOrder != nil { 455 if amendment.PeggedOffset != nil { 456 order.PeggedOrder.Offset = amendment.PeggedOffset.Clone() 457 } 458 459 if amendment.PeggedReference != PeggedReferenceUnspecified { 460 order.PeggedOrder.Reference = amendment.PeggedReference 461 } 462 if verr := order.ValidatePeggedOrder(); verr != OrderErrorUnspecified { 463 err = verr 464 } 465 } 466 467 return order, err 468 } 469 470 func (order *Order) ValidatePeggedOrder() OrderError { 471 if order.Type != OrderTypeLimit { 472 // All pegged orders must be LIMIT orders 473 return ErrPeggedOrderMustBeLimitOrder 474 } 475 476 if order.TimeInForce != OrderTimeInForceGTT && order.TimeInForce != OrderTimeInForceGTC && order.TimeInForce != OrderTimeInForceGFN { 477 // Pegged orders can only be GTC or GTT 478 return ErrPeggedOrderMustBeGTTOrGTC 479 } 480 481 if order.PeggedOrder.Reference == PeggedReferenceUnspecified { 482 // We must specify a valid reference 483 return ErrPeggedOrderWithoutReferencePrice 484 } 485 486 if order.Side == SideBuy { 487 switch order.PeggedOrder.Reference { 488 case PeggedReferenceBestAsk: 489 return ErrPeggedOrderBuyCannotReferenceBestAskPrice 490 case PeggedReferenceMid: 491 if order.PeggedOrder.Offset.IsZero() { 492 return ErrPeggedOrderOffsetMustBeGreaterThanZero 493 } 494 } 495 } else { 496 switch order.PeggedOrder.Reference { 497 case PeggedReferenceBestBid: 498 return ErrPeggedOrderSellCannotReferenceBestBidPrice 499 case PeggedReferenceMid: 500 if order.PeggedOrder.Offset.IsZero() { 501 return ErrPeggedOrderOffsetMustBeGreaterThanZero 502 } 503 } 504 } 505 return OrderErrorUnspecified 506 } 507 508 type PeggedOrder struct { 509 Reference PeggedReference 510 Offset *num.Uint 511 } 512 513 func (p PeggedOrder) Clone() *PeggedOrder { 514 cpy := p 515 return &cpy 516 } 517 518 func NewPeggedOrderFromProto(p *proto.PeggedOrder) (*PeggedOrder, error) { 519 if p == nil { 520 return nil, nil 521 } 522 523 offset, overflowed := num.UintFromString(p.Offset, 10) 524 if overflowed { 525 return nil, errors.New("invalid offset") 526 } 527 528 return &PeggedOrder{ 529 Reference: p.Reference, 530 Offset: offset, 531 }, nil 532 } 533 534 func (p PeggedOrder) IntoProto() *proto.PeggedOrder { 535 return &proto.PeggedOrder{ 536 Reference: p.Reference, 537 Offset: p.Offset.String(), 538 } 539 } 540 541 func (p PeggedOrder) String() string { 542 return fmt.Sprintf( 543 "reference(%s) offset(%s)", 544 p.Reference.String(), 545 stringer.PtrToString(p.Offset), 546 ) 547 } 548 549 type IcebergOrder struct { 550 ReservedRemaining uint64 551 PeakSize uint64 552 MinimumVisibleSize uint64 553 } 554 555 func (i IcebergOrder) Clone() *IcebergOrder { 556 cpy := i 557 return &cpy 558 } 559 560 func NewIcebergOrderFromProto(i *proto.IcebergOrder) (*IcebergOrder, error) { 561 if i == nil { 562 return nil, nil 563 } 564 return &IcebergOrder{ 565 ReservedRemaining: i.ReservedRemaining, 566 PeakSize: i.PeakSize, 567 MinimumVisibleSize: i.MinimumVisibleSize, 568 }, nil 569 } 570 571 func (i IcebergOrder) IntoProto() *proto.IcebergOrder { 572 return &proto.IcebergOrder{ 573 ReservedRemaining: i.ReservedRemaining, 574 PeakSize: i.PeakSize, 575 MinimumVisibleSize: i.MinimumVisibleSize, 576 } 577 } 578 579 func (i IcebergOrder) String() string { 580 return fmt.Sprintf( 581 "reserved-remaining(%d) initial-peak-size(%d) minimum-peak-size(%d)", 582 i.ReservedRemaining, 583 i.PeakSize, 584 i.MinimumVisibleSize, 585 ) 586 } 587 588 type OrderConfirmation struct { 589 Order *Order 590 Trades []*Trade 591 PassiveOrdersAffected []*Order 592 } 593 594 func (o *OrderConfirmation) IntoProto() *proto.OrderConfirmation { 595 return &proto.OrderConfirmation{ 596 Order: o.Order.IntoProto(), 597 Trades: Trades(o.Trades).IntoProto(), 598 PassiveOrdersAffected: Orders(o.PassiveOrdersAffected).IntoProto(), 599 } 600 } 601 602 func (o OrderConfirmation) TradedValue() *num.Uint { 603 total := num.UintZero() 604 for _, t := range o.Trades { 605 size := num.NewUint(t.Size) 606 total.AddSum(size.Mul(size, t.Price)) 607 } 608 return total 609 } 610 611 type OrderCancellationConfirmation struct { 612 Order *Order 613 } 614 615 func (o *OrderCancellationConfirmation) IntoProto() *proto.OrderCancellationConfirmation { 616 return &proto.OrderCancellationConfirmation{ 617 Order: o.Order.IntoProto(), 618 } 619 } 620 621 type Trade struct { 622 ID string 623 MarketID string 624 Price *num.Uint 625 MarketPrice *num.Uint 626 Size uint64 627 Buyer string 628 Seller string 629 Aggressor Side 630 BuyOrder string 631 SellOrder string 632 Timestamp int64 633 Type TradeType 634 BuyerFee *Fee 635 SellerFee *Fee 636 BuyerAuctionBatch uint64 637 SellerAuctionBatch uint64 638 } 639 640 func (t *Trade) SetIDs(tradeID string, aggressive, passive *Order) { 641 t.ID = tradeID 642 if aggressive.Side == SideBuy { 643 t.BuyOrder = aggressive.ID 644 t.SellOrder = passive.ID 645 return 646 } 647 t.SellOrder = aggressive.ID 648 t.BuyOrder = passive.ID 649 } 650 651 func (t *Trade) IntoProto() *proto.Trade { 652 var buyerFee, sellerFee *proto.Fee 653 if t.BuyerFee != nil { 654 buyerFee = t.BuyerFee.IntoProto() 655 } 656 if t.SellerFee != nil { 657 sellerFee = t.SellerFee.IntoProto() 658 } 659 return &proto.Trade{ 660 Id: t.ID, 661 MarketId: t.MarketID, 662 Price: num.UintToString(t.Price), 663 Size: t.Size, 664 Buyer: t.Buyer, 665 Seller: t.Seller, 666 Aggressor: t.Aggressor, 667 BuyOrder: t.BuyOrder, 668 SellOrder: t.SellOrder, 669 Timestamp: t.Timestamp, 670 Type: t.Type, 671 BuyerFee: buyerFee, 672 SellerFee: sellerFee, 673 BuyerAuctionBatch: t.BuyerAuctionBatch, 674 SellerAuctionBatch: t.SellerAuctionBatch, 675 } 676 } 677 678 func TradeFromProto(t *proto.Trade) *Trade { 679 if t == nil { 680 return nil 681 } 682 683 return &Trade{ 684 ID: t.Id, 685 MarketID: t.MarketId, 686 Price: num.MustUintFromString(t.Price, 10), 687 Size: t.Size, 688 Buyer: t.Buyer, 689 Seller: t.Seller, 690 Aggressor: t.Aggressor, 691 BuyOrder: t.BuyOrder, 692 SellOrder: t.SellOrder, 693 Timestamp: t.Timestamp, 694 Type: t.Type, 695 BuyerFee: FeeFromProto(t.BuyerFee), 696 SellerFee: FeeFromProto(t.SellerFee), 697 BuyerAuctionBatch: t.BuyerAuctionBatch, 698 SellerAuctionBatch: t.SellerAuctionBatch, 699 } 700 } 701 702 func (t Trade) String() string { 703 return fmt.Sprintf( 704 "ID(%s) marketID(%s) price(%s) marketPrice(%s) size(%v) buyer(%s) seller(%s) aggressor(%s) buyOrder(%s) sellOrder(%s) timestamp(%v) type(%s) buyerAuctionBatch(%v) sellerAuctionBatch(%v) buyerFee(%s) sellerFee(%s)", 705 t.ID, 706 t.MarketID, 707 stringer.PtrToString(t.Price), 708 stringer.PtrToString(t.MarketPrice), 709 t.Size, 710 t.Buyer, 711 t.Seller, 712 t.Aggressor.String(), 713 t.BuyOrder, 714 t.SellOrder, 715 t.Timestamp, 716 t.Type.String(), 717 t.BuyerAuctionBatch, 718 t.SellerAuctionBatch, 719 stringer.PtrToString(t.SellerFee), 720 stringer.PtrToString(t.BuyerFee), 721 ) 722 } 723 724 type Trades []*Trade 725 726 func (t Trades) IntoProto() []*proto.Trade { 727 out := make([]*proto.Trade, 0, len(t)) 728 for _, v := range t { 729 out = append(out, v.IntoProto()) 730 } 731 return out 732 } 733 734 type TradeType = proto.Trade_Type 735 736 const ( 737 // Default value, always invalid. 738 TradeTypeUnspecified TradeType = proto.Trade_TYPE_UNSPECIFIED 739 // Normal trading between two parties. 740 TradeTypeDefault TradeType = proto.Trade_TYPE_DEFAULT 741 // Trading initiated by the network with another party on the book, 742 // which helps to zero-out the positions of one or more distressed parties. 743 TradeTypeNetworkCloseOutGood TradeType = proto.Trade_TYPE_NETWORK_CLOSE_OUT_GOOD 744 // Trading initiated by the network with another party off the book, 745 // with a distressed party in order to zero-out the position of the party. 746 TradeTypeNetworkCloseOutBad TradeType = proto.Trade_TYPE_NETWORK_CLOSE_OUT_BAD 747 ) 748 749 type PeggedReference = proto.PeggedReference 750 751 const ( 752 // Default value for PeggedReference, no reference given. 753 PeggedReferenceUnspecified PeggedReference = proto.PeggedReference_PEGGED_REFERENCE_UNSPECIFIED 754 // Mid price reference. 755 PeggedReferenceMid PeggedReference = proto.PeggedReference_PEGGED_REFERENCE_MID 756 // Best bid price reference. 757 PeggedReferenceBestBid PeggedReference = proto.PeggedReference_PEGGED_REFERENCE_BEST_BID 758 // Best ask price reference. 759 PeggedReferenceBestAsk PeggedReference = proto.PeggedReference_PEGGED_REFERENCE_BEST_ASK 760 ) 761 762 type OrderStatus = proto.Order_Status 763 764 const ( 765 // Default value, always invalid. 766 OrderStatusUnspecified OrderStatus = proto.Order_STATUS_UNSPECIFIED 767 // Used for active unfilled or partially filled orders. 768 OrderStatusActive OrderStatus = proto.Order_STATUS_ACTIVE 769 // Used for expired GTT orders. 770 OrderStatusExpired OrderStatus = proto.Order_STATUS_EXPIRED 771 // Used for orders cancelled by the party that created the order. 772 OrderStatusCancelled OrderStatus = proto.Order_STATUS_CANCELLED 773 // Used for unfilled FOK or IOC orders, and for orders that were stopped by the network. 774 OrderStatusStopped OrderStatus = proto.Order_STATUS_STOPPED 775 // Used for closed fully filled orders. 776 OrderStatusFilled OrderStatus = proto.Order_STATUS_FILLED 777 // Used for orders when not enough collateral was available to fill the margin requirements. 778 OrderStatusRejected OrderStatus = proto.Order_STATUS_REJECTED 779 // Used for closed partially filled IOC orders. 780 OrderStatusPartiallyFilled OrderStatus = proto.Order_STATUS_PARTIALLY_FILLED 781 // Order has been removed from the order book and has been parked, this applies to pegged orders only. 782 OrderStatusParked OrderStatus = proto.Order_STATUS_PARKED 783 ) 784 785 type Side = proto.Side 786 787 const ( 788 // Default value, always invalid. 789 SideUnspecified Side = proto.Side_SIDE_UNSPECIFIED 790 // Buy order. 791 SideBuy Side = proto.Side_SIDE_BUY 792 // Sell order. 793 SideSell Side = proto.Side_SIDE_SELL 794 ) 795 796 type OrderType = proto.Order_Type 797 798 const ( 799 // Default value, always invalid. 800 OrderTypeUnspecified OrderType = proto.Order_TYPE_UNSPECIFIED 801 // Used for Limit orders. 802 OrderTypeLimit OrderType = proto.Order_TYPE_LIMIT 803 // Used for Market orders. 804 OrderTypeMarket OrderType = proto.Order_TYPE_MARKET 805 // Used for orders where the initiating party is the network (with distressed traders). 806 OrderTypeNetwork OrderType = proto.Order_TYPE_NETWORK 807 ) 808 809 type OrderTimeInForce = proto.Order_TimeInForce 810 811 const ( 812 // Default value for TimeInForce, can be valid for an amend. 813 OrderTimeInForceUnspecified OrderTimeInForce = proto.Order_TIME_IN_FORCE_UNSPECIFIED 814 // Good until cancelled. 815 OrderTimeInForceGTC OrderTimeInForce = proto.Order_TIME_IN_FORCE_GTC 816 // Good until specified time. 817 OrderTimeInForceGTT OrderTimeInForce = proto.Order_TIME_IN_FORCE_GTT 818 // Immediate or cancel. 819 OrderTimeInForceIOC OrderTimeInForce = proto.Order_TIME_IN_FORCE_IOC 820 // Fill or kill. 821 OrderTimeInForceFOK OrderTimeInForce = proto.Order_TIME_IN_FORCE_FOK 822 // Good for auction. 823 OrderTimeInForceGFA OrderTimeInForce = proto.Order_TIME_IN_FORCE_GFA 824 // Good for normal. 825 OrderTimeInForceGFN OrderTimeInForce = proto.Order_TIME_IN_FORCE_GFN 826 ) 827 828 type OrderError = proto.OrderError 829 830 const ( 831 // Default value, no error reported. 832 OrderErrorUnspecified OrderError = proto.OrderError_ORDER_ERROR_UNSPECIFIED 833 // Order was submitted for a market that does not exist. 834 OrderErrorInvalidMarketID OrderError = proto.OrderError_ORDER_ERROR_INVALID_MARKET_ID 835 // Order was submitted with an invalid identifier. 836 OrderErrorInvalidOrderID OrderError = proto.OrderError_ORDER_ERROR_INVALID_ORDER_ID 837 // Order was amended with a sequence number that was not previous version + 1. 838 OrderErrorOutOfSequence OrderError = proto.OrderError_ORDER_ERROR_OUT_OF_SEQUENCE 839 // Order was amended with an invalid remaining size (e.g. remaining greater than total size). 840 OrderErrorInvalidRemainingSize OrderError = proto.OrderError_ORDER_ERROR_INVALID_REMAINING_SIZE 841 // Node was unable to get Vega (blockchain) time. 842 OrderErrorTimeFailure OrderError = proto.OrderError_ORDER_ERROR_TIME_FAILURE 843 // Failed to remove an order from the book. 844 OrderErrorRemovalFailure OrderError = proto.OrderError_ORDER_ERROR_REMOVAL_FAILURE 845 // An order with `TimeInForce.TIME_IN_FORCE_GTT` was submitted or amended 846 // with an expiration that was badly formatted or otherwise invalid. 847 OrderErrorInvalidExpirationDatetime OrderError = proto.OrderError_ORDER_ERROR_INVALID_EXPIRATION_DATETIME 848 // Order was submitted or amended with an invalid reference field. 849 OrderErrorInvalidOrderReference OrderError = proto.OrderError_ORDER_ERROR_INVALID_ORDER_REFERENCE 850 // Order amend was submitted for an order field that cannot not be amended (e.g. order identifier). 851 OrderErrorEditNotAllowed OrderError = proto.OrderError_ORDER_ERROR_EDIT_NOT_ALLOWED 852 // Amend failure because amend details do not match original order. 853 OrderErrorAmendFailure OrderError = proto.OrderError_ORDER_ERROR_AMEND_FAILURE 854 // Order not found in an order book or store. 855 OrderErrorNotFound OrderError = proto.OrderError_ORDER_ERROR_NOT_FOUND 856 // Order was submitted with an invalid or missing party identifier. 857 OrderErrorInvalidParty OrderError = proto.OrderError_ORDER_ERROR_INVALID_PARTY_ID 858 // Order was submitted for a market that has closed. 859 OrderErrorMarketClosed OrderError = proto.OrderError_ORDER_ERROR_MARKET_CLOSED 860 // Order was submitted, but the party did not have enough collateral to cover the order. 861 OrderErrorMarginCheckFailed OrderError = proto.OrderError_ORDER_ERROR_MARGIN_CHECK_FAILED 862 // Order was submitted, but the party did not have an account for this asset. 863 OrderErrorMissingGeneralAccount OrderError = proto.OrderError_ORDER_ERROR_MISSING_GENERAL_ACCOUNT 864 // Unspecified internal error. 865 OrderErrorInternalError OrderError = proto.OrderError_ORDER_ERROR_INTERNAL_ERROR 866 // Order was submitted with an invalid or missing size (e.g. 0). 867 OrderErrorInvalidSize OrderError = proto.OrderError_ORDER_ERROR_INVALID_SIZE 868 // Order was submitted with an invalid persistence for its type. 869 OrderErrorInvalidPersistance OrderError = proto.OrderError_ORDER_ERROR_INVALID_PERSISTENCE 870 // Order was submitted with an invalid type field. 871 OrderErrorInvalidType OrderError = proto.OrderError_ORDER_ERROR_INVALID_TYPE 872 // Order was stopped as it would have traded with another order submitted from the same party. 873 OrderErrorSelfTrading OrderError = proto.OrderError_ORDER_ERROR_SELF_TRADING 874 // Order was submitted, but the party did not have enough collateral to cover the fees for the order. 875 OrderErrorInsufficientFundsToPayFees OrderError = proto.OrderError_ORDER_ERROR_INSUFFICIENT_FUNDS_TO_PAY_FEES 876 // Order was submitted with an incorrect or invalid market type. 877 OrderErrorIncorrectMarketType OrderError = proto.OrderError_ORDER_ERROR_INCORRECT_MARKET_TYPE 878 // Order was submitted with invalid time in force. 879 OrderErrorInvalidTimeInForce OrderError = proto.OrderError_ORDER_ERROR_INVALID_TIME_IN_FORCE 880 // A GFN order has got to the market when it is in auction mode. 881 OrderErrorCannotSendGFNOrderDuringAnAuction OrderError = proto.OrderError_ORDER_ERROR_CANNOT_SEND_GFN_ORDER_DURING_AN_AUCTION 882 // A GFA order has got to the market when it is in continuous trading mode. 883 OrderErrorGFAOrderDuringContinuousTrading OrderError = proto.OrderError_ORDER_ERROR_CANNOT_SEND_GFA_ORDER_DURING_CONTINUOUS_TRADING 884 // Attempt to amend order to GTT without ExpiryAt. 885 OrderErrorCannotAmendToGTTWithoutExpiryAt OrderError = proto.OrderError_ORDER_ERROR_CANNOT_AMEND_TO_GTT_WITHOUT_EXPIRYAT 886 // Attempt to amend ExpiryAt to a value before CreatedAt. 887 OrderErrorExpiryAtBeforeCreatedAt OrderError = proto.OrderError_ORDER_ERROR_EXPIRYAT_BEFORE_CREATEDAT 888 // Attempt to amend to GTC without an ExpiryAt value. 889 OrderErrorCannotHaveGTCAndExpiryAt OrderError = proto.OrderError_ORDER_ERROR_CANNOT_HAVE_GTC_AND_EXPIRYAT 890 // Amending to FOK or IOC is invalid. 891 OrderErrorCannotAmendToFOKOrIOC OrderError = proto.OrderError_ORDER_ERROR_CANNOT_AMEND_TO_FOK_OR_IOC 892 // Amending to GFA or GFN is invalid. 893 OrderErrorCannotAmendToGFAOrGFN OrderError = proto.OrderError_ORDER_ERROR_CANNOT_AMEND_TO_GFA_OR_GFN 894 // Amending from GFA or GFN is invalid. 895 OrderErrorCannotAmendFromGFAOrGFN OrderError = proto.OrderError_ORDER_ERROR_CANNOT_AMEND_FROM_GFA_OR_GFN 896 // IOC orders are not allowed during auction. 897 OrderErrorCannotSendIOCOrderDuringAuction OrderError = proto.OrderError_ORDER_ERROR_CANNOT_SEND_IOC_ORDER_DURING_AUCTION 898 // FOK orders are not allowed during auction. 899 OrderErrorCannotSendFOKOrderDurinAuction OrderError = proto.OrderError_ORDER_ERROR_CANNOT_SEND_FOK_ORDER_DURING_AUCTION 900 // Pegged orders must be LIMIT orders. 901 OrderErrorMustBeLimitOrder OrderError = proto.OrderError_ORDER_ERROR_MUST_BE_LIMIT_ORDER 902 // Pegged orders can only have TIF GTC or GTT. 903 OrderErrorMustBeGTTOrGTC OrderError = proto.OrderError_ORDER_ERROR_MUST_BE_GTT_OR_GTC 904 // Pegged order must have a reference price. 905 OrderErrorWithoutReferencePrice OrderError = proto.OrderError_ORDER_ERROR_WITHOUT_REFERENCE_PRICE 906 // Buy pegged order cannot reference best ask price. 907 OrderErrorBuyCannotReferenceBestAskPrice OrderError = proto.OrderError_ORDER_ERROR_BUY_CANNOT_REFERENCE_BEST_ASK_PRICE 908 // Pegged order offset must be >= 0. 909 OrderErrorOffsetMustBeGreaterOrEqualToZero OrderError = proto.OrderError_ORDER_ERROR_OFFSET_MUST_BE_GREATER_OR_EQUAL_TO_ZERO 910 // Sell pegged order cannot reference best bid price. 911 OrderErrorSellCannotReferenceBestBidPrice OrderError = proto.OrderError_ORDER_ERROR_SELL_CANNOT_REFERENCE_BEST_BID_PRICE 912 // Pegged order offset must be > zero. 913 OrderErrorOffsetMustBeGreaterThanZero OrderError = proto.OrderError_ORDER_ERROR_OFFSET_MUST_BE_GREATER_THAN_ZERO 914 // The party has an insufficient balance, or does not have 915 // a general account to submit the order (no deposits made 916 // for the required asset). 917 OrderErrorInsufficientAssetBalance OrderError = proto.OrderError_ORDER_ERROR_INSUFFICIENT_ASSET_BALANCE 918 // Cannot amend a non pegged orders details. 919 OrderErrorCannotAmendPeggedOrderDetailsOnNonPeggedOrder OrderError = proto.OrderError_ORDER_ERROR_CANNOT_AMEND_PEGGED_ORDER_DETAILS_ON_NON_PEGGED_ORDER 920 // We are unable to re-price a pegged order because a market price is unavailable. 921 OrderErrorUnableToRepricePeggedOrder OrderError = proto.OrderError_ORDER_ERROR_UNABLE_TO_REPRICE_PEGGED_ORDER 922 // It is not possible to amend the price of an existing pegged order. 923 OrderErrorUnableToAmendPriceOnPeggedOrder OrderError = proto.OrderError_ORDER_ERROR_UNABLE_TO_AMEND_PRICE_ON_PEGGED_ORDER 924 // An FOK, IOC, or GFN order was rejected because it resulted in trades outside the price bounds. 925 OrderErrorNonPersistentOrderOutOfPriceBounds OrderError = proto.OrderError_ORDER_ERROR_NON_PERSISTENT_ORDER_OUT_OF_PRICE_BOUNDS 926 // Unable to submit pegged order, temporarily too many pegged orders across all markets. 927 OrderErrorTooManyPeggedOrders OrderError = proto.OrderError_ORDER_ERROR_TOO_MANY_PEGGED_ORDERS 928 OrderErrorPostOnlyOrderWouldTrade OrderError = proto.OrderError_ORDER_ERROR_POST_ONLY_ORDER_WOULD_TRADE 929 OrderErrorReduceOnlyOrderWouldNotReducePosition OrderError = proto.OrderError_ORDER_ERROR_REDUCE_ONLY_ORDER_WOULD_NOT_REDUCE_POSITION 930 OrderErrorIsolatedMarginCheckFailed OrderError = proto.OrderError_ORDER_ERROR_ISOLATED_MARGIN_CHECK_FAILED 931 OrderErrorPeggedOrdersNotAllowedInIsolatedMargin OrderError = proto.OrderError_ORDER_ERROR_PEGGED_ORDERS_NOT_ALLOWED_IN_ISOLATED_MARGIN_MODE 932 OrderErrorPriceNotInTickSize OrderError = proto.OrderError_ORDER_ERROR_PRICE_NOT_IN_TICK_SIZE 933 OrderErrorPriceLTEMaxPrice OrderError = proto.OrderError_ORDER_ERROR_PRICE_MUST_BE_LESS_THAN_OR_EQUAL_TO_MAX_PRICE 934 OrderErrorSellOrderNotAllowed OrderError = proto.OrderError_ORDER_ERROR_SELL_ORDER_NOT_ALLOWED 935 ) 936 937 var ( 938 ErrInvalidMarketID = OrderErrorInvalidMarketID 939 ErrInvalidOrderID = OrderErrorInvalidOrderID 940 ErrOrderOutOfSequence = OrderErrorOutOfSequence 941 ErrInvalidRemainingSize = OrderErrorInvalidRemainingSize 942 ErrOrderRemovalFailure = OrderErrorRemovalFailure 943 ErrInvalidExpirationDatetime = OrderErrorInvalidExpirationDatetime 944 ErrEditNotAllowed = OrderErrorEditNotAllowed 945 ErrOrderAmendFailure = OrderErrorAmendFailure 946 ErrOrderNotFound = OrderErrorNotFound 947 ErrInvalidPartyID = OrderErrorInvalidParty 948 ErrInvalidSize = OrderErrorInvalidSize 949 ErrInvalidPersistence = OrderErrorInvalidPersistance 950 ErrInvalidType = OrderErrorInvalidType 951 ErrInvalidTimeInForce = OrderErrorInvalidTimeInForce 952 ErrPeggedOrderMustBeLimitOrder = OrderErrorMustBeLimitOrder 953 ErrPeggedOrderMustBeGTTOrGTC = OrderErrorMustBeGTTOrGTC 954 ErrPeggedOrderWithoutReferencePrice = OrderErrorWithoutReferencePrice 955 ErrPeggedOrderBuyCannotReferenceBestAskPrice = OrderErrorBuyCannotReferenceBestAskPrice 956 ErrPeggedOrderOffsetMustBeGreaterOrEqualToZero = OrderErrorOffsetMustBeGreaterOrEqualToZero 957 ErrPeggedOrderSellCannotReferenceBestBidPrice = OrderErrorSellCannotReferenceBestBidPrice 958 ErrPeggedOrderOffsetMustBeGreaterThanZero = OrderErrorOffsetMustBeGreaterThanZero 959 ErrTooManyPeggedOrders = OrderErrorTooManyPeggedOrders 960 ErrPostOnlyOrderWouldTrade = OrderErrorPostOnlyOrderWouldTrade 961 ErrReduceOnlyOrderWouldNotReducePosition = OrderErrorReduceOnlyOrderWouldNotReducePosition 962 ErrPeggedOrdersNotAllowedInIsolatedMargin = OrderErrorPeggedOrdersNotAllowedInIsolatedMargin 963 ErrOrderNotInTickSize = OrderErrorPriceNotInTickSize 964 ErrSellOrderNotAllowed = OrderErrorSellOrderNotAllowed 965 ) 966 967 func OtherSide(s Side) Side { 968 switch s { 969 case SideBuy: 970 return SideSell 971 case SideSell: 972 return SideBuy 973 } 974 return SideUnspecified 975 } 976 977 func IsOrderError(err error) (OrderError, bool) { 978 oerr, ok := err.(OrderError) 979 return oerr, ok 980 } 981 982 func IsStoppingOrder(o OrderError) bool { 983 return o == OrderErrorNonPersistentOrderOutOfPriceBounds || 984 o == ErrPostOnlyOrderWouldTrade || 985 o == ErrReduceOnlyOrderWouldNotReducePosition || 986 o == OrderErrorIsolatedMarginCheckFailed || 987 o == OrderErrorPeggedOrdersNotAllowedInIsolatedMargin 988 }