code.vegaprotocol.io/vega@v0.79.0/core/execution/spot/auction.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 spot 17 18 import ( 19 "context" 20 "time" 21 22 "code.vegaprotocol.io/vega/core/execution/common" 23 "code.vegaprotocol.io/vega/core/types" 24 "code.vegaprotocol.io/vega/libs/num" 25 "code.vegaprotocol.io/vega/logging" 26 ) 27 28 func (m *Market) checkAuction(ctx context.Context, now time.Time, idgen common.IDGenerator) { 29 if !m.as.InAuction() { 30 if m.as.AuctionStart() { 31 m.enterAuction(ctx) 32 } 33 return 34 } 35 36 if m.mkt.State == types.MarketStateSuspendedViaGovernance { 37 if endTS := m.as.ExpiresAt(); endTS != nil && endTS.Before(now) { 38 m.as.ExtendAuctionSuspension(types.AuctionDuration{Duration: int64(m.minDuration.Seconds())}) 39 } 40 } 41 42 // here we are in auction, we'll want to check 43 // the triggers if we are leaving 44 defer func() { 45 m.triggerStopOrders(ctx, idgen) 46 }() 47 48 indicativeUncrossingPrice := num.UintZero() 49 50 checkExceeded := m.mkt.State == types.MarketStatePending 51 // as soon as we have an indicative uncrossing price in opening auction it needs to be passed into the price monitoring engine so statevar calculation can start 52 isOpening := m.as.IsOpeningAuction() 53 if isOpening && !m.pMonitor.Initialised() { 54 indicativeUncrossingPrice = m.matching.OrderBook.GetIndicativePrice() 55 56 if !indicativeUncrossingPrice.IsZero() { 57 // pass the first uncrossing price to price monitoring engine so state variables depending on it can be initialised 58 m.pMonitor.ResetPriceHistory(indicativeUncrossingPrice) 59 m.OnOpeningAuctionFirstUncrossingPrice() 60 } 61 if checkExceeded && m.as.ExceededMaxOpening(now) { 62 m.closeSpotMarket(ctx) 63 return 64 } 65 } 66 67 if endTS := m.as.ExpiresAt(); endTS == nil || !endTS.Before(now) { 68 if checkExceeded && isOpening && m.as.ExceededMaxOpening(now) { 69 m.closeSpotMarket(ctx) 70 } 71 return 72 } 73 if indicativeUncrossingPrice.IsZero() { 74 indicativeUncrossingPrice = m.matching.OrderBook.GetIndicativePrice() 75 } 76 77 // opening auction 78 if isOpening { 79 if indicativeUncrossingPrice.IsZero() { 80 if checkExceeded && m.as.ExceededMaxOpening(now) { 81 m.closeSpotMarket(ctx) 82 } 83 return 84 } 85 86 // opening auction period has expired, and we have trades, we should be ready to leave 87 // other requirements still need to be checked downstream though 88 m.as.SetReadyToLeave() 89 90 // if we don't have yet consensus for the floating point parameters, stay in the opening auction 91 if !m.CanLeaveOpeningAuction() { 92 m.log.Info("cannot leave opening auction - waiting for floating point to complete the first round") 93 return 94 } 95 m.log.Info("leaving opening auction for market", logging.String("market-id", m.mkt.ID)) 96 m.leaveAuction(ctx, now) 97 98 m.equityShares.OpeningAuctionEnded() 99 // start the market fee window 100 m.feeSplitter.TimeWindowStart(now) 101 102 // reset SLA epoch 103 m.liquidity.OnEpochStart(ctx, 104 m.timeService.GetTimeNow(), 105 m.getCurrentMarkPrice(), 106 m.midPrice(), 107 m.getTargetStake(), 108 m.positionFactor, 109 ) 110 111 return 112 } 113 114 if m.as.Trigger() == types.AuctionTriggerLongBlock || m.as.ExtensionTrigger() == types.AuctionTriggerLongBlock || 115 m.as.Trigger() == types.AuctionTriggerAutomatedPurchase || m.as.ExtensionTrigger() == types.AuctionTriggerAutomatedPurchase { 116 if endTS := m.as.ExpiresAt(); endTS != nil && endTS.Before(now) { 117 m.as.SetReadyToLeave() 118 } 119 } 120 121 isPrice := m.as.IsPriceAuction() || m.as.IsPriceExtension() 122 if isPrice || m.as.CanLeave() { 123 m.pMonitor.CheckPrice(ctx, m.as, indicativeUncrossingPrice, true, true) 124 } 125 end := m.as.CanLeave() 126 if evt := m.as.AuctionExtended(ctx, m.timeService.GetTimeNow()); evt != nil { 127 m.broker.Send(evt) 128 end = false 129 } 130 // price monitoring engine and liquidity monitoring engine both indicated auction can end 131 if end { 132 // can we leave based on the book state? 133 m.leaveAuction(ctx, now) 134 } 135 }