The dynamics of market price movements are such that prices don't always represent the participants' true average view of the price, but are instead artefacts of the market microstructure: sometimes low liquidity and/or a large quantity of order volume can cause the price to diverge from the true market price. It is impossible to tell at any point in time if this has happened or not.
As a result, we assume that relatively small moves are "real" and that larger moves might not be. Price monitoring exists to determine the real price in the latter case. Distinguishing between small and large moves can be highly subjective and market-dependent.
We are going to rely on the risk model to formalise this process. Risk model can be used to obtain the probability distribution of prices at a future point in time given the current price. A price monitoring trigger can be constructed using a fixed horizon and probability level.
To give an example: get the price distribution in an hour as implied by the risk model given the current mid price, if after the hour has passed and the actual mid price is beyond what the model implied (either too low or too high) with some chosen probability level (say 99%), then we'd characterise such market move as large. In general we may want to use a few such triggers per market (i.e. different horizon and probability level pairs). The framework should be able to trigger a price protection auction period with any valid trading mode.
We're also going to allow specifying triggers directly as the maximum valid moves with respect to the reference price. In that case the maxUpMoveFactor
, maxDownMoveFactor
can be specified for a given horizon, such that a price is considered valid as long as it's in the range [reference_price(horizon) * maxDownMoveFactor, [reference)price(horizon) * maxUpMoveFactor]
, where [reference_price(horizon)
is the reference price corresponding to the specified horizon - obtained in exactly the same way as in the case of a model-based trigger.
As mentioned above, price monitoring is meant to stop large market movements that are not "real" from occurring, rather than just detect them after the fact. To that end, it is necessary to pre-process every transaction and check if it triggers the price monitoring action. If pre-processing the transaction doesn't result in the trigger being activated then it should be "committed" by generating the associated events and modifying the order book accordingly (e.g. generate a trade and take the orders that matched off the book). On the other hand if the trigger is activated and the submitted transaction is valid for auction mode, the entire order book along with that transaction needs to be processed via price protection auction. If the transaction which activate the trigger is not valid for auction, then it should get rejected and market should continue in the current trading mode. Auction period associated with a given distribution projection horizon and probability level will be specified as part of market setup. Once the auction period finishes the trading should resume in regular fashion (unless other triggers are active, more on that in reference-level explanation).
Please see the auction spec for auction details.
Price monitoring engine should track mark price evolution within the market. It should be used to monitor trades as well as mark price update candidates. If any of these violates the bounds the market should go into auction and the transaction should get rejected.
Price monitoring likely won't be the only possible trigger of auction period e.g. governance action could be the other ones. Thus the framework put in place as part of this spec should be flexible enough to easily accommodate other types of triggers.
Likewise, pre-processing transactions will be needed as part of the fees spec, hence it should be implemented in such a way that it's easy to repurpose it.
- We need to emit a "significant price change" event if price move over the horizon τ turned out to be more than what the risk model implied at a probability level α.
- Take arrival price of the next transaction (the value that will be the last traded price if we process the next transaction or the mark price update value): Vt,
- look-up mark price St-τ, (prices aren't continuous so will need max(Ss : s ≤ t-τ), call it St-τ*,
- get the bounds associated with St-τ*, at a probability level α:
- if Vt falls within those bounds then transaction is processed in the current trading mode
- otherwise:
- the incoming aggressive order (along with the rest of order book) needs to be processed via a temporary auction,
- the mark price update value gets discarded and the market goes into auction, the value obtained upon uncrossing the auction (if any) gets used as the next mark price update value. Any other mark price updates arriving during the price monitoring auction get discarded.
- We need to have "atomicity" in transaction processing:
- When we process transaction we need to check what the arrival price Vt is.
- If it results in "significant price change" event then we want the order book to maintain the state from before we started processing the transaction.
- If the transaction is valid for auction mode then price protection auction gets triggered for a period T.
- If the transaction is not valid for auction mode then it gets rejected, an appropriate event gets sent and market continues in current trading mode.
- In general we might have a list of triplets: α, τ, T specifying each trigger.
- Once the price protection auction period finishes, the remaining triggers should be examined and if hit the auction period should be extended accordingly.
- Then the market continues in the regular fashion.
priceMonitoringParameters
- an array of more price monitoring parameters with the following fields:horizon
- price projection horizon expressed as a year fraction over which price is to be projected by the risk model and compared to the actual market moves during that period. Must be positive.probability
- probability level used in price monitoring. Must be in the [0.9,1) range.auctionExtension
- auction duration (or extension in case market is already in auction mode) per breach of thehorizon
,probability
trigger pair specified above. Must be greater than 0.
If any of the above parameters or the risk model gets modified in any way, the price monitoring engine should get reset (price history gets cleared and bounds get recalculated). If the market is price monitoring auction (or auction extension triggered by price monitoring engine):
- any remaining price monitoring bounds calculated prior to the update should get deactivated,
- the auction end time implied by the currently running auction/extension should remain unchanged,
- when auction uncrosses price monitoring should get reset using the updated parameters.
modelFreePriceMonitoringParameters
- an array of more price monitoring parameters with the following fields:horizon
- price projection horizon expressed as a year fraction over which price is to be projected by the risk model and compared to the actual market moves during that period. Must be positive.maxUpMoveFactor
- a factor to be applied to the reference price (for the specified horizon) so that the maximum valid price isreference_price(horizon) * maxUpMoveFactor
. Must be greater than1
.maxDownMoveFactor
- a factor to be applied to the reference price (for the specified horizon) so that the minimum valid price isreference_price(horizon) * maxDownMoveFactor
. Must be less than1
.
market.monitor.price.defaultParameters
: Specifies default market parameters outlined in the previous paragraph. These will be used if market parameters don't get explicitly specified.
- Vega allows maximum of
100
price monitoring parameter triples inpriceMonitoringParameters
per market.
There are several reasons why this maximum is enforced.
- anything more than
100
triplets makes reasoning about what and when will trigger an auction more difficult and could lead to markets that behave in unexpected ways. - allowing high number of triplets could have performance impact
- testing everything works correctly is more manageable if the number is capped.
-
Per each transaction:
- the matching engine sends the price monitoring engine the arrival price of the next transaction along with the current
vega time
- price monitoring engine sends back signal informing if the price protection auction should be triggered (and if so how long the auction period should be),
- if no trigger gets activated then the transaction is processed in a regular fashion, otherwise:
- the price protection auction commences and the transaction considered should be processed in this way (along with any other orders on the book and pending transactions that are valid for auction).
- the matching engine sends the price monitoring engine the arrival price of the next transaction along with the current
-
Per mark price update:
- when the next mark price update value is received it gets checked against the price monitoring engine,
- price monitoring engine sends back signal informing if the price protection auction should be triggered (and if so how long the auction period should be),
- if no trigger gets activated then the mark price update candidate gets accepted, included in the internal price history tracked by the price monitoring engine and mark-to-market process carries on as usual, otherwise:
- the price protection auction commences, any other mark price update candidates received before the auction ends get discarded, if the auction ends and results in a price than that price gets used as the next mark price, it gets included in the internal price history tracked by the price monitoring engine and the mark-to-market process carries on as usual.
Price monitoring engine will interface between the matching engine and the risk model. It will communicate with the matching engine every time a new transaction is processed (to check it its' arrival price should trigger an auction). It will communicate with the risk model with a predefined frequency to inform the risk model of the latest mark price history and obtain a new set of scaling factors used to calculate min/max prices from the reference price.
Specifically:
- It periodically (in a predefined, deterministic way) sends the:
- the probability level α,
- period τ,
- the associated reference price to the risk model and obtains the range of valid up/down price moves per each of the specified triggers. Please note that these can be expressed as either additive offsets or multiplicative factors depending on the risk model used. The reference price is the latest price such that it's at least τ old or the earliest available price should price history be shorter than τ.
- It holds the history of mark prices looking back to the maximum τ configured in the market.
- Every time a new price is received from the matching engine the price monitoring engine checks all the [τ, up factor, down factor] triplets relevant for the timestamp, looks-up the associated past (volume weighted) price and sends the signal back to the matching engine informing if the received price would breach the min/max move prescribed by the risk model.
- Every time a new price is mark price candidate is available the price monitoring engine checks all the [τ, up factor, down factor] triplets relevant for the timestamp, looks-up the associated past (volume weighted) price and sends the signal back to the matching engine informing if the received price would breach the min/max move prescribed by the risk model.
- The bounds corresponding to the current time instant and the arrival price of the next transaction will be used to indicate if the price protection auction should commence. The triggers are sorted by period τ (increasing order) and probability level (decreasing order). As soon the first bound is violated the price monitoring auction with the extension period defined for the corresponding trigger is initiated. After that period elapses the indicative uncrossing price is checked against the remaining bounds and auction gets extended if another bound is violated. The process is repeated until the uncrossing price satisfies all the remaining bounds or there are no active triggers left.
- To give an example, with 3 triggers the price protection auction can be calculated as follows:
- >=1% move in 10 min window -> 5 min auction,
- >=2% move in 30 min window -> 15 min auction (i.e. if after 5 min this trigger condition is satisfied by the price we'd uncross at, extend auction by 10 minutes),
- >=5% move in 2 hour window -> 1 hour auction (if after 15 minutes, this is satisfied by the price we'd uncross at, extend auction by another 45 minutes).
- At the market start time and after each price-monitoring auction period the bounds will reset
- hence the bounds between that time and the minimum τ specified in the triggers will be constant (calculated using current price, the minimum τ and α associated with it).
- The resulting auction length should be at least
min_auction_length
(see the auctions spec). If the auction length implied by the triggers is less than that it should be extended.
View from quant library side
-
The risk model calculates the bounds per reference price, horizon τ and confidence level α beyond which a price monitoring auction should be triggered.
-
The ranges of valid price moves are returned as either additive offsets or multiplicative factors for the up and down move. The price monitoring engine (PME) will know how to cope with either and apply it to the price bounds.
-
These bounds are to be available to other components and included in the market data API
-
Internally the risk model implements a function that takes as input: (reference price, confidence level alpha, time period tau) and returns either:
- the additive offsets: fminadditive, fmaxadditive such that Smin:=Sref+fminadditive and Smax:=Sref+fmaxadditive or
- the multiplicative factors: fminmultiplicative, fmaxmultiplicative such that Smin:=Sref*fminmultiplicative and Smax:=Sref*fmaxmultiplicative
so that P(Smin < Sτ < Smax) ≥ α.
- Market's price monitoring parameters and triggers (horizon, confidence level, auction extension triplet) can be queried via APIs. (0032-PRIM-001). For product spot: (0032-PRIM-022)
- Non-persistent order does not result in an auction (1 out of 2 triggers breached), order gets cancelled (never makes it to the order book) (0032-PRIM-003). For product spot: (0032-PRIM-023)
- The market continues in regular fashion once price protection auction period ends and price monitoring bounds get reset based on last traded price (which may come from the auction itself if it resulted in trades) (0032-PRIM-005). For product spot: (0032-PRIM-024)
- Persistent order results in an auction (one trigger breached), no orders placed during auction, auction terminates with a trade from order that originally triggered the auction. (0032-PRIM-006). For product spot: (0032-PRIM-025)
- A maximum of
100
price monitoring triggers can be added per market (0032-PRIM-007). For product spot: (0032-PRIM-026) - Persistent order results in an auction (1 out of 2 triggers breached), orders placed during auction result in trade with indicative price outside the price monitoring bounds of the 2nd trigger, hence auction get extended (by extension period specified for the 2nd trigger), additional orders resulting in more trades (indicative price still outside the 2nd trigger bounds) placed, auction concludes. (0032-PRIM-008). For product spot: (0032-PRIM-027)
- If the cumulative extensions period of various chained auctions is more than the "time horizon" in a given triplet then there is no relevant reference price and this triplet is ignored. (0032-PRIM-009). For product spot: (0032-PRIM-028)
- Change of
market.monitor.price.defaultParameters
will change the default market parameters used in price monitoring when a new market is proposed and market parameters don't get explicitly specified. (0032-PRIM-010). For product spot: (0032-PRIM-029) - When market is in its default trading mode, change of
priceMonitoringParameters
results in price monitoring bounds being reset immediately. (0032-PRIM-011). For product spot: (0032-PRIM-030) - When market is in its default trading mode, change of a risk model or any of its parameters results in price monitoring bounds being reset immediately. (0032-PRIM-012). For product spot: (0032-PRIM-031)
- When market is in price monitoring auction, change of
priceMonitoringParameters
doesn't affect the previously calculated auction end time, any remaining price monitoring bounds cannot extend the auction further. Upon uncrossing price monitoring bounds get reset using the updated parameter values. (0032-PRIM-013). For product spot: (0032-PRIM-032) - When market is in price monitoring auction, change of a risk model or any of its parameters doesn't affect the previously calculated auction end time, any remaining price monitoring bounds cannot extend the auction further. Upon uncrossing price monitoring bounds get reset using the updated parameter values. (0032-PRIM-014). For product spot: (0032-PRIM-033)
- Specifying a non-positive horizon results in an error. (0032-PRIM-015). For product spot: (0032-PRIM-034)
- Specifying a probability outside the range (0.9,1) results in an error. (0032-PRIM-016). For product spot: (0032-PRIM-035)
- Specifying a non-positive auction extension results in an error. (0032-PRIM-017). For product spot: (0032-PRIM-036)
- Settlement price outside the current price monitoring bounds does not trigger an auction (0032-PRIM-018)
- A network trade (during closeout) with a price outside price monitoring bounds does not trigger an auction. (0032-PRIM-019)
- 2 persistent orders with prices outside both trigger price bands triggers an auction. Initial auction duration is equal to the extension period of the first trigger. Once the initial period ends the auction gets extended by the extension period of the second trigger. No other orders placed during auction, auction terminates with a trade from order that originally triggered the auction. (0032-PRIM-020). For product spot: (0032-PRIM-037)
- Same as above, but more matching orders get placed during the auction extension. The volume of the trades generated by the later orders is larger than that of the original pair which triggered the auction. Hence the auction concludes generating the trades from the later orders. The overall auction duration is equal to the sum of the extension periods of the two triggers. (0032-PRIM-021). For product spot: (0032-PRIM-038)
- For all available mark price calculation methodologies: the price history used by the price monitoring engine is in line with market's mark price history. (0032-PRIM-039)
- For all available mark-price calculation methodologies: the mark price update candidate gets rejected if it violates the price monitoring engine bounds. (0032-PRIM-040)
- Model-free triggers can be added to the market at creation time along with regular triggers. (0032-PRIM-041)
- Model-free triggers can be added to the market during market update along with regular triggers. (0032-PRIM-042)
- Adding a model-free trigger with
maxUpMoveFactor = 1.1
andmaxDownMoveFactor = 0.95
results in bonds with max valid price of110
and min valid price of95
when a reference price is100
. When time passes so that the reference price becomes90
then the resulting max valid price is99
and min valid price is85.5
. Violating any of these bounds results in an auction. (0032-PRIM-043 )