Markets
This document specifies nord’s market types and their respective behaviour, along with some implementation notes. It is designed to be readable by anyone with limited knowledge of financial markets, but with a strong technical background. Links to external resources are provided where appropriate.
Nord provides spot trading, perpetual futures trading, and spot lending.
To limit risk, a margining system is defined to limit the risk a user
may take on. To simplify margining, all prices are quoted (i.e.
denominated) in the same asset, which we chose to be USDC. In the
implementation, the first token, with token_id == 0, is
the denominator.
Open questions
Do we need to define a dust threshold?
We can define a “dust threshold” for assets, where below a certain amount the asset is considered to have amount 0. We defined this in the past to deal with certain edge cases around bankruptcy, but don’t recall the rationale.
Do we need to define position open notional for spot markets?
This depends on if we want to limit open orders given a certain amount of assets and if we allow spot trades to create borrows.
Is it possible to pay and charge interest additively?
Multiplicative interest payments cause some amount of loss of precision. Granted, the difference is negligible, but may open a possible loss of funds vector.
Do we adjust margin fractions for small cap coins?
We can apply the following to deal with small market caps. Similarly for CMF, MMF.
Definitions
For the purposes of this document specific representations are used. Implementation may choose to diverge.
Position size
The number of owned contracts for a given perpetuals market. May be a fractional amount. A short position is defined as a negative position size.
Fill size
The size of the fill when orders are matched. The size is defined to be negative for the side selling.
Iverson bracket
We sometimes use the Iverson bracket , where if is true, and otherwise.
Tokens
Prior to trading, a user must first deposit tokens in the form of tokenized financial assets such as USDC and ETH. The token is deposited into the vault and the user’s token amount is increased by the same amount. Similarly for withdrawals.
Parameters
weight
A number in defining the contribution of this token to the overall account value. The weight is used to deal with certain asset types having high volatility or low liquidity.
For example, suppose BTC has weight 0.9 and USD price 1000 USD/BTC. If
a user deposits 1 BTC, then their account value increases by
0.9 * 1 BTC * 1000 BTC/USD = 900 USD.
token decimals
The decimal shift for the smallest possible denomination
of this asset type. This allows deposit and withdrawals
to be defined in terms of integers. The original value is
recovered by dividing the amount by 10 ** token decimals.
For USDC, this might be set to 6. If a user wants to deposit 1 USDC,
they would set the deposit amount to 1_000_000. Note that the shifted
amount doesn’t have to be the fraction currency for the asset, such as
cents for USD. For example, for ETH, we may choose a token decimals value of
8 instead of the intelligently chosen default of 18 to prevent
overflows.
max rate
The maximum interest rate for borrows of this token.
optimal rate
The optimal interest rate, beyond which the rate sharply increases to the max rate.
optimal utilization
The optimal utilization, where utilization is the ratio of total borrow to total supply.
origination fee
Percentage fee charged for borrows. Suppose amount is borrowed. Then a fee of is moved to the accrued fee vault when the borrow occurs. The final borrowed amount is then .
liq fee
Fee charged for having a spot borrow of this asset type be liquidated.
Borrowing
Tokens may also be borrowed against other, positive token. All positive token is implicitly lent and gains interest. Limits for borrows are defined by the margining system explained further below. Here, we define how lending and borrowing interest rates are computed. We first define the utilization as the fraction of borrows for the supply for a given token type. In other words,
Given the token metaparameters defined above, the yearly interest rate is given by
The paid and charged interest are tracked lazily through the supply multiplier and borrow multiplier. Let be the period, the borrow multiplier at time , and the supply multiplier at time .
To apply the borrow and supply multipliers, the asset amounts by the borrow and supply multipliers to reflect the interest.
Markets
Index price
Index price provided by oracle is not a single scalar value but rather a probabilistic one.
Oracle collects prices for an asset from several values which leads to the final index price
being expressed as median price Pm and confidence interval C,
such that actual index price falls within [Pm-C; Pm+C] interval with 95% probability.
For more details, see Confidence intervals .
Computations which use index price prefer its “conservative” value, i.e. reduce positive values obtained with its use and increase negative ones. This way we’re more sure that we don’t overestimate factors like account health or funding rates.
Different kinds of index price are marked below as follows:
- median index price:
- lower-bound index price:
- upper-bound index price:
Parameters
These definitions apply to both spot markets and perp markets.
size decimals
Similar to token decimals, but applied to sizes. Can be interpreted
as the of the lot size of this market, where the lot size may only
be a power of 10.
tick decimals
Similar to token decimals, but applied to all prices. Note that
we use tick decimals and not a tick size, so tick sizes are limited to
powers of 10.
example decimals
Let have 1 ETH. 1 ETH on balance represented by . 1 ETH on orderbook represented by .
So we if want to find out number representing same ETH amount on balance and on orderbook (or position), we will get:
which gives us way to convert one value into other.
Here is some examples of used conversions:
| from\to | base_size | base_amount | quote_size | quote_amount |
|---|---|---|---|---|
| base size | self | self / 10^size_decimals | self * price mantissa | quote_size / 10^(size_decimals + price_decimals) |
| token balance | self * 10^size_decimals / 10^token_decimals |
where amount is real number which humans usually expect to see
maker fee
Fee charged to an order maker on trades by the exchange. A typical value is 2 bps, or 0.02%.
taker fee
Fee charged to an order taker on trades by the exchange. A typical value is 5 bps, or 0.05%.
liq fee
Fee charged for having a position on this perp market be liquidated.
withdrawal fee
Withdrawing balance from app takes amount of token equivalent to amount configured in USDC. For token to be withdrawable it should have price to be available.
Spot
Spot trading can be used to trade non-USDC assets for USDC, and vice versa. Unlike perps, there isn’t a notion of reduce only orders nor of position. Trades only lead to user assets being swapped.
Perpetual futures
What are perpetual futures?
Perpetual futures, colloquially perps, are a financial derivative designed to closely track the underlying’s price. In other words, 1 perp contract on ETHUSD will have a USD price close to that of 1 ETH.
For those familiar with regular futures, the idea is similar. Users deposit an initial margin and maintain it above a maintenance margin. The primary difference is the settlement is paid hourly and the future has no maturity. Perps are thus solely for speculative purposes and provide no inherent utility.
Why trade perps instead of the underlying?
Gaining leverage
Derivatives allow users to gain leverage, sometimes up to 20 times. For example, if a trader is 10x leveraged, then a 3% loss in BTCUSD will cause the trader to incur a 30% loss.
The exchange protects itself by defining a liquidation protocol. If a trader is close to wiping out their token, then the user is forced to close positions. The margining system is outlined further below.
Simplifying shorting
Shorting in spot markets requires the trader to first borrow an asset and then sell it. In perp markets, a short simply corresponds to a negative position.
Trading illiquid assets
Perps allow a trader to gain exposure to the underlying without having to own it. This makes perps great for illiquid assets. In fact this is what perps were originally designed for .
Perpetual Futures Fills
Users earns by trading taking and trading their positions. Let . On trades we perform the following updates:
Notice that the total sum of PnL and position sizes must sum to zero, i.e. and . In practice, there may be a small non-zero amount, though this should always be in favour of the exchange to prevent a possible loss of funds vector. Updates to PnL is mutually exclusive with updates to open price and position size.
Funding
For a given perp market, we define the mark price as
The “one sided multiplier” can be chosen arbitrarily and is used to incentivize placing orders on the empty side. We hardcode it to 1%. The mark price is kept close to the median index price through the use of funding. We define the funding rate as
For notational simplicity, we define short positions as simply having a negative position and fill size of sell to be negative too, although implementations may choose to do so differently.
For perp market:
We define current funding index to be
The funding payment is done every hour (update interval), computed by
Unfortunately, iterating through all accounts to pay funding can be expensive. To alleviate this problem, we can pay funding lazily. We introduce the concept of unsettled funding to refer to funding that has not been paid out yet, and settled funding to denote the total amount of funding paid out so far.
The funding index is adjusted on funding rate updates. The user funding index updated on user funding payments and position updates.
When the position is closed, change to user position calculated as:
where use stored on last position update.
Funding index updated with:
Summary
- if during update interval, grows, lead to grow, hence long positions pay short positions
- if during update interval, shorts pay long
- funding rate is interest payed to incentivize mid point mark price to become close to index price
- all spot user’s unfilled positions and balances are collateral quoted in USD
- index price expressed in USDC, and relevant USD/USDC transformation is done to handle difference with risk
- if positive position size reduced toward 0, and price increased since open, user balance increased
- if negative position size increased toward zero, and price decreased since open, user balance increased
Margining
The margining system is defined to limit the amount of risk a given user
can take on. Over-leveraged users are liquidated by the exchange, i.e.
their orders are cancelled and positions are reduced, and possibly closed, until the user is aptly
leveraged. This is to limit the exchange’s exposure to risk as a result
of aggressive leverage. Liquidated users are charged a liquidation fee
to disincentivize getting liquidated.
During periods of high volatility, it is possible a user is not liquidated
before their account value goes negative. In this case, the liquidation is
is tokenized by the exchange’s insurance fund. If the insurance fund
is depleted, losses are socialized among users
proportional to leverage of profitable accounts.
To summarise the margining system, when opening a position or borrowing,
the user must first provide an initial margin in the form of
token, proportional to their position. Then, they must maintain
their token above a maintenance margin. Otherwise, the user’s
liquidated until back above the
maintenance margin.
Due to the mark price being unreliable during liquidity shortages, we use the index price in risk calculations to avoid undeserved liquidation cascades.
position notional and position open notional
Note on index price: Since PN/PON are considered risk/borrow values, they’re maximized, usually by picking , in order to consider the worst case risk of the account.
Perp
The position notional is the value of a given user’s position. For perp markets, we define it as
The position open notional is the maximum position notional achievable by filling all the user’s open orders. This is used to limit how much risk a user is exposed to through their open orders.
We define the position open notional as
Spot
Spot positions refer to borrowed assets, which we define as having a
negative balance. Thus the position taken on by a trader for a negative
balance scales with the amount borrowed.
Only negative balances are counted towards the position,
while positive balances count instead as collateral.
See the account value definition for more info.
Currently, we set for borrows:
and
To sum it up, We can compute user’s total position notional and total position open notional as and respectively.
account value
The account value is computed by summing the unrealized profit and loss (PnL) of the user’s positions, the token, and the borrows. We define unrealized PnL as PnL that hasn’t currently been reflected in the user’s balances by closing the position. We say PnL is realized when a position is closed.
To compute this, we define as the price at which the position was opened at, corresponding to the purchase or sell price of the position. In practice, a user’s position will have been opened at different prices by purchasing or selling contracts at different prices. To simplify implementation, it’s sufficient to reweight the open price accordingly. For example, suppose a user purchases 5 contracts at price 20, and 10 contracts at price 30. Then,
The open price must be reweighted after each fill, for both makers and takers. Now, recall that the position size is defined to be negative for short positions. We can now define unrealized PnL as
Note on index price: since it’s assets value, we use higher-bound index price for negative position size and lower-bound for positive one
is a total value of weighted user’s tokens normalized by index price:
Note on index price: since it’s positive assets value, lower-bound index price is used
To compute the value of assets, we weigh positive token with the asset and subtract the borrows. To represent this succinctly, token corresponds to a positive amount and borrows correspond to a negative amount. Amount includes unsettled funding payments. With this, we have our final account value calculation.
denominated in token_id = 0.
Essentially, corresponds to the user’s collateral,
whereas also discounts borrows and includes the current PnL.
This is to ensure that borrows are capped by the collateral to prevent exploits.
Margin fraction
These fractions define initial and maintenance leverage permitted
by the exchange, before a user is liquidated.
Each market has a different base fraction, typically depending on the
risk or volatility of the underlying asset.
margin fraction
Calculated per user as:
open margin fraction
Approximately ratio for all user assets (positions, balances, PnL) to user possible risk(debt, derivatives. open orders).
Note the amount includes unsettled funding.
initial margin fraction
Defines the initial margin to open a position or borrow assets. After opening a position or borrowing an asset, we must have . First, we first define a per-market or per-asset base IMF.
where
- is the maximum leverage multiplier for specific market; implementation may operate with market’s value, in which case
- is the weight of spot market’s
base token
Note that in practice, we need only store the market IMF and token IMF. The leverage is implied from this value. Then we have the user’s IMF.
Note that for tokens, is only defined if the token is borrowable.
For condition we can observe that sides have same denominator, which allows to simplify it to:
Let use .
cancel margin fraction
The below which open orders that extend the user’s current position are cancelled. Defined similarly to IMF.
maintenance margin fraction
The below which the user’s positions are closed and borrows unlent until the is back above the .
Liquidations
Notice that, by definition,
and from that if implies ( will happen before ) (but not necessarily the other way around) because:
which implies, with gradual change of values, cancelling orders will happen not later than reducing positions.
implies . is bankruptcy
Action is successful and changes market and account state, or fails - in this case no changes retain. Batch is tuple of actions, in case of successful all action are successful, in case of any action fail - all actions fail.
So we can summarize next actions which can be taken by liquidators and users depending on conditions. If conditions are not met, actions cannot be executed.
Let indicated specific market on which action is executed. Table is per user:
| action | pre condition | post condition | role | |
|---|---|---|---|---|
| 0 | eliminate all orders/position/balances in batch | , | liquidator | |
| 1 | cancel open orders which would increase perp position or borrow | or bankruptcy | or bankruptcy | liquidator |
| 2 | place any order or withdraw | (same as precondition) | user | |
| 3 | place order to reduce perp position or borrows based on notional | , , | liquidator | |
| 4 | place order to sell tokens for token_id = 0 or owed | same as 3, but cannot do 3 | liquidator |
User always act as liquidator.
It is possible that user cannot open orders nor liquidator can cancel existing, which helps to avoid jitter of user open/liquidator cancel.
A liquidation fee is charged to the liquidated user in case action was performed by liquidator.
In case of bankruptcy no fees are payed.
All orders when user is subject to liquidation are Fill-or-Kill(FoK, executed within single action, flash).
User can execute any allowed action in any order. Liquidator can execute next actions in table only if previous are not possible. For example, cancelling orders taking priority over closing positions.
Batch is allowed to compensate remaining negative balances from insurance fund.
Orders
Ideal means amount which makes exactly.
So fee is payed only only for part of order which had to be eliminated to get factors healthy.
Perpetuals
Perp positions are liquidated by reducing the user’s position.
Ideal position is .
Let ideal balance fraction be , ideal position fraction , real balance fraction .
So:
So reward is:
So liquidating more than needed to get up to will not give liquidator more fee.
Liquidator fee calculated after taker fee taken as long as account is not in bankruptcy.
Action can be executed iff all orders increasing position canceled. Action collects during reduction.
Borrows
Borrows are liquidated by reducing a borrower’s debt by liquidating a positive supply token, at the choice of the liquidator.
The borrow the liquidator takes is defined by:
Sells
In order to reduce perpetual position or repay borrow, sometimes need to get other token than user have. In this case fee is not taken.
Bankruptcy
An account is said to be in bankruptcy if .
Liquidator detects bankrupt account(liquidatee) and:
- cancels all account orders
- transfers all, negative and positive, balances to insurance fund
- distributes all accounts’s positions and debt to using the closing mechanism described below
- account is
clearedand may be used again
Closing mechanism
- Applies negative debt or perp position PnL to liquidator(s) account.
- The liquidator(s) will be compensated for the borrowed debt or negative perp PnL amount in USDC by the insurance fund. 2.1. Insurance funds will be sold for USDC as needed 2.2. Negative balances of tokens in insurance vault are reduced
- If the insurance fund is depleted (bankruptcy of protocol), the loss will be socialized according to socializing mechanism
Socializing mechanism
Through the supply APY.
Withdrawals are penalized per token as long as there is debt of it on insurance funds (for perps USDC).
Difference is used to reduce
Price bands
Reject place order requests with a limit price too far from the index price for the perpetual market to band B to reduce price manipulation on small markets. for smallest price and for highest price possible, and .