Skip to content

Commit

Permalink
Merge pull request #2054 from vegaprotocol/ac-isolated-margin
Browse files Browse the repository at this point in the history
Ac isolated margin
  • Loading branch information
Jiajia-Cui authored Nov 15, 2023
2 parents 80449cb + 0b3c9c8 commit f759388
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 3 deletions.
104 changes: 102 additions & 2 deletions protocol/0019-MCAL-margin_calculator.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Margin Calculator

## Acceptance Criteria
## Acceptance Criteria (under Cross-margin modes)

- Get four margin levels for one or more parties (<a name="0019-MCAL-001" href="#0019-MCAL-001">0019-MCAL-001</a>)

Expand Down Expand Up @@ -82,6 +82,107 @@
- Thus, with `margin funding factor = 0.5`, `total margin requirement = futures margin + funding margin = 5565 + 0.5 * max(0, -90 * 1) = 5565` (<a name="0019-MCAL-028" href="#0019-MCAL-028">0019-MCAL-028</a>)
- However is position is instead `-1`, with the same margin requirement, if `margin funding factor = 0.5`, `total margin requirement = futures margin + funding margin = 5565 + 0.5 * max(0, -90 * -1) = 5610`(<a name="0019-MCAL-029" href="#0019-MCAL-029">0019-MCAL-029</a>)
## Acceptance Criteria (under Isolated-margin modes)
- If a party has a newly created short position of `1` and the mark price is `15 900` and `market.linearSlippageFactor = 0.25`, `RF short = 0.1` and `Initial margin factor = 1.5` and order book is
```book
buy 1 @ 15 000
buy 10 @ 14 900
and
sell 1 @ 100 000
sell 10 @ 100 100
```
then the maintenance margin (under cross-margin mode) for the party is `min(1 x (100000-15900), 15900 x 0.25 x 1) + 0.1 x 1 x 15900 = 5565`, and margin account should have initial margin level which is `5565 x 1.5 = 8348`.
when switching to isolated-margin mode and the `margin factor short = 0.3`, the maintenance margin should be updated to `average entry price x current position x new margin factor = 57500 x 1 x 0.3 = 17250`, and margin account should be updated to `17250`. (<a name="0019-MCAL-031" href="#0019-MCAL-031">0019-MCAL-031</a>)
when switching to isolated-margin mode and the `margin factor short = 0.11`, the maintenance margin should be updated to `average entry price x current position x new margin factor = 57500 x 1 x 0.11 = 6325`, the switching will be rejected. (<a name="0019-MCAL-032" href="#0019-MCAL-032">0019-MCAL-032</a>)
when switching to isolated-margin mode and the `margin factor short = 0.3`, the maintenance margin should be updated to `average entry price x current position x new margin factor = 57500 x 1 x 0.3 = 17250`, and margin account should be updated to `17250`. (<a name="0019-MCAL-033" href="#0019-MCAL-033">0019-MCAL-033</a>)
- When the party place a new short order of `1` with price `15000`, and the market is in continuous trading.
The margin account should have additional amount `average entry price x current position x new margin factor = 59524 x 1 x 0.3 = 17857` added if the party has enough asset in the general account(<a name="0019-MCAL-034" href="#0019-MCAL-034">0019-MCAL-034</a>)
The order will be rejected if the party does not have enough asset in the general account (<a name="0019-MCAL-035" href="#0019-MCAL-035">0019-MCAL-035</a>)
- When the party place a new short order of `1` with price `45000`, and the market is in continuous trading.
The margin account should have additional amount `limit price * size * margin factor = 45000 x 1 x 0.3 = 13500` added if the party has enough asset in the general account(<a name="0019-MCAL-036" href="#0019-MCAL-036">0019-MCAL-036</a>)
The order will be rejected if the party does not have enough asset in the general account(<a name="0019-MCAL-037" href="#0019-MCAL-037">0019-MCAL-037</a>)
- When the party place a new long order of `1` with price `145000` and the party has existing short position of `3`, and the market is in continuous trading. The margin account should not change(<a name="0019-MCAL-038" href="#0019-MCAL-038">0019-MCAL-038</a>)
- When the party place a new long order of `10` with price `145000` and the party has existing short position of `3`, and the market is in continuous trading. The margin account should have additional amount `limit price * size * margin factor = 145000 x (10-3) x 0.3 = 304500` added if the party has enough asset in the general account(<a name="0019-MCAL-039" href="#0019-MCAL-039">0019-MCAL-039</a>)
- Margin levels are correctly calculated in the case of an open position dropping below maintenance margin levels active orders will remain active as these are margined separately and will not be cancelled.(<a name="0019-MCAL-040" href="#0019-MCAL-040">0019-MCAL-040</a>)
- Zero position and zero orders results in all zero margin levels. (<a name="0019-MCAL-041" href="#0019-MCAL-041">0019-MCAL-041</a>)
- If a trader has a long position and there are no bids on the order book, the `exit price` is equal to infinity and hence the slippage cap is used as the slippage component of the margin calculation. (<a name="0019-MCAL-042" href="#0019-MCAL-042">0019-MCAL-042</a>)
- If a trader's `long position > 0 && 0 < *sum of volume of order book bids* < long position`, the `exit price` is equal to infinity. (<a name="0019-MCAL-043" href="#0019-MCAL-043">0019-MCAL-043</a>)
- If a trader's `short position < 0 && 0 < *sum of absolute volume of order book offers* < short position`, the `exit price` is equal to infinity. (<a name="0019-MCAL-044" href="#0019-MCAL-044">0019-MCAL-044</a>)
- If a trader's `long position > 0 && long position < *sum of volume of order book bids*`, the `exit price` is equal to the *volume weighted price of the order book bids* with cumulative volume equal to the riskiest long, starting from best bid. (<a name="0019-MCAL-045" href="#0019-MCAL-045">0019-MCAL-045</a>)
- If a trader's `short position < 0 && 0 < abs(short position) < *sum of absolute volume of order book offers*`, the `exit price` is equal to the *volume weighted price of the order book offers*. (<a name="0019-MCAL-046" href="#0019-MCAL-046">0019-MCAL-046</a>)
- A feature test that checks margin in case market PDP > 0 is created and passes. (<a name="0019-MCAL-047" href="#0019-MCAL-047">0019-MCAL-047</a>)
- A feature test that checks margin in case market PDP < 0 is created and passes. (<a name="0019-MCAL-057" href="#0019-MCAL-057">0019-MCAL-057</a>)
- For each market and each party which has either orders or positions on the market, the API provides the maintenance margin levels. (<a name="0019-MCAL-049" href="#0019-MCAL-049">0019-MCAL-049</a>)
- In the same situation as above, if `market.linearSlippageFactor = 100`, (i.e. 10 000%) instead, then the margin for the party is `min(1 x (100000-15900), 15900 x 100 x 1) + 0.1 x 1 x 15900 = 85690`. (<a name="0019-MCAL-051" href="#0019-MCAL-051">0019-MCAL-051</a>)
- If the `market.linearSlippageFactor` is updated via governance then it will be used at the next margin evaluation i.e. at the first mark price update following the parameter update. (<a name="0019-MCAL-052" href="#0019-MCAL-052">0019-MCAL-052</a>)
- For a perpetual future market, the maintenance margin is equal to the maintenance margin on an equivalent dated future market, plus a component related to the expected upcoming margin funding payment. Specifically:
- If a party is long `1` unit and the mark price is `15 900` and `market.linearSlippageFactor = 0.25` and `RF long = 0.1` and order book is
```book
buy 1 @ 15 000
buy 10 @ 14 900
and
sell 1 @ 100 000
sell 10 @ 100 100
```
then the dated future maintenance margin component for the party is `min(1 x (100000-15900), 15900 x 0.25 x 1) + 0.1 x 1 x 15900 = 5565`. The current accrued funding payment for the perpetual component is calculated using
```book
delta_t = funding_period_end - max(funding_period_start, internal_data_points[0].t)
funding_payment = f_twap - s_twap + min(clamp_upper_bound*s_twap,max(clamp_lower_bound*s_twap, (1 + delta_t * interest_rate)*s_twap-f_twap))
```
Where `f_twap` represents the internal mark price TWAP and `s_twap` represents the TWAP from the external oracle feed. When clamp bounds are large we use:
```book
funding_payment = f_twap - s_twap + (1 + delta_t * interest_rate)*s_twap-f_twap
= s_twap * delta_t * interest_rate
```
- If `s_twap = 1600`, `delta_t = 0.002` and `interest_rate = 0.05` then `funding_payment = 1600 * 0.002 * 0.05 = 0.16`.
- Thus, if `margin funding factor = 0.5`, `total margin requirement = futures margin + funding margin = 5565 + 0.5 * 0.16 * 1 = 5565.08` (<a name="0019-MCAL-053" href="#0019-MCAL-053">0019-MCAL-053</a>)
- If instead
- `clamp_upper_bound*s_twap < max(clamp_lower_bound*s_twap, (1 + delta_t * interest_rate)*s_twap-f_twap)`
- `funding payment = f_twap - s_twap + clamp_upper_bound*s_twap = f_twap + s_twap * (clamp_upper_bound - 1)`.
- Then with `s_twap = 1600`, `clamp_upper_bound = 0.05` and `f_twap = 1550`, `funding_payment = 1590 + 1600 * (0.05 - 1) = 1590 - 1520 = 70`
- Thus, with `margin funding factor = 0.5`, `total margin requirement = futures margin + funding margin = 5565 + 0.5 * 70 * 1 = 5600` (<a name="0019-MCAL-058" href="#0019-MCAL-058">0019-MCAL-058</a>)
- However is position is instead `-1`, with the same margin requirement, if `margin funding factor = 0.5`, `total margin requirement = futures margin + funding margin = 5565 + 0.5 * max(0, 70 * -1) = 5565`(<a name="0019-MCAL-054" href="#0019-MCAL-054">0019-MCAL-054</a>)
- If instead
- `clamp_upper_bound*s_twap > clamp_lower_bound*s_twap > (1 + delta_t * interest_rate)*s_twap-f_twap)`
- `funding payment = f_twap - s_twap + clamp_lower_bound*s_twap = f_twap + s_twap * (clamp_lower_bound - 1)`.
- Then with `s_twap = 1600`, `clamp_lower_bound = -0.05` and `f_twap = 1550`, `funding_payment = 1590 + 1600 * (-0.05 - 1) = 1590 - 1680 = -90`
- Thus, with `margin funding factor = 0.5`, `total margin requirement = futures margin + funding margin = 5565 + 0.5 * max(0, -90 * 1) = 5565` (<a name="0019-MCAL-055" href="#0019-MCAL-055">0019-MCAL-055</a>)
- However is position is instead `-1`, with the same margin requirement, if `margin funding factor = 0.5`, `total margin requirement = futures margin + funding margin = 5565 + 0.5 * max(0, -90 * -1) = 5610`(<a name="0019-MCAL-056" href="#0019-MCAL-056">0019-MCAL-056</a>)
## Summary
The *margin calculator* returns the set of margin levels for a given *actual position*, along with the amount of additional margin (if any) required to support the party's *potential position* (i.e. active orders including any that are parked/untriggered/undeployed).
Expand Down Expand Up @@ -494,4 +595,3 @@ riskiest short: -1
## SCENARIOS

Scenarios found [here](https://docs.google.com/spreadsheets/d/1VXMdpgyyA9jp0hoWcIQTUFrhOdtu-fak/edit#gid=1586131462)

29 changes: 28 additions & 1 deletion protocol/features.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,34 @@
},
"Margin isolation": {
"milestone": "palazzo",
"acs": []
"acs": [
"0019-MCAL-031",
"0019-MCAL-032",
"0019-MCAL-033",
"0019-MCAL-034",
"0019-MCAL-035",
"0019-MCAL-036",
"0019-MCAL-037",
"0019-MCAL-038",
"0019-MCAL-039",
"0019-MCAL-040",
"0019-MCAL-041",
"0019-MCAL-042",
"0019-MCAL-043",
"0019-MCAL-044",
"0019-MCAL-045",
"0019-MCAL-046",
"0019-MCAL-047",
"0019-MCAL-049",
"0019-MCAL-051",
"0019-MCAL-052",
"0019-MCAL-053",
"0019-MCAL-054",
"0019-MCAL-055",
"0019-MCAL-056",
"0019-MCAL-057",
"0019-MCAL-058"
]
},
"Quadratic slippage removal": {
"milestone": "palazzo",
Expand Down

0 comments on commit f759388

Please sign in to comment.