To protect LPs from front-run when oracle price is delayed and to simulate market makers’ behavior when a large order is traded, Symmetry implements an "Adjusted AMM mechanism".
Liquidity is uniformly distributed between − λ -\lambda − λ and. Outside this range, LP provides extra linear liquidity, which has the same liquidity distribution between and λ \lambda λ .
Parameters:
p o r a c l e p_{oracle} p or a c l e
oracle price before the trade
mid price before the trade
taker’s buy price before the trade
taker’s sell price before the trade. p s e l l ≤ p b u y p_{sell}\leq p_{buy} p se ll ≤ p b u y
p o r a c l e ′ p'_{oracle} p or a c l e ′
oracle price after the trade
mid price after the trade
taker’s buy price after the trade
taker’s sell price after the trade. p s e l l ′ ≤ p b u y ′ p'_{sell}\leq p'_{buy} p se ll ′ ≤ p b u y ′
Calculation
AMM formula is as below:
Before trade is executed, p r e m = λ ⋅ s p r ⋅ L P prem = \frac { \lambda \cdot s} {pr \cdot LP} p re m = p r ⋅ L P λ ⋅ s ,
After trade is executed, p r e m ′ = λ ⋅ s ′ p r ⋅ L P prem' =\frac {\lambda \cdot s'} {pr \cdot LP} p re m ′ = p r ⋅ L P λ ⋅ s ′ ,
where s ′ = s + T s' = s + T s ′ = s + T , T T T is trade quantity.
Therefore,
p m i d = p o r a c l e ( 1 + p r e m ) = p o r a c l e ( 1 + λ ⋅ s p r ⋅ L P ) p_{mid} = p_{oracle}(1+prem)
= p_{oracle}
\left(1 + \frac { \lambda \cdot s}
{pr \cdot LP}\right) p mi d = p or a c l e ( 1 + p re m ) = p or a c l e ( 1 + p r ⋅ L P λ ⋅ s ) p m i d ′ = p o r a c l e ′ ( 1 + p r e m ′ ) = p o r a c l e ′ ( 1 + λ ⋅ ( s + T ) p r ⋅ L P ) p'_{mid} = p'_{oracle}(1+prem') = p'_{oracle}
\left(1 + \frac { \lambda \cdot (s+T)}
{pr \cdot LP}\right) p mi d ′ = p or a c l e ′ ( 1 + p re m ′ ) = p or a c l e ′ ( 1 + p r ⋅ L P λ ⋅ ( s + T ) ) Besides p o r a c l e p_{oracle} p or a c l e and p m i d p_{mid} p mi d , smart contract also keeps track of the taker's buy price p b u y p_{buy} p b u y and sell price p s e l l p_{sell} p se ll .
【User’s Buy Price & Sell Price】
After the trade, when p m i d p_{mid} p mi d is between p b u y p_{buy} p b u y and p s e l l p_{sell} p se ll ., both prices gradually move towards p m i d ′ p'_{mid} p mi d ′ at a fixed speed, reaching p m i d ′ p'_{mid} p mi d ′ after 60 seconds.
When p m i d ′ p'_{mid} p mi d ′ exceeds either of these two prices, the crossed price moves immediately to p m i d ′ p'_{mid} p mi d ′ . And the other one will gradually move towards p m i d ′ p'_{mid} p mi d ′ at a fixed speed, reaching p m i d ′ p'_{mid} p mi d ′ after 60 seconds.
Formally speaking, after t t t seconds following a trade, these two prices change as follows.
p b u y ′ = { m a x ( t ⋅ p m i d ′ + ( 60 − t ) ⋅ p b u y 60 , p m i d ′ ) t < 60 p m i d ′ t ≥ 60 p s e l l ′ = { m i n ( t ⋅ p m i d ′ + ( 60 − t ) ⋅ p s e l l 60 , p m i d ′ ) t < 60 p m i d ′ t ≥ 60 \begin{align*}
p'_{buy} &=
\begin{dcases}
max\left(\frac{t \cdot p'_{mid} + (60 - t) \cdot p_{buy}}{60}, p'_{mid} \right) && t < 60
\\
p'_{mid} && t \ge 60\\
\end{dcases} \\
p'_{sell} &=
\begin{dcases}
min \left(\frac{t \cdot p'_{mid} + (60 - t) \cdot p_{sell}}{60},p'_{mid} \right) && t < 60
\\
p'_{mid} && t \ge 60\\
\end{dcases}
\end{align*} p b u y ′ p se ll ′ = ⎩ ⎨ ⎧ ma x ( 60 t ⋅ p mi d ′ + ( 60 − t ) ⋅ p b u y , p mi d ′ ) p mi d ′ t < 60 t ≥ 60 = ⎩ ⎨ ⎧ min ( 60 t ⋅ p mi d ′ + ( 60 − t ) ⋅ p se ll , p mi d ′ ) p mi d ′ t < 60 t ≥ 60 【Execution Price】
A trade is executed as if it is divided into infinite tiny pieces, which are executed one by one. For example, assume that a buy trade of volume T T T changes the mid price from p m i d p_{mid} p mi d to p m i d ′ p'_{mid} p mi d ′ and the user’s buy price is p b u y p_{buy} p b u y before the trade. Its turnover is
p e x e c ⋅ T = ∫ 0 T max ( v ⋅ p m i d + ( T − v ) ⋅ p m i d ′ T , p b u y ) d v p_{exec} \cdot T =
\int_0^T
\max\left(
\frac{v \cdot p_{mid} + (T - v) \cdot p'_{mid}}{T},
p_{buy}
\right)
\mathrm{d}v p e x ec ⋅ T = ∫ 0 T max ( T v ⋅ p mi d + ( T − v ) ⋅ p mi d ′ , p b u y ) d v Therefore, the execution price for user’s buy order is
p e x e c = { p b u y p m i d ′ ≤ p b u y ( p b u y − p m i d ) ⋅ p b u y + ( p m i d ′ − p b u y ) ⋅ p m i d ′ + p b u y 2 p m i d ′ − p m i d p m i d ′ > p b u y p_{exec} =
\begin{dcases}
p_{buy} & p'_{mid} \le p_{buy} \\
\frac{(p_{buy} - p_{mid}) \cdot p_{buy} + (p'_{mid} - p_{buy}) \cdot \frac{p'_{mid} + p_{buy}}{2}}{p'_{mid} - p_{mid}} & p'_{mid} > p_{buy}
\end{dcases} p e x ec = ⎩ ⎨ ⎧ p b u y p mi d ′ − p mi d ( p b u y − p mi d ) ⋅ p b u y + ( p mi d ′ − p b u y ) ⋅ 2 p mi d ′ + p b u y p mi d ′ ≤ p b u y p mi d ′ > p b u y Same as above, the execution notional for user’s sell order is
p e x e c ⋅ T = ∫ 0 T min ( v ⋅ p m i d + ( T − v ) ⋅ p m i d ′ T , p s e l l ) d v p_{exec} \cdot T =
\int_0^T
\min\left(
\frac{v \cdot p_{mid} + (T - v) \cdot p'_{mid}}{T},
p_{sell}
\right)
\mathrm{d}v p e x ec ⋅ T = ∫ 0 T min ( T v ⋅ p mi d + ( T − v ) ⋅ p mi d ′ , p se ll ) d v Example
Initial State
L P LP L P = 100,000,000 (assume it does not change in this example)
α \alpha α = 1
λ \lambda λ = 0.05
p r pr p r = 0.5
p o r a c l e p_{oracle} p or a c l e = 20000
s = 0
p m i d p_{mid} p mi d = p b u y p_{buy} p b u y = p s e l l p_{sell} p se ll = 20000
Trade #1 at time t = 0s
State before the trade
s = 0 s = 0 s = 0
p m i d = p b u y = p s e l l = 20000 p_{mid} = p_{buy} = p_{sell} = 20000 p mi d = p b u y = p se ll = 20000
User sells $40,000,000
s ′ = − 40 , 000 , 000 s' = -40,000,000 s ′ = − 40 , 000 , 000
p m i d ′ = 20000 × ( 1 + 1 × 0.05 × − 40 , 000 , 000 0.5 × 100 , 000 , 000 ) = 19200 p'_{mid} = 20000 \times \left( 1 + \frac{1 \times 0.05 \times -40,000,000}{0.5 \times 100,000,000} \right) = 19200 p mi d ′ = 20000 × ( 1 + 0.5 × 100 , 000 , 000 1 × 0.05 ×− 40 , 000 , 000 ) = 19200
p ′ s e l l = min ( p s e l l , p m i d ′ ) = 19200 p'{sell} = \min(p_{sell}, p'_{mid}) = 19200 p ′ se ll = min ( p se ll , p mi d ′ ) = 19200
The trade volume is evenly distributed between p s e l l p_{sell} p se ll and p s e l l ′ p'_{sell} p se ll ′ .
p e x e c = p s e l l + p s e l l ′ 2 = 19600 p_{exec} = \frac{p_{sell} + p'_{sell}}{2} = 19600 p e x ec = 2 p se ll + p se ll ′ = 19600
p b u y ′ = p b u y = 20000 p'_{buy} = p_{buy} = 20000 p b u y ′ = p b u y = 20000
Summary
Before this trade
After this trade
Trade #2 at time t = 15s
State before the trade
s = − 40 , 000 , 000 s = -40,000,000 s = − 40 , 000 , 000
p m i d = p s e l l = 19200 p_{mid} = p_{sell} = 19200 p mi d = p se ll = 19200
p b u y = p m i d × 15 + 20000 × ( 60 − 15 ) 60 = 19800 p_{buy} = \frac{p_{mid} \times 15 + 20000 \times (60 - 15)}{60} = 19800 p b u y = 60 p mi d × 15 + 20000 × ( 60 − 15 ) = 19800
User sells $20,000,000
s ′ = − 60 , 000 , 000 s' = -60,000,000 s ′ = − 60 , 000 , 000
p m i d ′ = 18800 p'_{mid} = 18800 p mi d ′ = 18800
p s e l l ′ = min ( p s e l l , p m i d ′ ) = 18800 p'_{sell} = \min(p_{sell}, p'_{mid}) = 18800 p se ll ′ = min ( p se ll , p mi d ′ ) = 18800
The trade volume is evenly distributed between p s e l l p_{sell} p se ll and p s e l l ′ p'_{sell} p se ll ′ .
p e x e c = p s e l l + p s e l l ′ 2 = 19000 p_{exec} = \frac{p_{sell} + p'_{sell}}{2} = 19000 p e x ec = 2 p se ll + p se ll ′ = 19000
p b u y ′ = p b u y = 19800 p'_{buy} = p_{buy} = 19800 p b u y ′ = p b u y = 19800
Summary
After the last trade
Before this trade
After this trade
Trade #3 at time t = 39s (24 seconds later)
State before the trade
s = − 60 , 000 , 000 s = -60,000,000 s = − 60 , 000 , 000
p m i d = p s e l l = 18800 p_{mid} = p_{sell} = 18800 p mi d = p se ll = 18800
p b u y = p m i d × 24 + 19800 × ( 60 − 24 ) 60 = 19400 p_{buy} = \frac{p_{mid} \times 24 + 19800 \times (60 - 24)}{60} = 19400 p b u y = 60 p mi d × 24 + 19800 × ( 60 − 24 ) = 19400
User buys $10,000,000
s ′ = − 50 , 000 , 000 s'=-50,000,000 s ′ = − 50 , 000 , 000
p m i d ′ = 19000 p'_{mid} = 19000 p mi d ′ = 19000
p b u y ′ = max ( p b u y , p m i d ′ ) = 19400 p'_{buy} = \max(p_{buy}, p'_{mid}) = 19400 p b u y ′ = max ( p b u y , p mi d ′ ) = 19400
The trade is completely executed at p b u y p_{buy} p b u y , which does not move in this trade
p e x e c = p b u y = 19400 p_{exec} = p_{buy} = 19400 p e x ec = p b u y = 19400
p s e l l ′ = p s e l l = 18800 p'_{sell} = p_{sell} = 18800 p se ll ′ = p se ll = 18800
Summary
After the last trade
Before this trade
After this trade
Trade #4 at time t = 54s (15 seconds later)
State before the trade
s = − 50 , 000 , 000 s = -50,000,000 s = − 50 , 000 , 000
p m i d = 19000 p_{mid} = 19000 p mi d = 19000
p b u y = p m i d × 15 + 19400 × ( 60 − 15 ) 60 = 19300 p_{buy} = \frac{p_{mid} \times 15 + 19400 \times (60 - 15)}{60} = 19300 p b u y = 60 p mi d × 15 + 19400 × ( 60 − 15 ) = 19300
p s e l l = p m i d × 15 + 18800 × ( 60 − 15 ) 60 = 18850 p_{sell} = \frac{p_{mid} \times 15 + 18800 \times (60 - 15)}{60} = 18850 p se ll = 60 p mi d × 15 + 18800 × ( 60 − 15 ) = 18850
User buys $50,000,000
s ′ = 0 s' = 0 s ′ = 0
p m i d ′ = 20000 p'_{mid} = 20000 p mi d ′ = 20000
p b u y ′ = max ( p b u y , p m i d ′ ) = 20000 p'_{buy} = \max(p_{buy}, p'_{mid}) = 20000 p b u y ′ = max ( p b u y , p mi d ′ ) = 20000
A fraction of the trade volume is executed at p b u y p_{buy} p b u y and the rest is evenly distributed between p b u y p_{buy} p b u y and p b u y ′ p'_{buy} p b u y ′ .
p e x e c = ( ( p b u y − p m i d ) × p b u y + ( p b u y ′ − p b u y ) × p b u y + p b u y ′ 2 ) ÷ ( p b u y ′ − p m i d ) = 19545 p_{exec} = \left((p_{buy} - p_{mid}) \times p_{buy} + (p'_{buy} - p_{buy}) \times \frac{p_{buy} + p'_{buy}}{2} \right) \div (p'_{buy} - p_{mid}) = 19545 p e x ec = ( ( p b u y − p mi d ) × p b u y + ( p b u y ′ − p b u y ) × 2 p b u y + p b u y ′ ) ÷ ( p b u y ′ − p mi d ) = 19545
p s e l l ′ = p s e l l = 18850 p'_{sell} = p_{sell} = 18850 p se ll ′ = p se ll = 18850
Summary
After the last trade
Before this trade
After this trade