主题切换
13.4 DEX流动性做市
AMM 模型的数学基础
自动做市商(Automated Market Maker, AMM)是去中心化交易所的核心机制。与传统订单簿不同,AMM 使用数学公式而非买卖双方报价来确定价格。
名词解释:AMM(Automated Market Maker)
一种基于恒定函数(如恒定乘积)的自动定价机制,流动性提供者将资产存入流动性池,交易者直接与池子交互,价格由池中资产比例决定。
Uniswap V2:恒定乘积模型
Uniswap V2 使用最简单的 AMM 公式——恒定乘积:
$$x \cdot y = k$$
其中
$$(x + \Delta x)(y - \Delta y) = k$$
由此可推出交易者获得的资产数量:
$$\Delta y = y - \frac{k}{x + \Delta x} = \frac{y \cdot \Delta x}{x + \Delta x}$$
此处有展示代码展开 ▼
python
import numpy as np
def uniswap_v2_swap(x, y, dx, fee=0.003):
"""
Uniswap V2 交易计算
x: 池中资产 X 的数量
y: 池中资产 Y 的数量
dx: 输入资产 X 的数量
fee: 手续费率 (0.3%)
返回:获得的资产 Y 数量,有效成交价格
"""
dx_after_fee = dx * (1 - fee)
dy = (y * dx_after_fee) / (x + dx_after_fee)
effective_price = dx / dy # 实际成交价格
# 新状态
new_x = x + dx
new_y = y - dy
new_price = new_x / new_y # 新边际价格
return {
'amount_out': dy,
'effective_price': effective_price,
'new_marginal_price': new_price,
'price_impact': (effective_price - x / y) / (x / y)
}
# 示例:用100 USDC 在 ETH-USDC 池中买入 ETH
pool_usdc = 1000000
pool_eth = 500
amount_in = 100 # USDC
result = uniswap_v2_swap(pool_usdc, pool_eth, amount_in)
print(f"获得 ETH: {result['amount_out']:.6f}")
print(f"成交价格: ${result['effective_price']:.2f} per ETH")
print(f"价格冲击: {result['price_impact']*100:.4f}%")点击展开可浏览运行结果
获得 ETH: 0.049845 成交价格: $2006.22 per ETH 价格冲击: 0.3109%
Uniswap V3:集中流动性
Uniswap V3 的革命性改进是集中流动性(Concentrated Liquidity):LP 可以选择一个价格区间
对于在区间
$$(x + x_{\text{virtual}})(y + y_{\text{virtual}}) = L^2$$
其中
此处有展示代码展开 ▼
python
def uniswap_v3_position(amount_x, amount_y, P_current, P_lower, P_upper):
"""
Uniswap V3 流动性头寸计算
amount_x: 提供的资产X数量
amount_y: 提供的资产Y数量
P_current: 当前价格
P_lower: 做市价格下限
P_upper: 做市价格上限
"""
sqrtP = np.sqrt(P_current)
sqrtPa = np.sqrt(P_lower)
sqrtPb = np.sqrt(P_upper)
# 计算流动性 L
if P_current <= P_lower:
# 全仓资产 X
L = amount_x * (sqrtP * sqrtPb) / (sqrtPb - sqrtP)
elif P_current >= P_upper:
# 全仓资产 Y
L = amount_y / (sqrtP - sqrtPa)
else:
# 两种资产都有
L_x = amount_x * (sqrtP * sqrtPb) / (sqrtPb - sqrtP)
L_y = amount_y / (sqrtP - sqrtPa)
L = min(L_x, L_y)
# 计算区间内的实际资产数量
if P_current <= P_lower:
x_real = amount_x
y_real = 0
elif P_current >= P_upper:
x_real = 0
y_real = amount_y
else:
x_real = L * (sqrtPb - sqrtP) / (sqrtP * sqrtPb)
y_real = L * (sqrtP - sqrtPa)
return {
'liquidity': L,
'x_real': x_real,
'y_real': y_real,
'position_value': x_real * P_current + y_real,
'capital_efficiency': (x_real * P_current + y_real) / (amount_x * P_current + amount_y)
}
# 示例:在 ETH=2000 USDC 的价格下做市
pos = uniswap_v3_position(
amount_x=1, # 1 ETH
amount_y=2000, # 2000 USDC
P_current=2000,
P_lower=1800,
P_upper=2200
)
print(f"流动性: {pos['liquidity']:.2f}")
print(f"资金效率: {pos['capital_efficiency']:.2%}")点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `uniswap_v3_position`(Uniswap V3 流动性头寸计算)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。
无常损失的量化
无常损失(Impermanent Loss, IL)是 AMM 做市的核心风险,指相对于简单持有资产(HODL),向流动性池提供流动性的价值损失。
对于 Uniswap V2,当价格从
$$IL = 1 - \frac{2\sqrt{P_1/P_0}}{1 + P_1/P_0}$$
此处有展示代码展开 ▼
python
def impermanent_loss(P_ratio):
"""
计算无常损失
P_ratio: 价格变动倍数 P_new / P_initial
返回:无常损失百分比
"""
return 1 - (2 * np.sqrt(P_ratio)) / (1 + P_ratio)
def il_with_fees(P_ratio, fee_apr, holding_period_years):
"""
考虑手续费收入后的净无常损失
"""
il = impermanent_loss(P_ratio)
fee_income = fee_apr * holding_period_years
net_return = fee_income - il # 正值为赚钱
return {
'impermanent_loss': il,
'fee_income': fee_income,
'net_return': net_return
}
# 无常损失对照表
print("无常损失随价格变化的对照表:")
print(f"{'价格倍数':<12} {'无常损失':<12}")
for ratio in [0.5, 0.75, 0.9, 1.0, 1.25, 1.5, 2.0, 3.0, 5.0]:
il = impermanent_loss(ratio)
print(f"{ratio:<12.2f} {il*100:<12.4f}%")
# 示例:价格涨1倍,IL约5.7%
print(f"\n价格翻倍时的IL: {impermanent_loss(2.0)*100:.2f}%")点击展开可浏览运行结果
无常损失随价格变化的对照表: 价格倍数 无常损失 0.50 5.7191 % 0.75 1.0257 % 0.90 0.1386 % 1.00 0.0000 % 1.25 0.6192 % 1.50 2.0204 % 2.00 5.7191 % 3.00 13.3975 % 5.00 25.4644 % 价格翻倍时的IL: 5.72%
无常损失的关键认知:
- 价格变动 1.5 倍(向上或向下),无常损失约 2%
- 价格变动 2 倍,无常损失约 5.7%
- 价格变动 5 倍,无常损失约 25.5%
- 无常损失是 对称的(涨和跌造成的损失相同)
- 只要价格回到原始位置,无常损失就消失(所以叫"无常")
集中流动性做市策略
V3 的集中流动性做市本质上是一个 Gamma 交易问题:做市商赚取手续费,但需要不断调仓以适应价格变动。
最优做市区间选择
此处有展示代码展开 ▼
python
def optimal_lp_range(volatility_daily, expected_fee_apr, horizon_days, risk_tolerance=0.05):
"""
基于波动率确定最优做市区间
volatility_daily: 资产日波动率
expected_fee_apr: 预期年化手续费收益
horizon_days: 做市期限(天)
risk_tolerance: 愿意接受的IL上限
"""
# 预期价格变动范围(基于波动率)
vol_period = volatility_daily * np.sqrt(horizon_days)
# 使用 Black-Scholes 风格的置信区间
from scipy.stats import norm
z_score = norm.ppf(1 - risk_tolerance / 2) # 双边置信度
# 价格倍数的上下限
P_upper_mult = np.exp(z_score * vol_period)
P_lower_mult = np.exp(-z_score * vol_period)
# 检查此范围下的最大IL是否可接受
max_il = max(impermanent_loss(P_upper_mult), impermanent_loss(P_lower_mult))
expected_net = expected_fee_apr * horizon_days / 365 - max_il
return {
'upper_mult': P_upper_mult,
'lower_mult': P_lower_mult,
'max_impermanent_loss': max_il,
'expected_fee_income': expected_fee_apr * horizon_days / 365,
'expected_net_return': expected_net,
'recommended': expected_net > 0
}点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `optimal_lp_range`(基于波动率确定最优做市区间)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。
自动再平衡策略
当价格接近区间边界时,LP 需要决定是否提取流动性并重新部署在新区间:
此处有展示代码展开 ▼
python
def rebalance_decision(P_current, P_lower, P_upper, gas_cost_eth, position_value_eth):
"""
判断是否应该进行再平衡
"""
range_width = (P_upper - P_lower) / ((P_upper + P_lower) / 2)
# 价格接近区间边界的阈值
rebalance_threshold_low = P_lower * 1.05 # 价格在5%内触及下限
rebalance_threshold_high = P_upper * 0.95 # 价格在5%内触及上限
if P_current <= rebalance_threshold_low or P_current >= rebalance_threshold_high:
# 评估再平衡成本 vs 收益
# 退出成本 = gas 费用
exit_cost = gas_cost_eth * 2 # 退出 + 重新进入
# 停留在原区间的预期损失
if P_current <= P_lower:
expected_loss_out_of_range = position_value_eth
else:
expected_loss_out_of_range = 0
# 再平衡决策
rebalance = expected_loss_out_of_range > exit_cost * 5 # 5倍收益/成本比
return {
'should_rebalance': rebalance,
'reason': f"价格 {P_current:.2f} 接近{'下限' if P_current <= rebalance_threshold_low else '上限'}",
'estimated_gas_cost_eth': exit_cost
}
return {'should_rebalance': False, 'reason': '价格在合理区间内'}点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `rebalance_decision`(判断是否应该进行再平衡)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。
LP 收益模拟与优化
此处有展示代码展开 ▼
python
def simulate_lp_returns(initial_price, volatility, fee_apr, horizon_days,
n_simulations=1000, v2=True, v3_range_multiplier=1.5):
"""
蒙特卡洛模拟 LP 收益分布
"""
import numpy as np
daily_vol = volatility / np.sqrt(365)
results = []
for _ in range(n_simulations):
# 生成价格路径
returns = np.random.randn(horizon_days) * daily_vol
price_path = initial_price * np.exp(np.cumsum(returns))
final_price = price_path[-1]
if v2:
# V2: 全区间做市
P_ratio = final_price / initial_price
il = impermanent_loss(P_ratio)
else:
# V3: 区间内做市
P_lower = initial_price / v3_range_multiplier
P_upper = initial_price * v3_range_multiplier
# 检查价格是否跑出区间
out_of_range = np.any((price_path < P_lower) | (price_path > P_upper))
if out_of_range:
# 简化:价格跑出区间则承受更大的IL
il = impermanent_loss(final_price / initial_price) * 0.5
else:
# 区间内IL更小(资本效率更高)
il = impermanent_loss(final_price / initial_price) * 0.3
fee_income = fee_apr * horizon_days / 365
net_return = fee_income - il
results.append(net_return)
results = np.array(results)
return {
'mean_return': results.mean(),
'median_return': np.median(results),
'std_return': results.std(),
'win_rate': (results > 0).mean(),
'var_95': np.percentile(results, 5),
'sharpe': results.mean() / results.std() if results.std() > 0 else 0
}
# V2 vs V3 比较
v2_result = simulate_lp_returns(100, 0.80, 0.15, 30, v2=True)
v3_result = simulate_lp_returns(100, 0.80, 0.25, 30, v2=False, v3_range_multiplier=1.5)
print("Uniswap V2 LP 模拟:")
for k, v in v2_result.items():
print(f" {k}: {v:.4f}")
print("\nUniswap V3 集中流动性 LP 模拟:")
for k, v in v3_result.items():
print(f" {k}: {v:.4f}")点击展开可浏览运行结果
📘 本段为代码片段(依赖上文变量或外部输入,如 df/data/参数等),无法独立运行
LP 做市的核心权衡:更窄的区间带来更高的资金效率和手续费收入,但也意味着更高的价格跑出区间风险,需要更频繁的链上操作(消耗 Gas)。最优策略是在资本效率、Gas 成本和操作复杂度之间找到平衡点——这本质上是一个随机最优控制问题。