# Curve A 参数五论之二：调整 A 带来的曲线变化及损益

By [observerdq](https://paragraph.com/@observerdq-2) · 2023-06-28

---

_（ 本人twitter：_[_@observerdq_](https://twitter.com/observerdq) _）_

2020 年 4 月 17 日，离 312 已一个多月，DAI 依然是正向脱锚状态，价格在 1.02 左右。

Michael（Curve 创始人）在推特上发起了一个[投票](https://twitter.com/CurveFinance/status/1250866482159841280)，看大家是否支持把 Compound pool 的 A 参数从 900 调到 400。

![](https://storage.googleapis.com/papyrus_images/4c1c44784bff83c2b64e9e5b0d856a55d49cb2010ceb341300104750b8b4c9ae.png)

49 人参与了投票，但回复者仅一人。8 个小时后，Michael 把 A 调到了 400，又发了一则[推特](https://twitter.com/CurveFinance/status/1250988019886120960)，0 回复。

在那个当下，能真正参与讨论这个议题的，寥寥无几。Michael 可能沉浸在一个人的试验之中，调试参数、观测、改进，在 Telegram 的只言片语中，我感受到了他的兴致和乐趣。

回到这次 A 参数的调整，带来了日化约 0.1% 的损失。

![](https://storage.googleapis.com/papyrus_images/918b92a1f1c12eb325c1f2b8217a296a449e9c71bd6c2a597760b24319f08ff7.jpg)

我的这一篇，就是想讲清楚 A 调整了之后，到底意味着什么？为什么会带来损失？

不同 A 值对应曲线的一个图示
---------------

我挑选了一组实际参数设定，进行图示呈现。本文的讨论对象是 Curve V1 pool，曲线公式见 V1 [白皮书](https://classic.curve.fi/files/stableswap-paper.pdf)。

黑色曲线对应的参数为：`A = 10     D = 20,000`

![](https://storage.googleapis.com/papyrus_images/9c799f9dcf1b6af38284b97b4d85ca018b183821f498c3502dbedc943b5e0ada.png)

当前池子处于黑色点，X\_token、Y\_token 的数量分别为 2500 / 18105，价格约为 1 X\_token = 1.36 Y\_token。

此刻将 A 降为3，曲线将变成红色线。这条曲线的参数为：`A = 3     D = 19,022`

比较红黑二曲线，很明显的，黑色曲线中趋近直线的比例更多，这也是 A 之核心作用，A 越大，价格 1 附近的流动性越多；黑色曲线的 A（10）高于红色曲线的 A（3）。相应地，远离价格 1 的区间的流动性，则是红色曲线要多过黑色曲线。

在那则推特投票的时刻，DAI 有些脱锚，如果是使用低 A 值的红色曲线，就能比高 A 值的黑色曲线提供更多的流动性，这也是 Michael 想调整 A 的原因，他希望池子能捕获更多手续费。

我们再回到将 A 降为 3 带来的变化，降为 3 的那个瞬间，池子内两种 token 的数量并没有变化，但 D 值发生了变化。此外，图中还能看出，当前点的切线斜率发生了变化，曲线形状亦发生了变化。

以下专门探讨这些变化。切线斜率、曲线形状的变化，若换一角度考察，会更加直观。D 值的变化，则涉及到了池子损益评估的话题。

订单簿视角来看 A 值调整后的变化
-----------------

Curve 池子可以从订单簿的角度去理解。单个池子，根据其 A、D 参数的不同，对应着在所有价格点上的挂单数量的不同分布，并且所有的挂单是联动的、整体性的存在。

上一节的案例里，当 A 从 10 降为 3 的瞬间，可以理解为所有的挂单瞬间做了一次整体性大调整，从黑色的一组挂单集合转换成了红色的挂单集合。

![](https://storage.googleapis.com/papyrus_images/ea61260ccda8d398cfa61c940a966286cf288b930656f6d1051a468ae591e21e.png)

先对上图做一些基本说明。

横轴是价格，1.00 代表 1 X\_token = \[ 1.00 ~ 1.01 ) Y\_token，1.01 代表 1 X\_token = \[ 1.01 ~ 1.02 ) Y\_token，以此类推。为了节省空间，我将价格 < 1.00 的挂单略去了。

竖轴表示 Y\_token的数量（即对 X\_token 的买单挂单）。黑色部分在价格 > 1.36 的区间没有数据，这是因为在黑色曲线上的当前价格是 1.36，> 1.36 意味着 X\_token 的更高价卖单挂单。这张图仅考察使用 Y\_token 进行买入挂单的部分，因此 > 1.36 的部分无数据。

我们看黑红的对比。首先，当前价格发生了变化，对应着前一节提到的切线斜率的变化。A 调整后，当前价格瞬间变动到了 1.92，红色部分的挂单延展到了 1.92。也就是说，有一定数量的 Y\_token 在 1.36 - 1.92 的价格区间内分批挂出了对 X\_token 的买单。

这其实是很奇怪的变化，一个 DEX 的当前价格在没有 swap 的情况下，竟然发生了变化。我们立刻可以想到，这将形成和市场价格的价差，我们假设套利者会瞬间介入把价格打到 1.36。

此外，可以看到从 1.00 - 1.36 的每一个价格点上的挂单数量都有所不同，整体而言，高位挂单的数量更多。这对应着上一节提到的曲线形状的变化。

A 调整带来的损益 - 最直接的计算方式
--------------------

Michael 的推提及了 Compound pool A 参数的调低会带来一些损失（ ‘wipe one day’s profits’ ）。在讨论背后的数学关系之前，需要先把“损失/损益”定义清楚。

> There are 2 ways to measure profit - with and without impermanent loss. - [Michael](https://t.me/curvefi/12066)

按照最直接的想法，定义损益很简单，将两个 token 的价值折算成 U 或是其中任意一个（X\_token 亦或 Y\_token），二维转一维，然后对比 A 调整前后的总价值。这也是 Michael 提到的 ‘with impermanent loss’。

不妨先简要讨论这个意义上的损益。   为求简化，所有的讨论暂且假设手续费 = 0。

还是基于前文一直用的示例，A 调低后，X\_token 的瞬时价格变高，套利者介入，把价格打回 A 调整前的价格，这便会带来损失。道理很简单，上一节提到，A 调低后，相当于按照高于市场价的价格挂了很多对 X\_token 的买单，这些不正常的买单被套利者吃掉，这必然会带来损失。

从曲线图上看得会更加清晰。

![](https://storage.googleapis.com/papyrus_images/0dfb7c6ef5c6a688922cc18210b2b37a2446dbcccd9d04c13f9e358046e19af3.png)

黑色点和黑色曲线是调整前池子的状态，对应价格为 1.36 。A 调低后，池子按红色曲线运行，调低的瞬间，池子价格变成 1.92，套利者介入使得池子的状态很快从黑色点移到红色点，对应着 1.36 的价格。

需要比较 A 调整前后的池子总价值，方法比较简单。

*   先看 A 调整后的总价值（套利者介入后）。找出红色曲线在红色点处的切线和 Y 轴的交点，即为两种 token 按现价折算成单一 Y\_token 的数量。
    

![](https://storage.googleapis.com/papyrus_images/87a01c635a0c40b4b6d9ce91d620a4456339f16c49ac42c593d0c693db82a86b.png)

*   再看 A 调整前的总价值。找出黑色曲线在黑色点处的切线和 Y 轴的交点。因为 A 调整前后的价格是一样的（套利者介入后），因此这条切线和第一步里的切线平行。
    
*   显然，黑色切线与 Y 轴的交点更高，也就是 A 调整前的总价值更高。A 调低带来了总价值的损失。
    

以上讨论仅限于 A 调低后的瞬时损失，还算简单。但若把追踪时间拉长，想探讨后续不同价格走势下 A 调低所带来的长期损益，就变得有些复杂。这取决于价格往更加脱锚的方向去发展、还是回归完美的锚定，A 调整后的总价值可能会不如不调整 A 的状态、也有可能会高过。这里暂不展开，本文的目的仅在简要演示一番 A 调整是如何影响到池子总价值的，并不求完整系统的论述。

剔除无常的损益评估
---------

按照两个 token 的当前价格折算，也就是考虑进无常，这是最直观的度量方法，但这种方法较为麻烦。Curve 引入了另一种独特的损益评估法，剔除了无常的因素，简化了计算，在大部分情况下也能够适用。

这就是 D 值，D 值是 Curve 曲线公式在 A 之外的另一核心参数。我们在 Curve 官网每个池子里看到的 virtual price 即为根据 D 值计算得出。

![](https://storage.googleapis.com/papyrus_images/4b5545602ac81757d3ff8c4f7ae56465b2611946d05ee5bf7b5a00ca96386050.png)

D 值，就是当池子价格是 1（完美锚定）的时候，池子内两种 token 的总数量。因为此刻价格是 1，因此可以把两种 token 的数量简单相加。池子价格等于 1 的点，即为曲线和 x=y 这条直线的交点。

![](https://storage.googleapis.com/papyrus_images/81c70487a093217b9d9e5436349a2d3ded7621da78ff652a266bf509ef4801d2.png)

回到前述示例，A 调低以后，很显然，D 值变小了。因此，长期来讲如果价格能够恢复锚定的话，D 值的变化能够反映出因为 A 调整带来的损失。

我上文使用的示例中，当前价格是 1.36，这其实是比较极端的情况。我们看 Curve V1 类池子，比如主流的稳定币/ LSD 池子，价格都不会偏离 1 太多。在价格接近 1 的时候，无常的影响很小，因此可以直接用 D 值的变化来近似反映损益。

D 值，作为一维的度量衡，且作为池子的参数之一，便于计算、便于追踪历史数值，比较适合用来近似地评估损益。

结语
--

A 参数的调整相当于在订单簿所有价格点上的挂单的一次重排，改变了当前价格点，改变了 D 值，带来了损益。

因此，A 参数的一次性大幅调整有一种突兀感，甚至有一种瑕疵感。白皮书内对 A 的动态管理并无涉及，或许是在 Curve 上线实际运行了一段时间后，Michael 才渐渐认识到了对 A 参数的调整方式需要修正。在宣布 Compound pool A 参数调整完毕的那则推特下，Michael 跟了一句评论。后续新版本的池子，A 参数的调整改成了一段时间渐变完成的模式。

![](https://storage.googleapis.com/papyrus_images/63266ed991c63c7c992fd29263f399e2a9e8e69c00dd296013a8566ff49ff653.png)

老池子 A 参数的一次性调整方式仅仅是瑕疵感么？没这么简单，背后还深藏了一个可被攻击的点。幸运的是，发现这个脆弱点的是白帽（对协议理解的深度真是天外有天）。后续会单写一篇讲述这个攻击方法。

---

*Originally published on [observerdq](https://paragraph.com/@observerdq-2/curve-a-a-2)*
