code.vegaprotocol.io/vega@v0.79.0/core/execution/spot/special_orders.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 //lint:file-ignore U1000 Ignore unused functions 17 18 package spot 19 20 import ( 21 "context" 22 23 "code.vegaprotocol.io/vega/core/events" 24 "code.vegaprotocol.io/vega/core/execution/common" 25 "code.vegaprotocol.io/vega/core/metrics" 26 "code.vegaprotocol.io/vega/core/types" 27 "code.vegaprotocol.io/vega/libs/num" 28 "code.vegaprotocol.io/vega/logging" 29 ) 30 31 func (m *Market) repricePeggedOrders(ctx context.Context, changes uint8) (parked []*types.Order, toSubmit []*types.Order) { 32 timer := metrics.NewTimeCounter(m.mkt.ID, "market", "repricePeggedOrders") 33 34 // Go through *all* of the pegged orders and remove from the order book 35 // NB: this is getting all of the pegged orders that are unparked in the order book AND all 36 // the parked pegged orders. 37 allPeggedIDs := m.matching.GetActivePeggedOrderIDs() 38 allPeggedIDs = append(allPeggedIDs, m.peggedOrders.GetParkedIDs()...) 39 for _, oid := range allPeggedIDs { 40 var ( 41 order *types.Order 42 err error 43 ) 44 if m.peggedOrders.IsParked(oid) { 45 order = m.peggedOrders.GetParkedByID(oid) 46 } else { 47 order, err = m.matching.GetOrderByID(oid) 48 if err != nil { 49 m.log.Panic("if order is not parked, it should be on the book", logging.OrderID(oid)) 50 } 51 } 52 if common.OrderReferenceCheck(*order).HasMoved(changes) { 53 // First if the order isn't parked, then 54 // we will just remove if from the orderbook 55 if order.Status != types.OrderStatusParked { 56 // Remove order if any volume remains, 57 // otherwise it's already been popped by the matching engine. 58 m.releaseOrderFromHoldingAccount(ctx, order.ID, order.Party, order.Side) 59 cancellation, err := m.matching.CancelOrder(order) 60 if cancellation == nil || err != nil { 61 m.log.Panic("Failure after cancel order from matching engine", 62 logging.Order(*order), 63 logging.Error(err)) 64 } 65 } else { 66 // unpark before it's reparked next eventually 67 m.peggedOrders.Unpark(order.ID) 68 } 69 70 if price, err := m.getNewPeggedPrice(order); err != nil { 71 // Failed to reprice, we need to park again 72 order.UpdatedAt = m.timeService.GetTimeNow().UnixNano() 73 order.Status = types.OrderStatusParked 74 order.Price = num.UintZero() 75 order.OriginalPrice = nil 76 m.broker.Send(events.NewOrderEvent(ctx, order)) 77 parked = append(parked, order) 78 } else { 79 // Repriced so all good make sure status is correct 80 order.Price = price.Clone() 81 order.OriginalPrice, _ = num.UintFromDecimal(price.ToDecimal().Div(m.priceFactor)) 82 order.Status = types.OrderStatusActive 83 order.UpdatedAt = m.timeService.GetTimeNow().UnixNano() 84 toSubmit = append(toSubmit, order) 85 } 86 } 87 } 88 89 timer.EngineTimeCounterAdd() 90 return parked, toSubmit 91 } 92 93 func (m *Market) reSubmitPeggedOrders(ctx context.Context, toSubmitOrders []*types.Order) []*types.Order { 94 var ( 95 updatedOrders = []*types.Order{} 96 evts = []events.Event{} 97 ) 98 99 // Reinsert all the orders 100 for _, order := range toSubmitOrders { 101 if err := m.checkSufficientFunds(order.Party, order.Side, order.Price, order.TrueRemaining(), order.PeggedOrder != nil, types.AccountTypeGeneral); err != nil { 102 order.Status = types.OrderStatusStopped 103 m.removePeggedOrder(order) 104 evts = append(evts, events.NewOrderEvent(ctx, order)) 105 continue 106 } 107 m.transferToHoldingAccount(ctx, order) 108 m.matching.ReSubmitSpecialOrders(order) 109 updatedOrders = append(updatedOrders, order) 110 evts = append(evts, events.NewOrderEvent(ctx, order)) 111 } 112 113 // send new order events 114 m.broker.SendBatch(evts) 115 116 return updatedOrders 117 } 118 119 func (m *Market) repriceAllSpecialOrders( 120 ctx context.Context, 121 changes uint8, 122 ) { 123 if changes == 0 { 124 // nothing to do, prices didn't move, 125 // no orders have been updated, there's no 126 // reason pegged order should get repriced or 127 // lp to be differnet than before 128 return 129 } 130 131 // first we get all the pegged orders to be resubmitted with a new price 132 var parked, toSubmit []*types.Order 133 if changes != 0 { 134 parked, toSubmit = m.repricePeggedOrders(ctx, changes) 135 for _, topark := range parked { 136 m.peggedOrders.Park(topark) 137 } 138 } 139 140 // if we needed to re-submit pegged orders, 141 // let's do it now 142 if len(toSubmit) > 0 { 143 m.reSubmitPeggedOrders(ctx, toSubmit) 144 } 145 } 146 147 func (m *Market) enterAuctionSpecialOrders(ctx context.Context) { 148 // first remove all GFN orders from the peg list 149 ordersEvts := m.peggedOrders.EnterAuction(ctx) 150 m.broker.SendBatch(ordersEvts) 151 m.parkAllPeggedOrders(ctx) 152 }