Skip to content

Commit

Permalink
Merge pull request #11262 from vegaprotocol/feature-test-0032-PRIM-033
Browse files Browse the repository at this point in the history
Adding feature test for 0032-PRIM-003 and bug fix
  • Loading branch information
jeremyletang committed May 13, 2024
1 parent 7c7e2ab commit 03b90de
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- [11250](https://github.com/vegaprotocol/vega/issues/11250) - Add missing dispatch strategy in transfer proposal.
- [11252](https://github.com/vegaprotocol/vega/issues/11252) - Treat no position as zero position when calculating stop order overrides.
- [11249](https://github.com/vegaprotocol/vega/issues/11249) - Composite mark price oracles are now deactivated when a market is rejected.
- [11262](https://github.com/vegaprotocol/vega/pull/11262) - Fix auction extensions after risk parameter update.


## 0.76.0
Expand Down
2 changes: 1 addition & 1 deletion core/execution/common/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ type PriceMonitor interface {
Changed() bool
IsBoundFactorsInitialised() bool
Initialised() bool
UpdateSettings(risk.Model, *types.PriceMonitoringSettings)
UpdateSettings(risk.Model, *types.PriceMonitoringSettings, price.AuctionState)
}

// TimeService ...
Expand Down
2 changes: 1 addition & 1 deletion core/execution/future/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ func (m *Market) Update(ctx context.Context, config *types.Market, oracleEngine
m.risk.UpdateModel(m.stateVarEngine, m.tradableInstrument.MarginCalculator, m.tradableInstrument.RiskModel, m.mkt.LinearSlippageFactor, m.mkt.QuadraticSlippageFactor)
m.settlement.UpdateProduct(m.tradableInstrument.Instrument.Product)
m.tsCalc.UpdateParameters(*m.mkt.LiquidityMonitoringParameters.TargetStakeParameters)
m.pMonitor.UpdateSettings(m.tradableInstrument.RiskModel, m.mkt.PriceMonitoringSettings)
m.pMonitor.UpdateSettings(m.tradableInstrument.RiskModel, m.mkt.PriceMonitoringSettings, m.as)
m.liquidity.UpdateMarketConfig(m.tradableInstrument.RiskModel, m.pMonitor)
if err := m.markPriceCalculator.UpdateConfig(ctx, oracleEngine, m.mkt.MarkPriceConfiguration); err != nil {
m.markPriceCalculator.SetOraclePriceScalingFunc(m.scaleOracleData)
Expand Down
2 changes: 1 addition & 1 deletion core/execution/spot/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ func (m *Market) Update(ctx context.Context, config *types.Market) error {
if err != nil {
return err
}
m.pMonitor.UpdateSettings(riskModel, m.mkt.PriceMonitoringSettings)
m.pMonitor.UpdateSettings(riskModel, m.mkt.PriceMonitoringSettings, m.as)
m.liquidity.UpdateMarketConfig(riskModel, m.pMonitor)
m.updateLiquidityFee(ctx)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,16 @@ Feature: Confirm return to continuous trading during significant mark price chan
| ETH/FEB23 | my-price-monitoring-2 | weight | 0,0,1,0 | 0s,0s,0h0m120s,0s |
# first we get bounds based on default factors, once the state variable engine finishes its calculation we get the proper values
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | auction trigger | horizon | ref price | min bound | max bound |
| 1000 | TRADING_MODE_MONITORING_AUCTION | AUCTION_TRIGGER_PRICE | 30 | 1000 | 900 | 1100 |
| mark price | trading mode | auction trigger |
| 1000 | TRADING_MODE_MONITORING_AUCTION | AUCTION_TRIGGER_PRICE |

# the last second of the original extensions
And the network moves ahead "3" blocks
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | auction trigger | horizon | ref price | min bound | max bound |
| 1000 | TRADING_MODE_MONITORING_AUCTION | AUCTION_TRIGGER_PRICE | 30 | 1000 | 997 | 1003 |
| mark price | trading mode | auction trigger |
| 1000 | TRADING_MODE_MONITORING_AUCTION | AUCTION_TRIGGER_PRICE |

# the updated extension triggered, no triggers left
# the updated extension triggered, no triggers left as they've all been switched off since update took place during auction
And the network moves ahead "1" blocks
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | auction trigger |
Expand Down Expand Up @@ -174,15 +174,15 @@ Feature: Confirm return to continuous trading during significant mark price chan
# the last second of the original extensions
And the network moves ahead "3" blocks
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | auction trigger | horizon | ref price | min bound | max bound |
| 1000 | TRADING_MODE_MONITORING_AUCTION | AUCTION_TRIGGER_PRICE | 30 | 1000 | 997 | 1003 |
| mark price | trading mode | auction trigger |
| 1000 | TRADING_MODE_MONITORING_AUCTION | AUCTION_TRIGGER_PRICE |

When the parties place the following orders with ticks:
| party | market id | side | volume | price | resulting trades | type | tif |
| party1 | ETH/FEB23 | buy | 1 | 2004 | 0 | TYPE_LIMIT | TIF_GTC |
| party2 | ETH/FEB23 | sell | 1 | 2004 | 0 | TYPE_LIMIT | TIF_GTC |

# the updated extension triggered, no triggers left
# the updated extension triggered, no triggers left as they've all been switched off since update took place during auction
And the network moves ahead "1" blocks
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | auction trigger |
Expand Down Expand Up @@ -217,14 +217,14 @@ Feature: Confirm return to continuous trading during significant mark price chan
# the last second of the original extensions
And the network moves ahead "3" blocks
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | auction trigger | horizon | ref price | min bound | max bound |
| 1000 | TRADING_MODE_MONITORING_AUCTION | AUCTION_TRIGGER_PRICE | 30 | 1000 | 997 | 1003 |
| mark price | trading mode | auction trigger |
| 1000 | TRADING_MODE_MONITORING_AUCTION | AUCTION_TRIGGER_PRICE |

When the oracles broadcast data with block time signed with "0xCAFECAFE1":
| name | value | time offset |
| prices.ETH.value | 2000 | -1s |

# the updated extension triggered, no triggers left
# the updated extension triggered, no triggers left as they've all been switched off since update took place during auction
And the network moves ahead "1" blocks
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | auction trigger |
Expand Down Expand Up @@ -253,4 +253,26 @@ Feature: Confirm return to continuous trading during significant mark price chan
And the network moves ahead "118" blocks
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | auction trigger | last traded price | horizon | ref price | min bound | max bound |
| 1000 | TRADING_MODE_CONTINUOUS | AUCTION_TRIGGER_UNSPECIFIED | 1003 | 30 | 1003 | 1000 | 1006 |
| 1000 | TRADING_MODE_CONTINUOUS | AUCTION_TRIGGER_UNSPECIFIED | 1003 | 30 | 1003 | 1000 | 1006 |

Scenario: Verify that trigger update in continuous trading works as expected

When the network moves ahead "2" blocks
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | horizon | ref price | min bound | max bound |
| 1000 | TRADING_MODE_CONTINUOUS | 60 | 1000 | 995 | 1005 |

And the price monitoring named "my-price-monitoring-2":
| horizon | probability | auction extension |
| 30 | 0.95 | 1 |

# update trigger here so that there's only one
When the markets are updated:
| id | price monitoring | price type | source weights | source staleness tolerance |
| ETH/FEB23 | my-price-monitoring-2 | weight | 0,0,1,0 | 0s,0s,0h0m120s,0s |

# the last second of the original extensions
And the network moves ahead "3" blocks
Then the market data for the market "ETH/FEB23" should be:
| mark price | trading mode | horizon | ref price | min bound | max bound |
| 1000 | TRADING_MODE_CONTINUOUS | 30 | 1000 | 997 | 1003 |
112 changes: 112 additions & 0 deletions core/integration/features/spot/orders/0032-PRIM-033.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
Feature: Spot market

Background:
Given time is updated to "2024-01-01T00:00:00Z"

Given the following network parameters are set:
| name | value |
| network.markPriceUpdateMaximumFrequency | 0s |
| market.value.windowLength | 1h |

Given the following assets are registered:
| id | decimal places |
| ETH | 2 |
| BTC | 2 |

Given the fees configuration named "fees-config-1":
| maker fee | infrastructure fee |
| 0.01 | 0.03 |
Given the log normal risk model named "lognormal-risk-model-1":
| risk aversion | tau | mu | r | sigma |
| 0.001 | 0.01 | 0 | 0.0 | 1.2 |

Given the log normal risk model named "lognormal-risk-model-2":
| risk aversion | tau | mu | r | sigma |
| 0.002 | 0.02 | 0 | 0.1 | 1.3 |

And the price monitoring named "price-monitoring-1":
| horizon | probability | auction extension |
| 30 | 0.999 | 10 |
| 60 | 0.999 | 20 |
| 90 | 0.999 | 40 |
| 120 | 0.999 | 80 |

And the spot markets:
| id | name | base asset | quote asset | risk model | auction duration | fees | price monitoring | decimal places | position decimal places | sla params |
| BTC/ETH | BTC/ETH | BTC | ETH | lognormal-risk-model-1 | 1 | fees-config-1 | price-monitoring-1 | 2 | 2 | default-basic |

# setup accounts
Given the parties deposit on asset's general account the following amount:
| party | asset | amount |
| party1 | ETH | 10000 |
| party1 | BTC | 1000 |
| party2 | ETH | 10000 |
| party4 | BTC | 1000 |
| party5 | BTC | 1000 |
And the average block duration is "1"

# Place some orders to get out of auction
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| party1 | BTC/ETH | buy | 1 | 1000 | 0 | TYPE_LIMIT | TIF_GFA |
| party5 | BTC/ETH | sell | 1 | 1000 | 0 | TYPE_LIMIT | TIF_GTC |

And the opening auction period ends for market "BTC/ETH"
When the network moves ahead "1" blocks
Then the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "BTC/ETH"
And the mark price should be "1000" for the market "BTC/ETH"

Scenario: 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-033)

# Check that the market price bounds are set
And the market data for the market "BTC/ETH" should be:
| mark price | trading mode | horizon | min bound | max bound | target stake | supplied stake | open interest | auction start | auction end |
| 1000 | TRADING_MODE_CONTINUOUS | 30 | 997 | 1003 | 0 | 0 | 0 | 0 | 0 |
| 1000 | TRADING_MODE_CONTINUOUS | 60 | 995 | 1005 | 0 | 0 | 0 | 0 | 0 |
| 1000 | TRADING_MODE_CONTINUOUS | 90 | 994 | 1006 | 0 | 0 | 0 | 0 | 0 |
| 1000 | TRADING_MODE_CONTINUOUS | 120 | 993 | 1007 | 0 | 0 | 0 | 0 | 0 |

# Place 2 persistent orders that are outside all of the price bounds
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | reference |
| party1 | BTC/ETH | buy | 1 | 1008 | 0 | TYPE_LIMIT | TIF_GTC | buy1 |
| party5 | BTC/ETH | sell | 1 | 1008 | 0 | TYPE_LIMIT | TIF_GTC | sell1 |
When the network moves ahead "1" blocks

# Check we have been placed in auction
Then the trading mode should be "TRADING_MODE_MONITORING_AUCTION" for the market "BTC/ETH"

# Check we know the auction time
And the market data for the market "BTC/ETH" should be:
| mark price | trading mode | horizon | min bound | max bound | target stake | supplied stake | open interest | auction start | auction end |
| 1000 | TRADING_MODE_MONITORING_AUCTION | 60 | 995 | 1005 | 0 | 0 | 0 | 1704067203000000000 | 1704067213000000000 |
| 1000 | TRADING_MODE_MONITORING_AUCTION | 90 | 994 | 1006 | 0 | 0 | 0 | 1704067203000000000 | 1704067213000000000 |
| 1000 | TRADING_MODE_MONITORING_AUCTION | 120 | 993 | 1007 | 0 | 0 | 0 | 1704067203000000000 | 1704067213000000000 |

# Now update the risk model to deactivate all pending price bounds
Then the spot markets are updated:
| id | risk model |
| BTC/ETH | lognormal-risk-model-2 |

# If we move ahead 25 blocks we should come out of auction instead of it being extended
When the network moves ahead "25" blocks

And the market data for the market "BTC/ETH" should be:
| mark price | trading mode | horizon | min bound | max bound | target stake | supplied stake | open interest | auction start | auction end |
| 1008 | TRADING_MODE_CONTINUOUS | 30 | 1004 | 1012 | 0 | 0 | 0 | 0 | 0 |
| 1008 | TRADING_MODE_CONTINUOUS | 60 | 1003 | 1013 | 0 | 0 | 0 | 0 | 0 |
| 1008 | TRADING_MODE_CONTINUOUS | 90 | 1001 | 1015 | 0 | 0 | 0 | 0 | 0 |
| 1008 | TRADING_MODE_CONTINUOUS | 120 | 1000 | 1016 | 0 | 0 | 0 | 0 | 0 |

Then the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "BTC/ETH"

# The mark price should show the orders have traded
And the mark price should be "1008" for the market "BTC/ETH"

And the orders should have the following states:
| party | market id | reference | side | volume | remaining | price | status |
| party1 | BTC/ETH | buy1 | buy | 1 | 0 | 1008 | STATUS_FILLED |
| party5 | BTC/ETH | sell1 | sell | 1 | 0 | 1008 | STATUS_FILLED |

12 changes: 7 additions & 5 deletions core/monitor/price/pricemonitoring.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ type Engine struct {
asset string
}

func (e *Engine) UpdateSettings(riskModel risk.Model, settings *types.PriceMonitoringSettings) {
func (e *Engine) UpdateSettings(riskModel risk.Model, settings *types.PriceMonitoringSettings, as AuctionState) {
e.riskModel = riskModel
e.fpHorizons, e.bounds = computeBoundsAndHorizons(settings)
e.fpHorizons, e.bounds = computeBoundsAndHorizons(settings, as)
e.initialised = false
e.boundFactorsInitialised = false
e.priceRangesCache = make(map[int]priceRange, len(e.bounds)) // clear the cache
Expand All @@ -169,7 +169,7 @@ func NewMonitor(asset, mktID string, riskModel RangeProvider, auctionState Aucti
}

// Other functions depend on this sorting
horizons, bounds := computeBoundsAndHorizons(settings)
horizons, bounds := computeBoundsAndHorizons(settings, auctionState)

e := &Engine{
riskModel: riskModel,
Expand Down Expand Up @@ -525,7 +525,9 @@ func (e *Engine) noHistory() bool {
return len(e.pricesPast) == 0 && len(e.pricesNow) == 0
}

func computeBoundsAndHorizons(settings *types.PriceMonitoringSettings) (map[int64]num.Decimal, []*bound) {
func computeBoundsAndHorizons(settings *types.PriceMonitoringSettings, as AuctionState) (map[int64]num.Decimal, []*bound) {
// set bounds to inactive if we're in price monitoring auction
active := !as.IsPriceAuction()
parameters := make([]*types.PriceMonitoringTrigger, 0, len(settings.Parameters.Triggers))
for _, p := range settings.Parameters.Triggers {
p := *p
Expand All @@ -541,7 +543,7 @@ func computeBoundsAndHorizons(settings *types.PriceMonitoringSettings) (map[int6
bounds := make([]*bound, 0, len(parameters))
for _, p := range parameters {
bounds = append(bounds, &bound{
Active: true,
Active: active,
Trigger: p,
})
if _, ok := horizons[p.Horizon]; !ok {
Expand Down
Loading

0 comments on commit 03b90de

Please sign in to comment.