From 438132a598a35d6aecbcbb8ac7ce57f0e26e5655 Mon Sep 17 00:00:00 2001 From: Jeremy Letang Date: Wed, 22 May 2024 10:11:54 +0200 Subject: [PATCH] Merge pull request #11305 from vegaprotocol/11304 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: Correctly verify pegged order offset with respect to tick size i… --- CHANGELOG.md | 1 + core/execution/future/market.go | 22 +++-- core/execution/spot/market.go | 20 ++-- .../features/orders/0037-OPEG-022.feature | 89 ++++++++++++++++++ .../spot/orders/0037-OPEG-023.feature | 91 +++++++++++++++++++ .../verified/special_orders_crossed.feature | 37 ++++++++ 6 files changed, 244 insertions(+), 16 deletions(-) create mode 100644 core/integration/features/orders/0037-OPEG-022.feature create mode 100644 core/integration/features/spot/orders/0037-OPEG-023.feature create mode 100644 core/integration/features/verified/special_orders_crossed.feature diff --git a/CHANGELOG.md b/CHANGELOG.md index 800bd42dce..13f952cd3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - [11293](https://github.com/vegaprotocol/vega/issues/11293) - Panic in data node with position estimate endpoint. - [11297](https://github.com/vegaprotocol/vega/issues/11297) - Handle properly asset decimals < market decimals when uncrossing the order book upon leaving auction. +- [11304](https://github.com/vegaprotocol/vega/issues/11304) - Correctly verify pegged order offset with respect to tick size in the right units. ## 0.76.3 diff --git a/core/execution/future/market.go b/core/execution/future/market.go index 90e28d6d3f..66829b7cf4 100644 --- a/core/execution/future/market.go +++ b/core/execution/future/market.go @@ -1374,26 +1374,30 @@ func (m *Market) getNewPeggedPrice(order *types.Order) (*num.Uint, error) { return num.UintZero(), common.ErrUnableToReprice } - offset, _ := num.UintFromDecimal(order.PeggedOrder.Offset.ToDecimal().Mul(m.priceFactor)) + // we're converting both offset and tick size to asset decimals so we can adjust the price (in asset) directly + priceInMarket, _ := num.UintFromDecimal(price.ToDecimal().Div(m.priceFactor)) if order.Side == types.SideSell { - price = price.AddSum(offset) + priceInMarket.AddSum(order.PeggedOrder.Offset) // this can only happen when pegged to mid, in which case we want to round to the nearest *better* tick size // but this can never cross the mid by construction as the the minimum offset is 1 tick size and all prices must be // whole multiples of tick size. - if mod := num.UintZero().Mod(price, m.mkt.TickSize); !mod.IsZero() { - price.Sub(price, mod) + if mod := num.UintZero().Mod(priceInMarket, m.mkt.TickSize); !mod.IsZero() { + priceInMarket.Sub(priceInMarket, mod) } + price, _ := num.UintFromDecimal(priceInMarket.ToDecimal().Mul(m.priceFactor)) + return price, nil } - if price.LTE(offset) { + if priceInMarket.LTE(order.PeggedOrder.Offset) { return num.UintZero(), common.ErrUnableToReprice } - price.Sub(price, offset) - if mod := num.UintZero().Mod(price, m.mkt.TickSize); !mod.IsZero() { - price = num.UintZero().Sub(price.AddSum(m.mkt.TickSize), mod) + priceInMarket.Sub(priceInMarket, order.PeggedOrder.Offset) + if mod := num.UintZero().Mod(priceInMarket, m.mkt.TickSize); !mod.IsZero() { + priceInMarket = num.UintZero().Sub(priceInMarket.AddSum(m.mkt.TickSize), mod) } + price, _ = num.UintFromDecimal(priceInMarket.ToDecimal().Mul(m.priceFactor)) return price, nil } @@ -1792,6 +1796,8 @@ func (m *Market) validateOrder(ctx context.Context, order *types.Order) (err err return nil } +// validateOrder checks that the order parameters are valid for the market. +// NB: price in market, tickSize in market decimals. func (m *Market) validateTickSize(price *num.Uint) error { d := num.UintZero().Mod(price, m.mkt.TickSize) if !d.IsZero() { diff --git a/core/execution/spot/market.go b/core/execution/spot/market.go index ac3e0e0cc1..2ffcee1620 100644 --- a/core/execution/spot/market.go +++ b/core/execution/spot/market.go @@ -819,26 +819,29 @@ func (m *Market) getNewPeggedPrice(order *types.Order) (*num.Uint, error) { return num.UintZero(), common.ErrUnableToReprice } - offset, _ := num.UintFromDecimal(order.PeggedOrder.Offset.ToDecimal().Mul(m.priceFactor)) + // we're converting both offset and tick size to asset decimals so we can adjust the price (in asset) directly + priceInMarket, _ := num.UintFromDecimal(price.ToDecimal().Div(m.priceFactor)) if order.Side == types.SideSell { - price = price.AddSum(offset) + priceInMarket.AddSum(order.PeggedOrder.Offset) // this can only happen when pegged to mid, in which case we want to round to the nearest *better* tick size // but this can never cross the mid by construction as the the minimum offset is 1 tick size and all prices must be // whole multiples of tick size. - if mod := num.UintZero().Mod(price, m.mkt.TickSize); !mod.IsZero() { - price.Sub(price, mod) + if mod := num.UintZero().Mod(priceInMarket, m.mkt.TickSize); !mod.IsZero() { + priceInMarket.Sub(priceInMarket, mod) } + price, _ := num.UintFromDecimal(priceInMarket.ToDecimal().Mul(m.priceFactor)) return price, nil } - if price.LTE(offset) { + if priceInMarket.LTE(order.PeggedOrder.Offset) { return num.UintZero(), common.ErrUnableToReprice } - price.Sub(price, offset) - if mod := num.UintZero().Mod(price, m.mkt.TickSize); !mod.IsZero() { - price = num.UintZero().Sub(price.AddSum(m.mkt.TickSize), mod) + priceInMarket.Sub(priceInMarket, order.PeggedOrder.Offset) + if mod := num.UintZero().Mod(priceInMarket, m.mkt.TickSize); !mod.IsZero() { + priceInMarket = num.UintZero().Sub(priceInMarket.AddSum(m.mkt.TickSize), mod) } + price, _ = num.UintFromDecimal(priceInMarket.ToDecimal().Mul(m.priceFactor)) return price, nil } @@ -971,6 +974,7 @@ func (m *Market) leaveAuction(ctx context.Context, now time.Time) { } // validateOrder checks that the order parameters are valid for the market. +// NB: price in market, tickSize in market decimals. func (m *Market) validateOrder(ctx context.Context, order *types.Order) (err error) { defer func() { if err != nil { diff --git a/core/integration/features/orders/0037-OPEG-022.feature b/core/integration/features/orders/0037-OPEG-022.feature new file mode 100644 index 0000000000..8d575324b2 --- /dev/null +++ b/core/integration/features/orders/0037-OPEG-022.feature @@ -0,0 +1,89 @@ + +Feature: 0001 tick size should be using market decimal, A pegged order specifying an offset which is not an integer multiple of the markets tick size should be rejected. + + Background: + Given the following network parameters are set: + | name | value | + | market.liquidity.bondPenaltyParameter | 1 | + | network.markPriceUpdateMaximumFrequency | 0s | + | limits.markets.maxPeggedOrders | 6 | + | validators.epoch.length | 5s | + | market.liquidity.earlyExitPenalty | 0.25 | + | market.liquidity.stakeToCcyVolume | 1.0 | + | market.liquidity.sla.nonPerformanceBondPenaltySlope | 0.19 | + | market.liquidity.sla.nonPerformanceBondPenaltyMax | 1 | + + And the liquidity monitoring parameters: + | name | triggering ratio | time window | scaling factor | + | lqm-params | 0.1 | 24h | 1 | + + And the following assets are registered: + | id | decimal places | + | ETH | 1 | + + And the average block duration is "1" + And the simple risk model named "simple-risk-model-1": + | long | short | max move up | min move down | probability of trading | + | 0.1 | 0.1 | 60 | 50 | 0.2 | + And the fees configuration named "fees-config-1": + | maker fee | infrastructure fee | + | 0.004 | 0.001 | + And the price monitoring named "price-monitoring-1": + | horizon | probability | auction extension | + | 1 | 0.99 | 5 | + And the liquidity sla params named "SLA": + | price range | commitment min time fraction | performance hysteresis epochs | sla competition factor | + | 0.01 | 0.5 | 1 | 1.0 | + + Scenario: + #0037-OPEG-022:Given a market with non-zero market and asset decimals where the asset decimals are strictly less than the market decimals (yielding a negative price factor). A pegged order specifying an offset which is not an integer multiple of the markets tick size should be rejected. + #0037-OPEG-025:Given a market with non-zero market and asset decimals where the asset decimals are equal to the market decimals (yielding a negative price factor). A pegged order specifying an offset which is not an integer multiple of the markets tick size should be rejected. + #0037-OPEG-026:Given a market with non-zero market and asset decimals where the asset decimals are strictly more than the market decimals (yielding a negative price factor). A pegged order specifying an offset which is not an integer multiple of the markets tick size should be rejected. + And the markets: + | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | decimal places | tick size | + | ETH/DEC21 | ETH | ETH | lqm-params | simple-risk-model-1 | default-margin-calculator | 1 | fees-config-1 | price-monitoring-1 | default-eth-for-future | 0.5 | 0 | SLA | 2 | 10 | + | ETH/DEC22 | ETH | ETH | lqm-params | simple-risk-model-1 | default-margin-calculator | 1 | fees-config-1 | price-monitoring-1 | default-eth-for-future | 0.5 | 0 | SLA | 2 | 5 | + | ETH/DEC23 | ETH | ETH | lqm-params | simple-risk-model-1 | default-margin-calculator | 1 | fees-config-1 | price-monitoring-1 | default-eth-for-future | 0.5 | 0 | SLA | 1 | 5 | + | ETH/DEC24 | ETH | ETH | lqm-params | simple-risk-model-1 | default-margin-calculator | 1 | fees-config-1 | price-monitoring-1 | default-eth-for-future | 0.5 | 0 | SLA | 0 | 10 | + And the parties deposit on asset's general account the following amount: + | party | asset | amount | + | party1 | ETH | 100000 | + | party3 | ETH | 1000000 | + | party4 | ETH | 1000000 | + And the average block duration is "1" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | error | + | party3 | ETH/DEC21 | buy | 100 | 101 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-1 | OrderError: price not in tick size | + | party3 | ETH/DEC21 | buy | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-1 | OrderError: price not in tick size | + | party4 | ETH/DEC21 | sell | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p4s2-1 | OrderError: price not in tick size | + | party4 | ETH/DEC21 | sell | 1000 | 191 | 0 | TYPE_LIMIT | TIF_GTC | p4s1-1 | OrderError: price not in tick size | + | party3 | ETH/DEC22 | buy | 100 | 101 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-2 | OrderError: price not in tick size | + | party3 | ETH/DEC22 | buy | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-2 | OrderError: price not in tick size | + | party4 | ETH/DEC22 | sell | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p4s2-2 | OrderError: price not in tick size | + | party4 | ETH/DEC22 | sell | 1000 | 191 | 0 | TYPE_LIMIT | TIF_GTC | p4s1-2 | OrderError: price not in tick size | + | party3 | ETH/DEC23 | buy | 100 | 101 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-3 | OrderError: price not in tick size | + | party3 | ETH/DEC23 | buy | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-3 | OrderError: price not in tick size | + | party4 | ETH/DEC23 | sell | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p4s2-3 | OrderError: price not in tick size | + | party4 | ETH/DEC23 | sell | 1000 | 191 | 0 | TYPE_LIMIT | TIF_GTC | p4s1-3 | OrderError: price not in tick size | + | party3 | ETH/DEC24 | buy | 100 | 101 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-4 | OrderError: price not in tick size | + | party3 | ETH/DEC24 | buy | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-4 | OrderError: price not in tick size | + | party4 | ETH/DEC24 | sell | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p4s2-4 | OrderError: price not in tick size | + | party4 | ETH/DEC24 | sell | 1000 | 191 | 0 | TYPE_LIMIT | TIF_GTC | p4s1-4 | OrderError: price not in tick size | + + Then the network moves ahead "2" blocks + And the trading mode should be "TRADING_MODE_OPENING_AUCTION" for the market "ETH/DEC21" + And the trading mode should be "TRADING_MODE_OPENING_AUCTION" for the market "ETH/DEC22" + And the trading mode should be "TRADING_MODE_OPENING_AUCTION" for the market "ETH/DEC23" + And the trading mode should be "TRADING_MODE_OPENING_AUCTION" for the market "ETH/DEC24" + + And the parties place the following pegged iceberg orders: + | party | market id | peak size | minimum visible size | side | pegged reference | volume | offset | reference | error | + | party1 | ETH/DEC21 | 10 | 5 | buy | MID | 10 | 10 | peg-buy-1 | | + | party1 | ETH/DEC21 | 10 | 5 | sell | MID | 20 | 20 | peg-buy-2 | | + | party1 | ETH/DEC21 | 10 | 5 | buy | MID | 20 | 100 | peg-buy-3 | | + | party1 | ETH/DEC21 | 10 | 5 | sell | MID | 20 | 2 | peg-buy-4 | OrderError: price not in tick size | + | party1 | ETH/DEC21 | 10 | 5 | buy | MID | 20 | 5 | peg-buy-5 | OrderError: price not in tick size | + | party1 | ETH/DEC22 | 10 | 5 | buy | MID | 20 | 15 | peg-buy-6 | | + | party1 | ETH/DEC23 | 10 | 5 | sell | MID | 20 | 6 | peg-buy-7 | OrderError: price not in tick size | + | party1 | ETH/DEC24 | 10 | 5 | buy | MID | 20 | 17 | peg-buy-8 | OrderError: price not in tick size | diff --git a/core/integration/features/spot/orders/0037-OPEG-023.feature b/core/integration/features/spot/orders/0037-OPEG-023.feature new file mode 100644 index 0000000000..71f64c9ce4 --- /dev/null +++ b/core/integration/features/spot/orders/0037-OPEG-023.feature @@ -0,0 +1,91 @@ + +Feature: 0001 tick size should be using market decimal, A pegged order specifying an offset which is not an integer multiple of the markets tick size should be rejected. + + Background: + Given the following network parameters are set: + | name | value | + | market.liquidity.bondPenaltyParameter | 1 | + | network.markPriceUpdateMaximumFrequency | 0s | + | limits.markets.maxPeggedOrders | 6 | + | validators.epoch.length | 5s | + | market.liquidity.earlyExitPenalty | 0.25 | + | market.liquidity.stakeToCcyVolume | 1.0 | + | market.liquidity.sla.nonPerformanceBondPenaltySlope | 0.19 | + | market.liquidity.sla.nonPerformanceBondPenaltyMax | 1 | + + And the liquidity monitoring parameters: + | name | triggering ratio | time window | scaling factor | + | lqm-params | 0.1 | 24h | 1 | + + And the following assets are registered: + | id | decimal places | + | ETH | 1 | + | BTC | 1 | + + And the average block duration is "1" + And the simple risk model named "simple-risk-model-1": + | long | short | max move up | min move down | probability of trading | + | 0.1 | 0.1 | 60 | 50 | 0.2 | + And the fees configuration named "fees-config-1": + | maker fee | infrastructure fee | + | 0 | 0 | + And the price monitoring named "price-monitoring-1": + | horizon | probability | auction extension | + | 1 | 0.99 | 5 | + And the liquidity sla params named "SLA": + | price range | commitment min time fraction | performance hysteresis epochs | sla competition factor | + | 0.01 | 0.5 | 1 | 1.0 | + + Scenario: + #0037-OPEG-023:Given a market with non-zero market and asset decimals where the asset decimals are strictly less than the market decimals (yielding a negative price factor). A pegged order specifying an offset which is not an integer multiple of the markets tick size should be rejected. + #0037-OPEG-024:Given a market with non-zero market and asset decimals where the asset decimals are equal to the market decimals (yielding a negative price factor). A pegged order specifying an offset which is not an integer multiple of the markets tick size should be rejected. + #0037-OPEG-027:Given a market with non-zero market and asset decimals where the asset decimals are strictly more than the market decimals (yielding a negative price factor). A pegged order specifying an offset which is not an integer multiple of the markets tick size should be rejected. + And the spot markets: + | id | name | quote asset | base asset | liquidity monitoring | risk model | auction duration | fees | price monitoring | sla params | decimal places | tick size | + | ETH/DEC21 | BTC/ETH | BTC | ETH | lqm-params | simple-risk-model-1 | 1 | fees-config-1 | price-monitoring-1 | default-basic | 2 | 10 | + | ETH/DEC22 | BTC/ETH | BTC | ETH | lqm-params | simple-risk-model-1 | 1 | fees-config-1 | price-monitoring-1 | default-basic | 2 | 5 | + | ETH/DEC23 | BTC/ETH | BTC | ETH | lqm-params | simple-risk-model-1 | 1 | fees-config-1 | price-monitoring-1 | default-basic | 1 | 5 | + | ETH/DEC24 | BTC/ETH | BTC | ETH | lqm-params | simple-risk-model-1 | 1 | fees-config-1 | price-monitoring-1 | default-basic | 0 | 10 | + And the parties deposit on asset's general account the following amount: + | party | asset | amount | + | party1 | ETH | 1000000000000 | + | party1 | BTC | 1000 | + | party3 | ETH | 1000000 | + | party4 | ETH | 1000000 | + And the average block duration is "1" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | error | + | party3 | ETH/DEC21 | buy | 100 | 101 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-1 | OrderError: price not in tick size | + | party3 | ETH/DEC21 | buy | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-1 | OrderError: price not in tick size | + | party4 | ETH/DEC21 | sell | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p4s2-1 | OrderError: price not in tick size | + | party4 | ETH/DEC21 | sell | 1000 | 191 | 0 | TYPE_LIMIT | TIF_GTC | p4s1-1 | OrderError: price not in tick size | + | party3 | ETH/DEC22 | buy | 100 | 101 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-2 | OrderError: price not in tick size | + | party3 | ETH/DEC22 | buy | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-2 | OrderError: price not in tick size | + | party4 | ETH/DEC22 | sell | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p4s2-2 | OrderError: price not in tick size | + | party4 | ETH/DEC22 | sell | 1000 | 191 | 0 | TYPE_LIMIT | TIF_GTC | p4s1-2 | OrderError: price not in tick size | + | party3 | ETH/DEC23 | buy | 100 | 101 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-3 | OrderError: price not in tick size | + | party3 | ETH/DEC23 | buy | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-3 | OrderError: price not in tick size | + | party4 | ETH/DEC23 | sell | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p4s2-3 | OrderError: price not in tick size | + | party4 | ETH/DEC23 | sell | 1000 | 191 | 0 | TYPE_LIMIT | TIF_GTC | p4s1-3 | OrderError: price not in tick size | + | party3 | ETH/DEC24 | buy | 100 | 101 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-4 | OrderError: price not in tick size | + | party3 | ETH/DEC24 | buy | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-4 | OrderError: price not in tick size | + | party4 | ETH/DEC24 | sell | 10 | 111 | 0 | TYPE_LIMIT | TIF_GTC | p4s2-4 | OrderError: price not in tick size | + | party4 | ETH/DEC24 | sell | 1000 | 191 | 0 | TYPE_LIMIT | TIF_GTC | p4s1-4 | OrderError: price not in tick size | + + Then the network moves ahead "2" blocks + And the trading mode should be "TRADING_MODE_OPENING_AUCTION" for the market "ETH/DEC21" + And the trading mode should be "TRADING_MODE_OPENING_AUCTION" for the market "ETH/DEC22" + And the trading mode should be "TRADING_MODE_OPENING_AUCTION" for the market "ETH/DEC23" + And the trading mode should be "TRADING_MODE_OPENING_AUCTION" for the market "ETH/DEC24" + + And the parties place the following pegged iceberg orders: + | party | market id | peak size | minimum visible size | side | pegged reference | volume | offset | reference | error | + | party1 | ETH/DEC21 | 10 | 5 | buy | MID | 10 | 10 | peg-buy-1 | | + | party1 | ETH/DEC21 | 10 | 5 | sell | MID | 20 | 20 | peg-buy-2 | | + | party1 | ETH/DEC21 | 10 | 5 | buy | MID | 20 | 100 | peg-buy-3 | | + | party1 | ETH/DEC21 | 10 | 5 | sell | MID | 20 | 2 | peg-buy-4 | OrderError: price not in tick size | + | party1 | ETH/DEC21 | 10 | 5 | buy | MID | 20 | 5 | peg-buy-5 | OrderError: price not in tick size | + | party1 | ETH/DEC22 | 10 | 5 | buy | MID | 20 | 15 | peg-buy-6 | | + | party1 | ETH/DEC23 | 10 | 5 | sell | MID | 20 | 6 | peg-buy-7 | OrderError: price not in tick size | + | party1 | ETH/DEC24 | 10 | 5 | buy | MID | 20 | 17 | peg-buy-8 | OrderError: price not in tick size | diff --git a/core/integration/features/verified/special_orders_crossed.feature b/core/integration/features/verified/special_orders_crossed.feature new file mode 100644 index 0000000000..1d0cced078 --- /dev/null +++ b/core/integration/features/verified/special_orders_crossed.feature @@ -0,0 +1,37 @@ + +Feature: Issue: re submit special order would cross + + Background: + + Given the average block duration is "1" + And the following assets are registered: + | id | decimal places | + | ETH | 1 | + And the following network parameters are set: + | name | value | + | limits.markets.maxPeggedOrders | 6 | + + Given the markets: + | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | decimal places | tick size | + | ETH/DEC21 | ETH | ETH | default-parameters | default-simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.5 | 0 | default-basic | 2 | 10 | + And the parties deposit on asset's general account the following amount: + | party | asset | amount | + | aux1 | ETH | 1000000000000 | + | aux2 | ETH | 1000000000000 | + | party1 | ETH | 1000000000000 | + | party2 | ETH | 1000000000000 | + + Scenario: + + Given the parties place the following pegged iceberg orders: + | party | market id | peak size | minimum visible size | side | pegged reference | volume | offset | reference | error | + | party1 | ETH/DEC21 | 10 | 5 | buy | MID | 10 | 10 | peg-buy-1 | | + | party2 | ETH/DEC21 | 10 | 5 | sell | MID | 10 | 10 | peg-buy-2 | | + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | aux1 | ETH/DEC21 | buy | 1 | 1000 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-1 | + | aux1 | ETH/DEC21 | buy | 1 | 1000 | 0 | TYPE_LIMIT | TIF_GTC | p3b1-1 | + | aux2 | ETH/DEC21 | sell | 1 | 1000 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-1 | + | aux2 | ETH/DEC21 | sell | 1 | 1010 | 0 | TYPE_LIMIT | TIF_GTC | p3b2-1 | + When the opening auction period ends for market "ETH/DEC21" + Then the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "ETH/DEC21" \ No newline at end of file