深度解析:自动做市商(AMM)算法的数学原理及其未来发展
作者:Leo Liu, Guangwu Xie
翻译:Vanessa Cao
校对:Leo Liu, Guangwu Xie
排版:Jane Hu
感谢:Fangyuan Zhao, Showen Peng, DW, Lianxuan Li, Dave White, Dan Robinson, Vanessa Cao, Jane Hu
本文由星际密探和Dachale Research 战略合作伙伴BTXCapital独家授权星际密探发布,在本文中,我们将首先回顾由 Bancor、Uniswap、Balancer 和 Curve 协议实现的四种自动做市商 (AMM) 算法。还将讨论 AMM 算法的最新发展、可能的改进和未来。
由于本论文过长,本文总共分为上、中、下篇阐述自动做市商算法、现状及未来迭代的思考。。
上篇目录
- Bancor Network的联合曲线概念和交易公式
- Uniswap 的无常损失计算
- 当价格变动在2ρ之间时的正向收益
- 流动性分布、流动性注入、 Uniswap V3 范围订单
- Balancer 的做市函数和交易公式
- 智能订单路由(SOR)算法
......
Bancor Network 的联合曲线概念和交易公式:
Bancor¹利用联合曲线的概念来确定价格。联合曲线是代币价格与其总供应量之间的关系。
Bancor¹
Bancor Protocol Continuous Liquid ity for Cryptographic Tokens through their Smart Contracts
https://storage.googleapis.com/website-bancor/2018/04/01ba8253-bancor_protocol_whitepaper_en.pdf
联合曲线 Bonding Curve:
联合曲线模型可以理解为描述“代币买卖价格”与“代币发行总量”之间的函数关系,可以由智能合约以去中心化的方式自动执行。
https://medium.com/linum-labs/intro-to-bonding-curves-and-shapes-bf326bc4e11a
Bancor Network选择的不变量是F,称为连接权重。在第一个表达式中R是指流动性池中的储备代币数量,S是流动性池外的BNT总供应量,P是BNT和储备代币 的相对价格。我们可以代入P的方程,对两边积分²得到P和S之间的关系。这是一个指数表达式,其中指数α与连接权重F有关(F在0和1之间)。F越小,α越大,这意味着价格相对于BNT的总供应量变化得更快。
两边积分²
Formulas for Bancor system
https://drive.google.com/file/d/0B3HPNP-GDn7aRkVaV3dkVl9NS2M/view?resourcekey=0-mbIgrdd0B9H8dPNRaeB_TA
使用这个表达式和简单的积分,我们可以导出T(购买的BNT代币)和E(支付的储备代币)之间的关系,其中R0,S0是R和S的当前值。
如果我们想在代币A和代币B之间交换,则将代币A出售给代币B。我们首先需要使用代币A从池A购买BNT代币(注:如果我们没有BNT代币)。接下来,我们需要使用BNT从池B购买代币B。下面是计算我们将收到多少代币所需的精确公式。代币A和代币B之间的相对价格可以用BNT代币和代币A/B之间的相对价格表示。
优点:Bancor 允许在某些池中进行单边流动性的注入,这由Bancor治理决定。可以存入多少单边流动性是有限制的,这也是由Bancor治理决定的。在限额内,当用户以其他代币的形式存入单边流动性时,Bancor将补充等值的 BNT 代币。这使得用户提供的有效流动性加倍。如果达到限额,如果人们想要存单边流动性,就得等有人提取单边流动性,或者有人把BNT做为单边流动性注入。
Bancor 协议以BNT部分赚取的手续费补偿用户在存入单边流动性时的无常损失(将在后面讨论)。如果交易费用不能完全补偿无常损失,Bancor将铸造 BNT以确保无常损失为零。因此,流动性提供者如果将流动性存入一定的时间(存入满100天可全额补偿),就可以享受稳定的收入。
缺点:如上所述,所有交易都需要 BNT 代币作为中介。因此,我们将经历两次滑点。由于相同的原因,所有流动性池都由 BNT 和另一个代币组成,因此缺乏多样性。BNT 代币价格也可能受到影响,因为需要弹性供应才能实现无常损失补偿和单边流动性存款。
Bancor 引入了连接代币 BNT 的概念,它连接到所有具有不同连接权重的代币,对应不同决定价格的联合曲线。
Uniswap 的无常损失计算:
Uniswap 使用恒定乘积做市商 (CPMM) 来决定价格。在我们深入研究 Uniswap V2 和 V3 使用的算法之前,让我们先了解什么是无常损失 (IL) 以及如何计算它。
恒定乘积做市商 (CPMM)
Constant Product Market Maker
强制要求两种资产储备量的乘积必须始终保持不变 x*y=k
https://ethresear.ch/t/improving-front-running-resistance-of-x-y-k-market-makers/1281
无常损失
Impermanent Loss
是指资金在流动性池中面临的损失。
https://finematics.com/impermanent-loss-explained/
如果 AMM 函数是凸的(注:价格随着我们买入而增加 / 价格随着我们卖出而减少),那么没有交易费用补偿的单笔交易总是会导致流动性提供者赔钱。假设一笔交易导致 AMM 函数从点 1 移动到点 2。点 1 和点 2 的现货价格(函数导数的绝对值)是 P1 和 P2。P3 为实际交易价格。由于凸函数的性质,P1 > P3 > P2。无常损失定义为交易后池中流动性提供者代币的当前价值与流动性提供者的代币当前价值之间的差值,如果他只是持有他的代币而不将它们用于流动性提供,则表示为V 和 Vheld。为方便起见,无常损失和价格将以代币 Y 表示(1 个代币 Y 的价格为单位 1)。经过一些简单的推导,很容易证明无常损失总是小于零(x2 > x1,P2 < P3)。
Uniswap³ V2 使用一个简单但功能强大的公式来确定交易。池代币储备数量的乘积是一个常数。与 Bancor 相比,它摆脱了连接代币的依赖。交易完全由流动性池中的代币数量决定。
Uniswap³
Uniswap V2 Core
https://uniswap.org/whitepaper.pdf
由于此函数的性质,池中两个代币的价值将始终相同(我们在本文中使用的价格将始终是相对价格)。
使用相同的逻辑,不难计算 Uniswap V2中单笔无手续费的无常损失。假设交易将价格从P更改为Pk。以百分比衡量的无常损失可以单独表示为k的函数。
毫不奇怪,这个函数总是小于或等于零,正如我们从上面没有费用的无常损失图中可以看出的。如果在对数空间中绘制横轴,则 IL(k) 将是对称的。结论是:相对价格变化越大,无常损失就越大。这可以解释为流动性提供者的更有价值的代币从池中被买出,留给他们更多价值较低的代币。
当价格变动在2ρ之间时的正向收益:
接下来,让我们看看如果我们添加交易费用,IL(k) 会如何表现:
导出的无常损失函数 IL(k, ρ) 看起来与无费用的无常损失函数非常相似。我们可以通过将ρ设置为零来进行合理性验证,得出相同的结果。典型的 Uniswap V2 费用百分比为ρ= 0.3%。在绘制无常损失函数时,我们可以看到在大约k= 0.994 到 1(大约 2ρ跨度)之间有一个高于零的部分。在该地区,无常损失是正的,这意味着流动性提供者实际上获得了价值(在该地区赚取的交易费用优于损失)。通过引入交易费,当价格在一定范围内波动时,流动性提供者将获得正收益。
当价格变动更加波动时,流动性提供者似乎总是会出现亏损。然而,实际情况并非如此。我们知道 Dave White4(注:Paradim风险投资基金研究员)等人解决了这个难题。遗憾的是,它超出了这篇介绍性论文的范围。我们打算在未来进一步研究这个问题。
Dave White4
Uniswap’s Financial Alchemy
https://research.paradigm.xyz/uniswaps-alchemy
至于其他流行的 AMM 算法(包括 Uniswap V3)的无常损失推导,我们向读者推荐Jiahua Xu⁵等人的这篇论文。这些推导将是下一次的主题。
Jiahua Xu⁵
SoK: Decentralized Exchanges (DEX) with Automated Market Maker (AMM) protocols
https://arxiv.org/abs/2103.12732
优点:第一个用池中代币数量的凸函数来确定价格。
缺点:流动性供应均匀分布于所有价格范围,这意味着资本效率较低。
流动性分布、流动性注入、Uniswap V3 范围订单:
为了提高流动性效用并降低无常损失风险,Uniswap⁶ V3 允许用户仅在特定价格范围内提供流动性。
Uniswap⁶
Uniswap V3 Core
https://uniswap.org/whitepaper-v3.pdf
From Uniswap V3 whitepaper
这是通过对 Uniswap V2 函数进行平移来实现的:
From Uniswap V3 whitepaper
将函数向下平移a点的y值,向左平移b点的x值,如上图和等式所示,确保a 和b之间的有效交易结果,就像我们使用绿色曲线作为我们的价格决定函数。当价格超出此范围时,其中一个代币储备将被售罄,从而有效地将流动性集中到此价格范围内。
Dan Robinson⁷ (注:Paradim风险投资基金研究员主管)发表了一篇关于计算多个 AMM 的流动性分布的优秀论文。
Dan Robinson⁷
Uniswap V3: The Universal AMM
https://www.paradigm.xyz/2021/06/uniswap-v3-the-universal-amm/
也可以简单地证明,两个流动性提供者在同一价格范围内的流动性可以简单地加在一起。
在存入流动性时,如上所示,Uniswap V3中每个资产的价值不一定相等。只有当P等于Pa和 Pb 的几何平均值时,每个资产的价值才相等。当P小于几何平均值时,资产X的价值大于资产Y的价值。当P大于几何平均值时,资产X的价值小于资产Y的价值。
当当前价格完全超出流动性提供者设定的价格区间时,Uniswap V3将流动性提供者的输入算作范围订单(Range Order),只允许其存入一种代币(类型取决于价格区间是否完全高于或低于当前价格)。例如,考虑一个由 ETH 和 Dai 组成的流动性池。如果设定的价格区间完全高于 ETH 的当前价格,则只允许用户存入 ETH。如果价格区间完全低于 ETH 的当前价格,则只允许用户存入 Dai。当价格完全越过流动性提供者设定的价格区间时,他存入的资产将全部转换为另一种的代币。由于用户只能存入一种代币,范围订单只能实现传统限价订单中四分之二的订单(获利订单、买入限价订单)。另一方面,买入止损订单和止损订单无法实现。截至目前,我们不知道限制范围订单代币类型的目的是什么。
范围订单
Range Orders
本质上并不是真正的订单,而是 LP 向资金池某个特定价格点提供的聚合流动性。虽然不是真正的订单,但「范围订单」所表现出的特性,却很好地模拟了限价单的基本功能。
https://docs.uniswap.org/protocol/concepts/V3-overview/range-orders
优点:Uniswap V3 引入了流动性分布的概念,允许其用户在价格范围内存入流动性。通过集中流动性,提高资本效率。当存入相同价值的资产时,可以获得更高的流动性和更低的滑点。在某个价格范围内提供流动性也在某种程度上降低了无常损失的风险。
缺点:用户在进行范围订单时只能存入某些类型的代币。因此无法实现买入止损订单和止损订单。
Uniswap V2 和 V3 在其 AMM 算法中引入了 CPMM 和流动性分布。提供价格范围内的流动性本质上使 Uniswap V3 成为一个通用的 AMM,能够通过改变其流动性分布成为任何可能的 AMM。
Balancer 的做市函数和交易公式:
Balancer⁸ 将 Uniswap V2 的 双代币池扩展到多代币池。Balancer 池中每种资产的价值都持有一个不变的权重,加起来为 1。不难证明,这相当于每种资产的储备数量的幂乘积是一个常数。资产 n 相对于资产 t 的价格也可以导出为资产 t 和 n 的储备数量之间的比率,通过它们的权重进行归一化。
Balancer⁸
A non-custodial portfolio manager, liquidity provider, and price sensor
https://balancer.fi/whitepaper.pdf
基于常数不变式,我们可以求导出有不同输入值的交易公式(资产 o 和资产 i 之间的交易)。在这种记法标准中,资产 o 始终是买出的资产。资产 i 是卖出的资产。A 和 B 是打入/接收的代币和当前的代币储备数量。我们还可以根据价格的变化计算打入的代币或买出的代币数量。
智能订单路由(SOR)算法:
Balancer 还引入了智能订单路由(SOR⁹) 算法。
SOR⁹
Smart Order Router V2
https://docs.balancer.fi/developers/smart-order-router
来源:https://docs.balancer.fi/v/v1/smart-contracts/sor/
该算法的总体思路是将一个订单分成几个小块在不同的Balancer池中进行交易,以获得更好的交易结果。假设我们要在代币池1和代币池2进行交易,如果我们要交易的总金额N低于上图中的A,我们将只在代币池1进行交易,因为代币池1的价格总是比代币池2价格好。如果总金额超过A,我们将部分订单在代币池1中交易,部分在代币池2中交易。在每个代币池中交易的数量将使每个池中的价格相等(B + C = N)。
很容易证明最优策略总是使每个池中的价格相等的策略(如果价格不相等,我们总是可以找到一个价格更好的池来改善我们的交易结果)。
价格函数,相对于交易量,通常是一个非线性函数。Balancer 将价格函数简化为线性函数。如果有n个代币池,最优策略可以表示为:
如果存在一个价格函数总是大于或小于范围 (0, N) 的其余价格函数,则应从上述计算中删除该价格函数和相应的池,以确保结果有效。如果价格函数总是较小,那么显然的最佳策略将是在该池中交换所有代币。
在这个计算中,不用考虑gas费用。实际上,最优策略应该是在路由收益和gas费用损失之间保持平衡。
SOR 算法,我们相信可以在更广泛的背景下使用。例如,价格函数可以是其他 AMM 协议池的函数。由于我们目前知识的限制,我们不确定实际的 AMM 聚合器是否使用相同的逻辑来实现更好的价格。没有任何价格函数近似的更通用的解决方案将在本文后面讨论。
优点:Balancer 将 2 个代币池推广到多个代币池,并引入 SOR 算法为其用户实现更好的价格。
缺点:“流动性池的强度取决于其最弱的资产。” 一个池中的代币类型越多,风险就越高。
Balancer 是一种多代币投资组合管理工具,允许灵活的代币价值分配,具有价格优化算法。
中篇目录
Curve 的 StableSwap 和交易公式- Curve V2 的动态权重、可定制的价格锚定和平滑的价格过渡
- Curve V2 在 2 代币池中的做市商函数
- 与 CPMM 和 StableSwap 相比,Curve V2 的价格函数
11. 价格重锚过程:Xcp 标准、EMA 价格预言机、相对价格变化步长 s
- Curve V2 的动态交易手续费
13. DEX 聚合器:Balancer SOR 算法的通用解决方案
14. Pivot 算法:解决无常损失问题的一种尝试
- 单边流动性解决方案
Curve 的 StableSwap 和交易公式:
Curve 将 恒定加和做市商 (CSMM) 和 恒定乘积做市商 (CPMM) 合并在一起,以实现更低的价格滑点。我们可以把这个算法看作是向 Uniswap/Balancer 模型添加一个固定价格部分,使最终的做市函数锚定于一个价格。
Curve¹⁰ V1,被称为 StableSwap,设计了用于稳定币交易的算法。它将 CSMM 与权重相乘并加上 CPMM:
Curve¹⁰ V1
StableSwap — efficient mechanism for Stablecoin liquidity
https://curve.fi/files/stableswap-paper.pdf
首先我们考虑一个特殊情况,即流动性池中每种代币的数量是相同的。很容易证明在平衡点处时这个方程成立( χ _是权重,与 D ⁿ⁻¹ 相乘以使 CSMM 和 CPMM 具有相同的数量级)。但是,当流动性池失衡时,如果 χ 是一个常数,则该等式将不再成立。因此,我们需要将 χ 变量化。Curve V1 选择了一种 χ 的函数形式,使它在流动性池极端不平衡时变为零,这意味着该方程由 CPMM 主导。在平衡点下, χ 等于 A 。 A 是一个常数,通过模拟历史数据进行优化。代入 χ _给了我们一个始终成立的方程。
接下来,让我们推导出 StableSwap 如何实际计算交易结果。根据当前池中的代币数量,我们可以计算出_ D 。例如,如果我们想换出代币 j ,我们可以将 xⱼ 分离开来并求解 xⱼ _的方程:
该方程可以简化为二次形式。可悲的是,现在链上 Vyper 语言里没有可以解二次方程的数学库。因此,StableSwap 使用了 牛顿法 来求解_ xⱼ 。迭代公式每次迭代都将其精度加倍。因此,可以在设定的 gas 上限内计算可接受的 xⱼ 。最后,交换前后 xⱼ _之间的差值将是购买的代币 j 的数量。
牛顿法
它是一种在实数域和复数域上近似求解方程的方法
https://en.wikipedia.org/wiki/Newton%27s_method
From StableSwap whitepaper
From StableSwap whitepaper
与 CPMM 相比,StableSwap 做市商受压、 以 x + y = 常数方向压平。这确保交易价格接近或等于 1,在平衡点附近有非常小的滑点(当池中的一个代币不接近几乎售罄时)。当池中的一个代币几乎售罄时,价格开始急剧下降。这很容易理解:函数的曲率 / 滑点被集中 / 推到别处,以确保在平衡点附近的低滑点。
该模型中的 CPMM 和动态权重被用于惩罚提前知道消息的大额订单,防止池中的代币被完全售罄。
优点: 通过添加 CSMM 和 CPMM 以及动态权重,Curve 的 StableSwap 实现了非常小的滑点,非常适合稳定币。
缺点: 价格始终锚定在 1。如果市场价格与流动性池价格显著不同,流动性池将被买空。因此,StableSwap 仅适用于稳定币。
Curve V2 的动态权重、可定制的价格锚定和平滑的价格过渡:
为了确保更平稳的价格过渡和可定制的价格锚定,Curve¹¹ V2 将动态权重_ χ 修改为 K _,如下所示:
Curve¹¹ V2
Automatic market-making with dynamic peg
https://curve.fi/files/crypto-pools-paper.pdf
K0 _在 0 (流动性池不平衡)和 1 (平衡点)之间变化, χ 和 K (以 A 归一化)作为 K0 _的函数绘制如下:
我们可以从上图中了解 Curve V2 如何使价格转变得平滑。它实际上使动态权重在远离平衡点时迅速下降。_ γ _值越小,下降越快。使动态权重快速下降到零本质上相当于强制函数表现得更像 CPMM,即使流动性池只是有一点不平衡。
DW 在 twitter¹² 上发布了一条很棒的推文,解释了相同的概念。
DW 在 Twitter¹²的推文
https://twitter.com/dken_w/status/1422623679150649345
价格过渡问题得到了解决。现在我们讨论 Curve V2 如何实现其他不是 1 的 价格锚定 。有一个价格锚定(他们在白皮书中称之为 价格标度 )意味着在做市曲线上存在一个平衡点,在平衡点处按价格标度缩放的代币数量相等:
Curve V2 在 2 代币池中的做市商函数:
缩放后的代币数满足与 StableSwap 类似的等式。以最简单的 2 币流动性池为例,做市商函数可以用 A、γ、p、D、x、y 表示。该函数可以简化为关于 x, y 的三次函数(关于 D 的六次函数)。
该函数的典型值图如下所示:
与 CPMM 和 StableSwap 相比,Curve V2 的价格函数:
也可以绘制代币 x 相对于代币 y 的价格曲线。在平衡点 (1000, 1000) 附近 Curve V2 价格函数恒定。与 StableSwap 相比,Curve V2 略微延迟了价格变动,而不是完全延迟。与 CPMM 相比,随着交易量的增加,价格开始以较小的滑点做出反应。总而言之,Curve V2 在平衡点附近实现了非常小的滑点,并且在其他区域比 CPMM 实现了更好的滑点。至于其他非 1 的价格锚定,我们只需更改上面三次 / 六次方程中的_ p _。因此, 锚定价格 的问题也解决了。
我们可以使用类似的在 StableSwap 中的牛顿法来计算交换结果。首先,我们根据池中当前的代币数量计算_ D _(这次使用牛顿法,因为方程要复杂得多)。其次,如果我们想换出代币 i,我们再次使用牛顿法来求解 xᵢ。同样,xᵢ的差异(按其价格标度归一化)将是我购买的代币数量(所有 xᵢ 都是按价格标度缩放的代币数量)。
为了确保多项式函数的根可以在设定的 gas 上限 内求解,Curve 白皮书讨论了他们选择的起始猜测,以及函数中的参数。他们使用一种称为模糊测试(假设框架)的方法来确定这些最佳值。目前,我们不知道有关此方法的任何详细信息,并且很想了解更多信息。
价格重锚过程:Xcp 标准、EMA 价格预言机、相对价格变化步长 s:
为了确保小滑点(在平衡点附近交易), Curve V2 通过改变价格标度不断重锚做市商函数。然而,价格重锚可能导致流动性提供者承受价值损失。Curve V2 引入了一个名为 Xcp 的变量来缓解这个问题:
如果一次重锚后的损失大于累积的 Xcp 的一半(原始 Xcp 增加的价值),则该算法将保持做市商函数不变。有几个问题我们想在未来回答,因为白皮书只简要讨论了 Xcp。查看其源代码可能会有所帮助。
- Xcp 值是否与用流动性池中当前代币数计算出的价值成正比?
- 存入或取出流动性是否计入 Xcp?
- 如果取出流动性计入 Xcp,如果 Xcp 减少幅度过大会阻止取出流动性吗?
对于价格重锚,Curve V2 使用 EMA (注:指数移动平均线)价格预言机来确定预言机价格。新的预言机价格向量由最近一次交易价格向量和前一个预言机价格向量的线性组合确定。新价格标度向量的变化方向与预言机价格相似,但不完全等于新预言机价格。他们通过引入相对价格变化步长 s,将价格标度向量滞后于预言机价格。该方程可以使用欧几里得几何轻松导出。EMA 价格预言机和价格标度延迟是为了减少近期价格波动的影响并更好地代表长期市场价格。
关于相对价格变化步长_ s ,根据我们“刷新 Curve 官网”的经验,部分流动性池的 s 变化频率至少为十分钟的量级以上。Curve V2 如何更新 s _是一个有趣的问题,超出了我们当前知识的范围。查看其源代码也会有所帮助。
下面显示了一个演示一次价格重锚过程的图:
假设我们在 x = 1000 开始我们的交易,并在 x = 1400 结束我们的交易。最初,价格锚定于 1 。交易后,价格移动到 0.6。为简化起见,仅出于演示目的,我们将新的价格标度设置为与现货价格相等(价格现在锚定于 0.6),并求解六次方程以获得_ D _。现在做市商函数锚定于 0.6,如上所示。
价格重锚本质上相当于找到一个新的做市商函数,该函数穿过当前代币数量位置(在 2 代币池情况下为 ( x, y )),在 ( x0, y0 ) 处有一个平衡点,使得_ y0/x0 为 等于 ( x0, y0 _) 处导数的绝对值。一个有趣的课题是获取真实的 Curve 流动性池参数,做一个更好的(可能是动画)价格重锚过程的演示。
Curve V2 的动态交易手续费:
由于上面讨论的 Curve V2 的做市商特性,将交易费用设为 2 级交易费用与动态权重的线性组合是合理的,衡量我们离平衡点有多远(当前价格变动是否更像是 StableSwap 或 CPMM)。Curve V2 选择的_ fmid 和 fout _值分别为 0.04% 和 0.4%。下图展示了 2 代币池中的费用如何变化(假设没有价格重锚或流动性变化):
优点: 做市商函数可以锚定于任何价格,适合所有代币,而不仅仅是稳定币。价格过渡比 StableSwap 更平滑。Curve V2 还根据其内部的价格预言机不断更新价格标度,以更好地代表市场价格,确保在平衡点附近交易。动态费用确保在此基础上提供甚至更好的价格。
缺点: 由于求解三次方程和六次方程,Gas 费用可能会更高。仅根据其内部价格预言机进行价格重锚可能存在风险。我们想知道在通过_ Xcp _标准时,是否存在价格标度与市场价格明显不同的情况。如果是这种情况,与其他预言机交叉检查价格可能会有所帮助。
Curve 的 StableSwap 和动态锚定 V2 是为了使交易滑点尽可能小。StableSwap 始终锚定于 1,而 V2 使锚定价格跟随市场价格。
下面将讨论 AMM 算法的一些最新进展和可能的改进。
DEX 聚合器:Balancer SOR 算法的通用解决方案 :
DEX 聚合器是聚合现有 AMM 协议以实现更好交易结果的协议。如上所述,Balancer 的 SOR 算法也适用于 DEX 聚合器,以确保数学上最优的交换策略。
Balancer 的 SOR 算法的一般解决方案,没有任何价格函数近似,可以表示如下:
因为价格函数可以是任何形式,具体取决于生成它们的 AMM 算法。这意味着满足总代币数量守恒和相等最终价格等条件的方程可能没有解析解。
因此,我们引入了一种在机器学习等领域常用的技术,称为梯度下降。我们将损失函数定义为不同价格函数值的方差。在选择一个起始猜测(一个简单的、不知情的猜测可以是每个池中的交易量相等_ N/n _)后,我们可以迭代(通过损失函数相对于该变量的偏导数改变每个交换量,乘以学习率 l ) 以获得最佳结果,在一定的误差接受范围内。
由于作为最终等价函数的总交易量是单调的,因此该方法应该能够找到全局最小值(方差 = 0)。同样,上面的计算假设没有简单的解决方案(没有价格函数总是大于或小于范围 (0, N ) 上的其余价格函数)。
Pivot 算法:解决无常损失问题的一种尝试 :
Pivot 算法试图通过使做市商函数经过一个固定点 (x0, y0) 来对其进行枢轴旋转。
( x0, y0 ) 处的价格将始终是设计的当前市场价格 Pt。这在概念上确保套利总是将流动性池带回到点 ( x0, y0 )。由于此功能,无常损失将为零。然而,实际上,该算法没有足够的参数来拟合当前储备( x,y )和( x0,y0 )。这意味着我们必须等待流动性池回到 ( x0, y0 ),然后更改做市商函数。
从上图中我们可以看出,交易后的点不在新的做市商函数上(蓝色和蓝色虚线)。如果当前市场价格低于当前储备的现货价格,则流动性池也可能没有任何动力回到 ( x0, y0 )。
我们想知道是否存在这样的函数通过 ( x, y ) 和 ( x0, y0 ) 以及在 ( x0, y0 ) 处的可调导数来适应市场价格。如果我们假设函数是凸的,那么市场价格不能小于这两个点之间的线性段斜率。因此,如果做市商函数必须是凸函数,则此问题可能没有完整的解决方案。
单边流动性解决方案 :
流动性提供者在存入流动性时可能不方便存入所有类型的资产。我想知道是否存在与 Bancor 采取的弹性供应方法不同的其他机制。直觉上,有两种解决方案:1. 首先使用相同的协议交换部分代币 2. 无论如何存入单边流动性,让套利将价格带回市场价格。
例如,我们希望将流动性存入一个等值的 2 代币池中。
我们只有代币 x。不难计算我们需要交换多少,以便交换后每种代币的价值相等。也很容易证明 β 总是在 0 和 1 之间,这意味着一个合理的结果。但是,交易后的价格可能与存入流动性时的价格不同。因此,我想知道协议是否真的将交换和流动性存入作为一项原子操作。进行交易时也存在价格滑点。到目前为止,Balancer 和 Curve 等协议如何处理单边流动性存入仍然是我们的一个问题。如果滑点很小,则进行上述操作是合理的。
Balancer and Curve 白皮书中描述的第二种方法是是直接存入单边流动性。这可能会大大改变价格。由此产生的套利也可能使无常损失变得重大。我们个人在 Balancer 白皮书和文档中没有看到任何惩罚措施。另一方面,Curve 在存入单边流动性时引入了一种称为不平衡费的东西,其范围从 0% 到 0.02%。在现实中,由于套利和无常损失,在第二种方法下存入单边流动性并没有真正的动机。
下篇目录
- 为 Curve V2 设计更好的动态权重
17. 当价格函数为非解析时应用价格范围
- Clipper:针对小额交易优化的 AMM 算法
- TWAMM:针对大额长期订单优化的 AMM 算法
- TWAMM 在恒定乘积做市商 (CPMM) 和对数市场评分规则 (LMSR) 上的应用
- TWAMM 在 YieldSpace 等与时间相关的 AMM 上的应用
- 结论和未来工作
为 Curve V2 设计更好的动态权重:
γ值
在 Curve V2 中,有一个常数称为 γ。如果我们也让它动态化,会发生什么?例如,我们可以使它成为 K0 的函数。最简单的情况是使其等于 K0。这里的动机是让函数在接近平衡点时表现得更像 StableSwap,当函数远离平衡点时,使其更像 CPMM。
紫色虚线曲线位于 StableSwap 和小 γ 值曲线之间,应该为我们提供 StableSwap 和 Curve V2 之间的做市商函数。然而,当我们绘制做市商函数时,它的图像跟 StableSwap 很相似:
这个问题有两种解决方案:1. 使 A 更小 2. 选择 K0 的较高幂数来表示γ。两者似乎都是可行的, 然而 1. 破坏了 A 作为一个大数的目的:使做市商函数与价格锚定。我们进行的进一步测试似乎表明,更改 A 不会对函数行为产生影响(更改 A 后做市商函数仍然看起来像 StableSwap)。
第二种解决方案会使 gas 费用更高。K0 的更高次幂数对应于我们需要求解的更高阶多项式方程。事实上,Curve V2 选择动态权重 K 的特定形式的原因是为了模拟大指数 K0 的函数行为,同时不使多项式的阶数更高。
有趣的问题是:我们能否找到一个更好的动态权重来简化我们需要求解的方程,同时保持与 Curve V2 相同或更好的功能?在设计这样的动态权重时,我们还必须记住,我们需要在小滑点和做市商函数对预知市场未来的大订单做出反应的能力之间保持平衡。显然,只有价格锚定的 StableSwap 在这方面是行不通的,因为如果锚定价格与市场价格不同,几乎所有的代币都会被买断。只有在保持这种平衡的情况下,价格重锚才可行。
当价格函数为非解析时应用价格范围 :
我们可以将价格范围概念应用于 Curve V2。由于没有关于池中代币数量的价格解析表达式,我们需要拟合价格和代币数量之间的关系。应用于做市商函数的偏移量由价格范围决定。编写这样的程序可以使资本效率更高。
Clipper:针对小额交易优化的 AMM 算法 :
Clipper¹³ 使用最适合小额交易需求的 AMM 算法。它将恒定乘积做市商 (CPMM) 和恒定总和做市商 (CSMM) 概括为两个极端情况(k = 1 和 k = 0)。
Clipper¹³ :New Invariants for Automated Market Making
https://github.com/shipyard-software/market-making-whitepaper/blob/main/paper.pdf
当只有两种类型的代币(X 和 Y)时,不变量可以简化为更简单的形式,其中 x0 和 y0 是初始流动性提供者设置的代币数量。以下是流动性池在不同 k 值下的行为。x 和 y 轴由 x0 和 y0 归一化。
较小的 k 值对应于 (1, 1) 附近的较低滑点(函数不太凸)。当 k 介于 0 和 1 之间时,不变函数可以与 x 和 y 轴相交。这意味着池中的代币可能会售罄。该交叉点的价格为零,这意味着该价格在转折点之前优于 CPMM 价格。过了转折点后,CPMM 的价格比较好。这可以在下图中说明:
再次对 x 轴进行归一化。随着我们远离初始点 (1, 1),X 代币相对于 Y 的价格下降。我们可以精确计算交点发生的位置:
优点: 通过引入 k,Clipper 在交易量较小时实现了更低的滑点(更好的价格)。Clipper 白皮书中的以下图表进一步证明了这一点。
From Clipper whitepaper
缺点: 当交易量超过一定门槛时,价格会明显低于 CPMM。
为了保证更好的价格,算法必须不断地价格重锚(改变 x0 和 y0)以保持当前池储备接近 (1, 1) 点。它可以使用与 Curve 相同的机制。该算法通过遵循其跟踪市场价格的内部价格预言机进行价格重锚。本质上,这等价于求解下面的公式,但这次 x, y 是已知的。P 由价格预言机给出。最后求解 x0 的这个方程给了我们新的平衡点。
这确保我们始终以较小的滑点接近市场价格进行交易。目前我们还没有调查 Clipper 是否实现了这一点,因为这在 Clipper 白皮书中没有解释。需要进一步查看其源代码。
价格范围概念也可以应用于 Clipper:
TWAMM:针对大额长期订单优化的 AMM 算法 :
在上面讨论的所有 AMM 中,我们一次只能在一个方向上进行交易。如果我告诉您最近出现了一种允许同时进行双向交易的算法呢?
TWAMM¹⁴(注:时间加权自动做市商,发音为“tee-wham”)算法将一段时间内的长期订单转换为无限小的虚拟订单的积分。订单可以两边同时进行。此外,在同一时间范围内、同一交易方向执行的订单会汇集在一起以简化计算。因此,一段时间内的长期订单以等于该时期时间加权市场价格的价格执行。
TWAMM¹⁴
https://www.paradigm.xyz/2021/07/twamm/
截至目前,只对于两种类型的 AMM,CPMM 和 LMSR (注:对数市场评分规则)存在解析形式的 TWAMM 解。
让我们考虑一般情况,在一段时间内,代币 X 的总销售额为 xin ,Y 的总销售额为 yin 。X 的卖出率为 _ f(t) _ ,Y 的卖出率为 g(t) 。从时间 t 到 _ t _ + _ dt _ 代币 X 数量的净变化可以计算为代币 X 的销售数量减去在此期间购买的代币 X 数量,汇率为 dy/dx 。由于在此期间代币 Y 的销售量无限小,因此可以使用现货价格作为实际汇率。
因此,我们得到一个非线性一阶微分方程。取决于 dy/dx 、 _ f(t) _ 和 g(t) 的形式,方程可能有也可能没有解析解。
TWAMM 在恒定乘积做市商 (CPMM) 和对数市场评分规则 (LMSR) 上的应用 :
当应用于 CPMM 时,方程可以被积分,如果 f(t)/g(t) 是一个常数,这意味着代币 X 和 Y 的销售策略是相同的。我们可以进一步简化表达式:
存在这个积分的解析表达式。利用双曲函数的性质,我们可以得到一个漂亮的最终解(交易后池中的代币 X 数),它只取决于池的原始位置 _ (x0,y0) _ 和 _ xin,yin _ 。由于 CPMM 的做市商函数关于 _ x _ 和 y 完全对称,因此也可以通过在 xend 的最终表达式中交换 xin 和 yin、x0 和 y0 的位置来表示最终的代币 Y 数。代币 X 数和代币 Y 数的乘积正如预期的那样等于 k。
这种源自 CPMM 的微分方程形式,实际上有一个数学名称叫做“Riccati 方程”。Riccati 方程的一般形式如下:
Riccati 方程没有一般的解析解。但是,存在可以求解 Riccati 方程的特殊情况。有一篇论文¹⁵讨论了这些案例。如果 Riccati 方程的系数满足这个条件:
论文¹⁵:Analytical solutions of the Riccati equation with coefficients satisfying integral or differential conditions with arbitrary functions
https://arxiv.org/abs/1311.1150
则 Riccati 方程可以转化为 Bernoulli 型方程。Bernoulli 型方程可以很容易地求解。这应该给我们与以前相同的结果。从上面我们可以看出,满足这个条件与保持 f(t)/g(t) 恒定相同,这是我们在第一种求解微分方程的方法中假设的。
当 _ f(t)/g(t) _ 不是常数时,我们可以选择什么形式的 _ f(t) _ 和 _ g(t) _ 使微分方程具有解析解仍然是一个悬而未决的问题。找到这样的解决方案会给我们更多的选择(代币 X 和 Y 的销售策略不必相同)。
现在让我们将 TWAMM 应用到 LMSR:
同样,我们假设销售策略是相同的。然后可以对微分方程进行积分。我们可以进一步简化最终的代币 X 和 Y 数量表达式为:
同样,当销售策略不同时,也不能保证微分方程具有解析解。
一旦我们获得了 _ xend _ 和 _ yend _ ,我们就可以计算出每方将收到多少代币 X 和代币 Y:
由于在此期间,同一交易方向的所有订单都汇集在一起。每个个体交易者将根据他对 _ xin _ 和 _ yin _ 的贡献比例获得他应得的代币份额。
优点: TWAMM 通过允许交易对手同时对这些大订单进行交易,从而使大订单的价格滑点更小。在最理想的情况下( _ xin/yin _ = x0/y0 ),可以实现零滑点交易。在这种情况下, _ xend _ = x0 , _ yend _ = _ y0 _ ,TWAMM 可以理解为充当了订单簿,在不提供流动性的情况下在双方之间交换代币。长期订单被分解成无限小的订单,这些订单在区块之间虚拟执行。由于这种性质,它不太容易受到 三明治攻击 ,因为攻击者必须在块的末尾放置一个命令,并在下一个块的开头放置另一个命令。
缺点: 如果我们允许订单在任何时候到期,gas 费用可能会非常高。这是因为我们必须多次计算积分结果(在论文中他们称之为“懒惰计算”)。在最坏的情况下,我们必须计算每个块的结果。因此,在实践中我们必须让订单在某些区块到期以简化计算。此外,TWAMM 使用的流动性池必须与现有的流动性池不同,因为没有虚拟订单和懒惰计算的概念。普通交易者在与 TWAMM 交互时不想支付懒惰计算产生的额外 gas 费用(只要有人与之交互,流动性池就会更新)。
TWAMM 在 YieldSpace 等与时间相关的 AMM 上的应用 :
我们还可以将 TWAMM 应用于与时间相关的 AMM,例如 YieldSpace¹⁶:
YieldSpace¹⁶:An Automated Liquidity Provider for Fixed Yield Tokens
https://yield.is/YieldSpace.pdf
做市商函数有两种形式,这两种形式都会导出目前我们不知道如何求解的微分方程。在第二种形式的情况下,微分方程可以简化为单个微分方程。
结论和未来工作 :
我们希望这篇综合性的、介绍性的、学习笔记风格的论文能够为对 AMM 算法一无所知的人和有更多经验的人提供一些见解。
总而言之,AMM 算法的核心基本上是关于做市商函数的设计及其曲率分布的操纵。显然,我们需要阅读另一篇 Guillermo Angeris 和 Tarun Chitra 写的论文¹⁷,其中详细讨论了这一点。除此之外,还有高效的价格解决方案(如 DEX 聚合器)和高效的流动性提供解决方案(如价格范围)。最近的 TWAMM 算法阐明了我们如何使用 AMM 算法来实现中心化交易中常见的订单簿类型的撮合。我们相信 AMM 算法的未来将更接近订单簿风格。
Guillermo Angeris 和 Tarun Chitra 写的论文¹⁷:Improved Price Oracles: Constant Function Market Makers
https://arxiv.org/abs/2003.10001
至于未来的工作,我们计划对本文中提到的一些问题进行更深入的挖掘。这包括阅读论文 [4]、[5]、[7]、[16]、[17],推导其他 AMM 的无常损失公式,推导其他 AMM 的流动性分布,了解模糊测试的工作原理,回答我们提出的关于 Xcp 的 3 个问题,更多地了解如何选择最有效的价格预言机和 s 值,制作 Curve 价格重锚过程的动画,了解更多关于单边流动性的创新,尝试设计更好的动态权重 K,将价格范围应用于 其他 AMM,将 TWAMM 应用到其他 AMM 并找到更多解析解。
作者感谢 Fangyuan Zhao、Showen Peng、DW 对本文研究课题提出十分有用的意见。作者还要感谢火币研究院的 Lianxuan Li。作者特别感谢 Paradigm 的 Dave White 和 Dan Robinson 邀请加入 TWAMM 讨论组以及他们富有洞察力的讨论。同时也要感谢 BTX Capital 的 Vanessa Cao 和 Jane Hu 对本文的翻译和排版。