code.vegaprotocol.io/vega@v0.79.0/core/monitor/README.md (about)

     1  # Monitor package
     2  
     3  This package contains all engines that will monitor the sanity of the markets currently running. If something goes awry, these engines will suspend the _"normal"_ trading mode of markets, and trigger an auction. What it means to change the way a market trades is beyond the domain of the engines, just like the market itself shouldn't be aware of how the determination is made whether or not an auction ought to be triggered.
     4  
     5  That's where the `AuctionState` in this package comes in.
     6  
     7  ## Glorified DTO
     8  
     9  At its core, the `AuctionState` is little more than a DTO. It keeps track of what trading mode a given market is in, what its default trading mode is, and why it is in the mode it is in. If a market opens, a new `AuctionState` object is created for it. The state will immediately be set to reflect a market in opening auction. The start and end times will be set, and the state object will have a flag set that this auction period has just been triggered.
    10  
    11  The market will then check if its auction-state has been updated (`AuctionState.AuctionStart()`), and if it has, the market calls `EnterAuction()`. This function will do whatever a market has to do to enter an auction (update the orderbook, for example), and finally acknowledge the auction was started by calling `AuctionState.AuctionStarted()`. This function returns an auction event that the market will send to the broker.
    12  
    13  Every `market.OnChainTimeUpdate()`, the market checks whether it is currently trading in an auction. If it's an opening auction, we're dealing with a simple time-limited auction, and the market will check to see whether or not the auction period has expired. If it has, the market calls `AuctionState.SetReadyToLeave()`, performs everything it has to do to terminate the auction (updating the orderbook, uncrossing auction orders, ...), and then finally `AuctionState.Left()` is called. Like the `AuctionStarted()` call, this returns an event to push to the broker.
    14  
    15  ## For the monitor sub-packages
    16  
    17  Each monitor sub-package will have a slightly different interface definition for the `AuctionState` type. Specific calls like `StartPriceAuction()` are used by the price monitoring engine in case the mark price exceeds the expected range, but this call is meaningless to any other monitoring engines. What monitoring engines _can_ do, however is extend an auction period if needed. This is the reason why auction starts and endings require 2 calls (one returning a boolean value indicating an auction is starting/ending, the other for the market to confirm it has done so).
    18  
    19  One monitoring engine could find that it's safe to end an auction it triggered, but we don't want to leave this auction if another monitoring engine would immediately trigger a new auction period. In code, it could look something like this:
    20  
    21  ```go
    22  func (m *Market) inMarket() {
    23      if m.as.InAuction() {
    24          // see if price auction has anything to say/do with this auction
    25          m.price.CheckAuction(m.as)
    26          // same, but liquidity monitoring
    27          m.liquidity.CheckAuction(m.as)
    28          // any other monitoring engines we decide to add
    29          m.parties.CheckAuction(m.as)
    30          // monitoring engines have determined we can/should leave the auction
    31          if m.as.CanLeave() {
    32              m.LeaveAuction()
    33          }
    34      }
    35  }
    36  // in monitoring engines:
    37  func (p *Price) CheckAuction(as AuctionState) {
    38      // clearly, this monitoring engine only cares about auctions it started
    39      if !as.IsPriceAuction() {
    40          return
    41      }
    42      if as.AuctionStart().Before(as.CanLeave()) {
    43          // auction has expired - mark auction as over
    44          // this can be determined in different ways, that's up to the engine itself
    45          // for example: auctions bound by traded volume
    46          as.SetReadyToLeave()
    47      }
    48      // auction carries on as per usual
    49  }
    50  
    51  func (l *Liquidity) CheckAuction(as AuctionSate) {
    52      if as.IsOpeningAuction() {
    53          // an opening auction is not something we check
    54          return
    55      }
    56      if as.IsLiquidityAuction() {
    57          // auction was started by this engine
    58          // check if auction expired according to internal logic
    59          if l.checkSaysStop {
    60              as.SetReadyToLeave()
    61          }
    62          return // we've checked auction we started
    63      }
    64      // not a liquidity or opening auction, but it's the end of this auction
    65      if as.CanLeave() {
    66          // check internal logic, see if this auction can safely terminate
    67          if l.auctionNeeded() {
    68              as.ExtendAuction(params) // extend auction by some parameters based on internal logic
    69          }
    70      }
    71  }
    72  ```
    73  
    74  ## Price sub-package
    75  
    76  Price subpackage contains the price monitoring engine. It's used to determine if the price movement exceeded the bounds implied by the risk model over a specified horizon at a specified probability level. If that's the case, the price monitoring engine modifies the `AuctionState` to indicate that the price monitoring auction should commence. Once in auction, the engine checks if the auction time has elapsed, and if so if the resulting auction uncrossing price falls within the price monitoring bounds, if that condition is met the `AuctionState` object gets modified to indicate that price monitoring auction should finish, otherwise the  `AuctionState` object gets modified to indicate that the auction should be extended.
    77  
    78  Below is the signature of the price monitoring constructor:
    79  
    80  ```go
    81  func NewMonitor(riskModel RangeProvider, settings types.PriceMonitoringSettings) (*Engine, error)
    82  ```
    83  
    84  where:
    85  
    86  * `RangeProvider` exposes the method `PriceRange(price, yearFraction, probability float64) (float64, float64)` which returns the minimum (`minPrice`) and maximum (`maxPrice`) valid price per current price (`price`), the time horizon expressed as year fraction (`yearFraction`) and probability level (`probability`). `price`, `minPrice`, `maxPrice` are then used to imply `MinMoveDown` and `MaxMoveUp` over `yearFraction` at probability level  `probability` as: `MinMoveDown`=`minPrice` - `price`, `MaxMoveUp`: `maxPrice` - `price`.
    87  * `PriceMonitoringSettings` contains:
    88    * a list of `yearFraction`, `probability` and `auctionExtension` tuples, where `yearFraction`, `probability` are used in a call to the risk model and `auctionExtension` is the period in seconds by which the current auction should be extended (or initial period of new auction if currently market is in its _"normal"_ trading mode) should the actual price movement over min(`yearFraction`,t), where t is the time since last auction expressed as a year fraction, violate the bounds implied by the `RangeProvider` (`MinMoveDown`, `MaxMoveUp`),