Skip to content

Commit

Permalink
Merge pull request #11567 from vegaprotocol/8777-stop-order-changes
Browse files Browse the repository at this point in the history
feat: change behaviour of stop orders
  • Loading branch information
EVODelavega authored Aug 13, 2024
2 parents f2ad5d3 + 80306d1 commit cbb9d89
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 39 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### 🚨 Breaking changes

- [](https://github.com/vegaprotocol/vega/issues/xxx)
- [8777](https://github.com/vegaprotocol/vega/issues/8777) - Stop orders can now be used to create or increase a position.

### 🗑️ Deprecation

Expand Down
34 changes: 2 additions & 32 deletions core/execution/future/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -2141,43 +2141,13 @@ func (m *Market) SubmitStopOrdersWithIDGeneratorAndOrderIDs(
}

// now check for the parties position
positions := m.position.GetPositionsByParty(party)
if len(positions) > 1 {
if positions := m.position.GetPositionsByParty(party); len(positions) > 1 {
m.log.Panic("only one position expected", logging.Int("got", len(positions)))
}

if len(positions) < 1 {
} else if len(positions) < 1 {
rejectStopOrders(types.StopOrderRejectionNotAllowedWithoutAPosition, fallsBelow, risesAbove)
return nil, common.ErrStopOrderSubmissionNotAllowedWithoutExistingPosition
}

pos := positions[0]

// now we will reject if the direction of order if is not
// going to close the position or potential position
potentialSize := pos.Size() - pos.Sell() + pos.Buy()
size := pos.Size()

var stopOrderSide types.Side
if fallsBelow != nil {
stopOrderSide = fallsBelow.OrderSubmission.Side
} else {
stopOrderSide = risesAbove.OrderSubmission.Side
}

switch stopOrderSide {
case types.SideBuy:
if potentialSize >= 0 && size >= 0 {
rejectStopOrders(types.StopOrderRejectionNotClosingThePosition, fallsBelow, risesAbove)
return nil, common.ErrStopOrderSideNotClosingThePosition
}
case types.SideSell:
if potentialSize <= 0 && size <= 0 {
rejectStopOrders(types.StopOrderRejectionNotClosingThePosition, fallsBelow, risesAbove)
return nil, common.ErrStopOrderSideNotClosingThePosition
}
}

fallsBelowTriggered, risesAboveTriggered := m.stopOrderWouldTriggerAtSubmission(fallsBelow),
m.stopOrderWouldTriggerAtSubmission(risesAbove)
triggered := fallsBelowTriggered || risesAboveTriggered
Expand Down
74 changes: 68 additions & 6 deletions core/integration/features/orders/stoporders.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1885,8 +1885,7 @@ Feature: stop orders
| party2 | ETH/DEC19 | STATUS_EXPIRED | stop2-1 |


Scenario: A party with a long position cannot enter a buy stop order,
and a party with a short position cannot enter a sell stop order. (0014-ORDT-137)
Scenario: A party with a long or short position CAN increase their position with stop orders. (0014-ORDT-137)

# setup accounts
Given time is updated to "2019-11-30T00:00:00Z"
Expand Down Expand Up @@ -1933,14 +1932,77 @@ Feature: stop orders

# We should not be able to place a but stop order for party2 as they have a long position and it would make it more long
When the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | only | ra price trigger | fb price trigger | reference | error |
| party2 | ETH/DEC19 | buy | 1 | 0 | 0 | TYPE_MARKET | TIF_IOC | reduce | 75 | 25 | stop | side used in stop order does not close the position |
| party | market id | side | volume | price | resulting trades | type | tif | only | ra price trigger | fb price trigger | reference | error |
| party2 | ETH/DEC19 | buy | 1 | 0 | 0 | TYPE_MARKET | TIF_IOC | reduce | 75 | 25 | stop | |

# We should not be able to place a sell stop order for party1 as they have a short position and it would make it more short
When the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | only | ra price trigger | fb price trigger | reference | error |
| party1 | ETH/DEC19 | sell | 1 | 0 | 0 | TYPE_MARKET | TIF_IOC | reduce | 75 | 25 | stop | side used in stop order does not close the position |
| party | market id | side | volume | price | resulting trades | type | tif | only | ra price trigger | fb price trigger | reference | error |
| party1 | ETH/DEC19 | sell | 1 | 0 | 0 | TYPE_MARKET | TIF_IOC | reduce | 75 | 25 | stop | |

Scenario: A party with a long position cannot flip to short by placing a stop order.
Given time is updated to "2019-11-30T00:00:00Z"
And the parties deposit on asset's general account the following amount:
| party | asset | amount |
| party1 | BTC | 10000000 |
| party2 | BTC | 10000000 |
| party3 | BTC | 10000000 |
| aux | BTC | 10000000 |
| aux2 | BTC | 10000000 |
| aux3 | BTC | 100000 |
| lpprov | BTC | 90000000 |

And the parties submit the following liquidity provision:
| id | party | market id | commitment amount | fee | lp type |
| lp1 | lpprov | ETH/DEC19 | 90000000 | 0.1 | submission |
| lp1 | lpprov | ETH/DEC19 | 90000000 | 0.1 | submission |
And the parties place the following pegged iceberg orders:
| party | market id | peak size | minimum visible size | side | pegged reference | volume | offset |
| lpprov | ETH/DEC19 | 2 | 1 | buy | BID | 50 | 100 |
| lpprov | ETH/DEC19 | 2 | 1 | sell | ASK | 50 | 100 |

# place auxiliary orders so we always have best bid and best offer as to not trigger the liquidity auction
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| aux | ETH/DEC19 | buy | 100 | 1 | 0 | TYPE_LIMIT | TIF_GTC |
| aux | ETH/DEC19 | sell | 100 | 10001 | 0 | TYPE_LIMIT | TIF_GTC |
| aux2 | ETH/DEC19 | buy | 5 | 50 | 0 | TYPE_LIMIT | TIF_GTC |
| aux3 | ETH/DEC19 | sell | 5 | 50 | 0 | TYPE_LIMIT | TIF_GTC |

When the opening auction period ends for market "ETH/DEC19"
Then the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "ETH/DEC19"

When the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| party1 | ETH/DEC19 | sell | 10 | 50 | 0 | TYPE_LIMIT | TIF_GTC |
| party2 | ETH/DEC19 | buy | 10 | 50 | 1 | TYPE_LIMIT | TIF_GTC |
Then the following trades should be executed:
| buyer | seller | price | size |
| party2 | party1 | 50 | 10 |

When the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| party1 | ETH/DEC19 | sell | 1 | 75 | 0 | TYPE_LIMIT | TIF_GTC |
| party3 | ETH/DEC19 | buy | 50 | 75 | 1 | TYPE_LIMIT | TIF_GTC |
And the network moves ahead "1" blocks
Then the following trades should be executed:
| buyer | seller | price | size |
| party3 | party1 | 75 | 1 |

When the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | only | ra price trigger | fb price trigger | reference | error |
| party2 | ETH/DEC19 | sell | 20 | 0 | 1 | TYPE_MARKET | TIF_IOC | reduce | 75 | 25 | stop | |
Then the following trades should be executed:
| buyer | seller | price | size |
| party3 | party2 | 75 | 10 |

# Ensure the party has closed its position, despite the stop order being for a larger volume than their open position.
When the network moves ahead "1" blocks
Then the parties should have the following profit and loss:
| party | volume | unrealised pnl | realised pnl |
| party1 | -11 | -250 | 0 |
| party2 | 0 | 0 | 250 |
| party3 | 11 | 0 | 0 |

Scenario: If a stop order is placed with a position_fraction equal to 0.5 and the position
size is 5 then the rounding should be equal to 3 (0014-ORDT-138)
Expand Down

0 comments on commit cbb9d89

Please sign in to comment.