DeFi 的灵魂 -- AMM 自动做市商模型

这篇文章带大家过一遍DeFi里常见的自动做市商模型。

视频版本可以看这里。ppt内容可以看这里。Mirror上会持续分享一下crypto scientist & analyst 相关的内容,我的mirror主页,我的twitter链接BuidlerDAO链接,欢迎大家关注。

下面是全文内容。


此文从无常损失和滑点两个方面,分析 Uniswap 和 Curve (主流自动做市商) 稳定币做市曲线。

定义

滑点有2种定义。本文采用第一种定义方法,反映交易者成交的真实平均损失。(!!视频里用的第二种定义方式,因为觉得成交后的当时的价格作为市场价格会更有参考意义吧!!)

  1. (成交平均价格-初始价格)/ 初始价格

  2. (成交后价格-初始价格)/ 初始价格

无常损失定义:

  1. 有两种选项

    1. 参加流动性挖矿 ==> w10(参与挖矿的资产市值)

    2. 持有资产,不参加流动性挖矿 ==> W11(不参与挖矿的资产市值)

  2. 无常损失 = (w10 - w11) / w11

结论 -- 稳定币对交易

选择什么样的做市曲线,这是一个滑点(交易者)和无常损失(流动性提供者)的权衡利弊。就稳定币而言,我们追求更低的滑点,且绝大多数情况下价格会在1附近波动。Uniswap v3 和 Curve 曲线会是更好的选择,因为他们相当于加个杠杆的uniswap v1/v2 曲线,同样的成交量可以带来更低的滑点。而Uniswap v3 和 Curve 曲线可以通过调整参数(价格区间和A值)达到相似的效果。就现在市场而言(P=[0.9986, 1.0014], A=5000),Curve 能够在价格在1附近提供更好的滑点,而无常损失和Uniswap v3 基本一致。假设稳定币价格不会脱钩,Curve 会是更好的选择。

滑点

假设我们从价格为1的点开始做交易

  1. 相同的成交量,Curve上的滑点低于Uniswap v1/v2。如果我们单次交易池子里一个币对的99.9999%存量,Curve上的滑点也低于Uniswap v1/v2。对交易者来说,Curve 确实会带来更好的用户体验。

  2. Uniswap v3 采用了设置区间的方式来放大流动性。在区间范围内,Uniswap v3上的滑点始终低于Uniswap v1/v2。但只要超出区间,Uniswap v3交易对就失去了流动性,无法交易。

  3. Uniswap v3的价格区间的宽窄就类似于Curve曲线中A值带来的杠杆。Uniswap v3所对应的滑点和我们想要的成交数量和资产效率乘数是线性相关的。Curve曲线会随着A值的变大,滑点由线性变得更弯曲。不同的价格区间和不同的A值会带来不同的滑点:

    1. Uniswap v3: [0.8, 1.25]; Curve A =2 (图1)==> Uniswap v3 滑点低

    2. Uniswap v3: [0.8, 1.25]; Curve A =8 (图2)==> 成交量比较小,Curve 滑点低;成交量比较大,Uniswap v3 滑点低

    3. Uniswap v3: [0.8, 1.25]; Curve A =50 (图3)==> 成交量比较小,Curve 滑点低;成交量比较大,Uniswap v3 滑点低

    4. Uniswap v3: [0.9986, 1.0014]; Curve A = 5000【现在市场情况】 (图4)==> 成交量比较小,Curve 滑点低;成交量比较大,Uniswap v3 滑点低。绝大多数情况,同样成交量,Curve 滑点更低。

  4. 就现在市场而言 (图4),成交量较小时,Curve 滑点 < Uniswap v3 < Uniswap v1/v2。如果出现出现巨额成交量(超90%)或者池子内一个币的数量偏移90%以上或者严重脱钩(稳定币价格远离1),Uniswap v3 滑点 < Curve < Uniswap v1/v2

图1: Uniswap v3:
图1: Uniswap v3:
图2: Uniswap v3:
图2: Uniswap v3:
图3: Uniswap v3:
图3: Uniswap v3:
图4:Uniswap v3:
图4:Uniswap v3:

无常损失

此处做了两个重要假设:

  1. 池子里只有两个币对(A, B)

  2. A和B的初始数量为1:1

结论

  1. 同样成交量下,Curve滑点比uniswap v1/v2更低,但是在同样价格变化下,Curve无常损失更大。随着A值增大,Curve滑点越来越低,无常损失也越来越大(图5)。

  2. 为达到和uniswap一样的价格,Curve池需要更多的成交量。假设P0=1

    1. A = 1时,一次性交易池内99%的一个币,价格变化99.3%

    2. A = 100时,一次性交易池内99%的一个币,价格变化84.8%

    3. A = 1000时,一次性交易池内99%的一个币,价格变化38%

    4. ==> 因为需要更多的成交量,Curve 很难出现和Uniswap同样的价格。但是假设没有无风险套利机会,Curve 和Uniswap V1/v2 上 是同样的价格,Curve 无常损失更大。

  3. 同样成交量下,Uniswap v3滑点比uniswap v1/v2更低,但是同样价格变化下,Uniswap v3无常损失更大。随着价格区间变小,Uniswap v3滑点越来越低,无常损失也越来越大(图6)。

  4. 同样是加了杠杆的Uniswap v1/v2仓位, Uniswap v3和Curve 有什么区别呢?

    1. 固定Uniswap v3价格区间为[0.8, 1.25], 我们变化 Curve 的A值,我们可以看到,Uniswap v3 的无常损失曲线是在Curve[A =10] 和Curve[A =100] 之间的。也就是说,通过变化A值,Uniswap v3 和 Curve 的无常损失可以达到类似效果。(图7)

    2. Uniswap v3: [0.9986, 1.0014]; Curve A = 5000【现在市场情况】。就现在市场而言,同样价格变化,Curve 和 Uniswap v3 的无常损失基本一致。(图8)

图5
图5
图6
图6
图7
图7
图8
图8

详细python实现见此:python

详细excel实现见此:excel


以下是公式推导

Uniswap v1/v2

做市曲线 -- 恒定乘积做市

x * y = k = L^2

其中x,y分别代表代币x和y的数量。因为k>0,可以把它定义为L^2

价格 (以y为基本单位,x的价格)

y = L^2 / x ==> dy = - L^2 / x^2 dx ==>  
P = - dy / dx = - (- L^2 / x^2 dx) / dx = L^2 / x^2 = y / x
 
x = L / sqrt(P)
y = L * sqrt(P)
价格为边际数量变化之商
价格为边际数量变化之商

成交价格

假设流动池里的币对从(x1,y1) 变化到(x2,y2),而价格从p1变化到p2

滑点

无常损失

w10: wealth at time t1 if participate as UNISWAP LP at time t0 
w11: wealth at time t1 if hold half asset x and half asset y at time t0
p(t1): price for x at time t1 
p(t0): price for x at time t0

Assume r = p(t1) / p(t0)

!!! all the wealth are denominated in y. 

w10 = p(t1) * x1 + y1 
    = p(t1) * L / sqrt(p(t1)) + y1
    = L * sqrt(p(t1)) + y1
    = 2 * L * sqrt(p(t1))

w11 = p(t1) * x0 + y0 【the quantities remain the same】
    = p(t1) * L / sqrt(p(t0)) + y0
    = r * P(t0) * L / sqrt(p(t0)) + y0 
    = r * sqrt(p(t0)) * L + sqrt(p(t0)) * L
    = (1 + r) * sqrt(p(t0)) * L
 
IL = w10 / w11 - 1   
   = 2 * L * sqrt(p(t1)) / ((1 + r) * sqrt(p(t0)) * L) - 1
   = 2 * sqrt(p(t1)) / ((1 + r) * sqrt(p(t0))) - 1 
   = 2 * sqrt(r) / (1 + r) - 1 

做市曲线 -- 恒定乘积做市

what's new:
Pa: low range for x
Pb: up range for x
Pc: current price for x 
Pa < Pc < Pb 

x_v: virtual reserve for x 
y_v: virtual reserve for y 
L: virtual liquidity 

(x + L / sqrt(Pb)) * (y + L * sqrt(Pa)) = L^2 

x_v * y_v =  L^2 
x_v = x + L / sqrt(Pb)
y_v = y + L * sqrt(Pa)

Pc = - dy / dx = y_v / x_v     
x_v = L / sqrt(Pc)
y_v = L * sqrt(Pc)

x = x_v -  L / sqrt(Pb)
  = L / sqrt(Pc) - L / sqrt(Pb)

y = y_v - L * sqrt(Pa)
  = L * sqrt(Pc) - L * sqrt(Pa)

无常损失

w10: wealth at time t1 if participate as UNISWAP LP at time t0 
w11: wealth at time t1 if hold half asset x and half asset y at time t0

Assume r = p(x1) / p(x0)

资本效率乘数

w_v2 = w_v3
w_v2 = w_v3

单区间滑点

假设V3只有一个流动区间

  1. V2滑点 = 资本效率乘数 * V3滑点

  2. 区间越小, V3滑点越小

实际上,Uniswap v3 是无数个流动性区间累加起来的。每个tick之间对应其单独的流动性,只有这个tick对应的流动性被耗尽,才会进入下一个区间继续寻找流动性。

Curve v1

Curve 是 恒定乘积做市 和 恒定和做市的结合。当 A 取值接近于0时,Curve 曲线 = Uniswap v1/v2 曲线;当 A 取值接近于无穷时,Curve 曲线 = 恒定和做市曲线。A 越大,Curve 曲线越向恒定和做市曲线倾斜。

做市曲线 -- 恒定乘积和恒定和结合做市

A ==> 扩增参数(amplification parameter)

D ==> 不变量参数 (StableSwap invariant)

其中,Ann = An^n

如何计算置换的量

假设我们手上有 xi,想去池子换成 xj (=y)。

通过上图的变化,再加上一些简化,我们就可以得到

这个问题就变为,在满足f(y)=0的情况下,求解y。这是一元二次方程,可以直接用求根公式,但Curve.fi 用的牛顿迭代法(可能是Solidity没有根号?)。

牛顿迭代法 (Newton Raphson Method)
牛顿迭代法 (Newton Raphson Method)

由于f’(y) = 2y + (b-D),我们就可以得出下图的迭代公式了

Curve Stable Swap - 牛顿迭代法
Curve Stable Swap - 牛顿迭代法

如何计算D

和计算置换量类似的方法,我们假设x,y不变,对做市曲线求解D。

这里的S = sum(xi)。

求导
求导

其中 Dp 如下图

Dp
Dp

同样用牛顿迭代法,求解D「注:当n=2,此方程有闭式解;当n>2,使用牛顿迭代法」

Curve Stable Swap - 牛顿迭代法
Curve Stable Swap - 牛顿迭代法

现在假设n=2(池子里只有两个币对),x和y

做市曲线 (n = 2, x1 = x, x2 = y)

n = 2, x1 = x, x2 = y
n = 2, x1 = x, x2 = y

如何计算D

已知x,y求D,这是一个三元方程, 可以通过卡尔达诺公式(Cardano Formula)求解

其中

值得注意的是,假设不添加或删除流动性,D是恒定的。x的变化只会带来y的变化。

如何计算置换的量

已知n=2,n^n =4, 带入之前的置换公式,可以得到

同理,对于y来说,这是一个一元二次方程,可以用求根公式求解。

其中a, b, c 分别为:

置换后价格

我们知道

对等式两边求导得到

即可得到y’的公式

我们知道价格等于边际变化量之比,即p_x = -y’ = -dy / dx。通过上述公式,我们就可以得到置换后价格。

滑点

已知 p_x = - y’ = g(x,y),对任意(x,y),我们都可以求到其对应的价格。也可以求到平均价格。再利用滑点定义【(成交平均价格-初始价格)/ 初始价格】,即可以求出滑点。

无常损失

已知做市曲线f(x,y) = 0 和 p_x = - y’ = g(x,y),两个方程求解两个未知数(x,y),我们就可以求到 x,y 分别关于 D和 p_x 的函数。然后再通过无常损失定义【(w10 - w11) / w11】,即可以求出无常损失。

首先找到 y = f(p,x),如下图。

然后我们还知道 y = f(x),所以通过y = f(x) = f(p,x),我们就可以求解 x = f(p) 。这是一个一元四次方程,不太容易解出来,就没继续了。


**此处考虑另外一种方法画出无常损失曲线。**首先我们假设池子里的初始币对(x,y)数量为1:1,那么对于每个给定的y的数量变化,我都可以得到对应x的数量变化,从而计算得到变化后的价格。已知了初始价格,初始数量,新价格和新数量,我们就可以通过无常损失定义,计算出其无常损失了。为了画出,我们就需要一个y的数量变化的列表【dy= [-99, -98, -97, ……, 99]】,然后计算出当前价格,再计算出无常损失。我们就可以得到一个当前价格和无常损失的一一对应关系列表。即可以画出价格对应的无常损失的曲线。

详细python实现见此:python

详细excel实现见此:excel

!!!在推导Uniswap无常损失时,我们是没有限制初始币对数量的。它的机制,在任何时刻,两个币对的价值都是1:1。所以不管当前池子里数量是什么,我们都可以通过公式直接得出无常损失。而在推导Curve无常损失时,我们假设了初始币对数量为1:1。我们通过初始币对数量求到D=x+y=2x=2y(如果不添加或删除流动性,D不变),再通过成交量就可以求到无常损失。 如果初始币对数量不是1:1,那么同样的价格变化(与1:1的初始状态相比),对应的无常损失会不一样。

公式

参考目录

Uniswap v1 example: https://hackmd.io/@HaydenAdams/HJ9jLsfTz?type=view#🦄-Uniswap-Whitepaper

Uniswap V2 白皮书:https://uniswap.org/whitepaper.pdf

Uniswap V3 白皮书:https://uniswap.org/whitepaper-v3.pdf

Curve v1 白皮书:https://curve.fi/files/stableswap-paper.pdf

Curve v1 详解:https://alvarofeito.com/articles/curve/

Subscribe to June
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.