Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ac isolated margin #2054

Merged
merged 9 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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