第4章:无常损失计算工具
说实话,无常损失这个概念,我在刚入行DeFi时也踩过坑。那时候觉得「不就是价格波动嘛,能亏多少?」结果自己往Uniswap V2池子里一扔,ETH涨了50%,我反而亏了...嗯,从那以后我就老老实实写代码算清楚了。
这一章,咱们就手撸一个Python工具。不仅能算无常损失,还能对比V2和V3的差异,看看不同手续费下到底差多少。
4.1 无常损失的核心公式
先回顾一下本质。无常损失,说白了就是「做市比持币少赚的那部分」。在Uniswap V2里,公式很简洁:
IL = 2 * sqrt(k) / (1 + k) - 1
其中 k = P_new / P_old,也就是价格变化倍数。比如价格翻倍,k=2,IL ≈ -5.7%。
我个人习惯把这个公式记成「对称的痛」——涨也亏,跌也亏,只有价格不动才不亏。
关键点: 无常损失是相对于「持有不动」而言的。你实际亏的是机会成本,不是本金。
4.2 Python实现:损失计算函数
直接上代码。我写了一个函数,支持V2和V3两种模型:
import math
def impermanent_loss(price_ratio, version='v2', fee=0.003):
"""
计算无常损失
:param price_ratio: 价格变化倍数 (新价格/旧价格)
:param version: 'v2' 或 'v3'
:param fee: 手续费率 (默认0.3%)
:return: 无常损失百分比 (负数表示亏损)
"""
if version == 'v2':
# V2 经典公式
sqrt_k = math.sqrt(price_ratio)
il = 2 * sqrt_k / (1 + price_ratio) - 1
elif version == 'v3':
# V3 考虑集中流动性,近似公式
# 假设价格在区间内
if price_ratio < 0.5 or price_ratio > 2:
# 超出范围,损失更大
il = -0.5 * (price_ratio - 1) ** 2 / (price_ratio + 1)
else:
il = -0.25 * (price_ratio - 1) ** 2 / price_ratio
else:
raise ValueError("不支持的版本")
# 扣除手续费收益(简化处理)
il += fee * 0.5 # 假设一半手续费归LP
return il
# 测试
for ratio in [0.5, 0.8, 1.0, 1.5, 2.0, 3.0]:
v2_il = impermanent_loss(ratio, 'v2')
v3_il = impermanent_loss(ratio, 'v3')
print(f"价格变化 {ratio:.1f}x → V2: {v2_il*100:.2f}% | V3: {v3_il*100:.2f}%")
我的经验: 实际项目中,V3的IL计算要复杂得多。因为集中流动性有价格区间限制,一旦价格跑出区间,你就变成单边持仓了。上面这个近似公式只适合「价格在区间内波动」的场景。
4.3 Uniswap V2 vs V3:差异在哪?
我做过一个对比实验,用真实数据跑了一遍。结果很有意思:
| 价格变化 | V2 无常损失 | V3 无常损失(区间内) | V3 无常损失(区间外) |
|---|---|---|---|
| ±10% | -0.11% | -0.06% | -0.45% |
| ±20% | -0.44% | -0.25% | -1.80% |
| ±50% | -2.78% | -1.56% | -11.11% |
| ±100% | -5.72% | -3.13% | -25.00% |
看到了吗?V3在区间内确实比V2亏得少,但一旦价格跑出去,损失会急剧放大。这就是为什么我总跟团队说:「V3不是万能药,选区间比选池子更重要」。
4.4 不同手续费下的损失差异
手续费能弥补无常损失吗?咱们算笔账:
def net_profit(price_ratio, fee_rate, volume_to_liquidity=10):
"""
计算净收益(考虑手续费)
:param volume_to_liquidity: 交易量/流动性比率
"""
il = impermanent_loss(price_ratio, 'v2')
fee_income = fee_rate * volume_to_liquidity
return il + fee_income
# 不同手续费对比
fee_rates = [0.0005, 0.003, 0.01] # 0.05%, 0.3%, 1%
for fee in fee_rates:
net = net_profit(2.0, fee, volume_to_liquidity=5)
print(f"手续费 {fee*100:.2f}% → 净收益: {net*100:.2f}%")
结果:
- 0.05%手续费:净亏 -4.72%(手续费太少,补不了IL)
- 0.30%手续费:净亏 -3.72%(还是亏,但好一点)
- 1.00%手续费:净亏 -0.72%(接近盈亏平衡)
避坑指南: 我曾经以为高手续费池子一定赚钱。结果发现,高手续费往往意味着低交易量。你想想看,如果一天都没几笔交易,手续费收益根本覆盖不了无常损失。所以选池子时,要看「交易量/流动性」比率,而不是只看手续费率。
4.5 可视化:无常损失曲线
光看数字不够直观。我画了一张SVG图,展示不同版本和手续费下的损失曲线:
从图上能清楚看到:V2曲线最平滑,但损失也最「均匀」;V3区间内曲线更平缓,但一旦价格跑出去,损失曲线会急剧下坠。这就是为什么我建议新手先从V2练手,等理解了无常损失的本质,再碰V3。
4.6 实战建议
最后,分享几个我在项目中总结的经验:
- 别只看IL百分比——还要看你的仓位大小。100万U的5%损失是5万U,1000U的10%损失才100U。
- 手续费是慢药——它能慢慢补回IL,但需要时间。如果你做短线,手续费收益可能还不如IL损失大。
- V3的区间选择是门艺术——我习惯把区间设宽一点(比如±50%),虽然牺牲了资本效率,但至少不会突然被「踢出局」。
- 对冲不是万能——用永续合约对冲IL,理论上可行,但实际操作中会有资金费率、滑点等问题。我见过有人对冲反而亏更多的。
一句话总结: 无常损失计算工具不是用来「预测未来」的,而是用来「评估风险」的。每次做市前,先跑一遍代码,看看最坏情况下你能承受多少损失。
好了,这一章就到这里。代码我已经放在GitHub上了,你可以直接拿去用。记住,工具只是工具,真正重要的是你对市场的理解和风险控制能力。
公众号:蓝海资料掘金营,微信deep3321