Skip to content

13.4 DEX流动性做市

AMM 模型的数学基础

自动做市商(Automated Market Maker, AMM)是去中心化交易所的核心机制。与传统订单簿不同,AMM 使用数学公式而非买卖双方报价来确定价格。

名词解释:AMM(Automated Market Maker)

一种基于恒定函数(如恒定乘积)的自动定价机制,流动性提供者将资产存入流动性池,交易者直接与池子交互,价格由池中资产比例决定。

Uniswap V2:恒定乘积模型

Uniswap V2 使用最简单的 AMM 公式——恒定乘积

$$x \cdot y = k$$

其中 xy 为池中两种资产的数量,k 为常数。任何交易都必须保持乘积不变:

$$(x + \Delta x)(y - \Delta y) = k$$

由此可推出交易者获得的资产数量:

$$\Delta y = y - \frac{k}{x + \Delta x} = \frac{y \cdot \Delta x}{x + \Delta x}$$
PYTHON36 行 · 1.0 KB
📄此处有展示代码36 行 · 1.0 KB展开 ▼
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 可以选择一个价格区间 [Pa,Pb] 来提供流动性,而非在整个价格曲线上均匀分布。

对于在区间 [Pa,Pb] 内提供流动性,虚拟储备满足:

$$(x + x_{\text{virtual}})(y + y_{\text{virtual}}) = L^2$$

其中 L=xy 为流动性单位。

PYTHON55 行 · 1.6 KB
📄此处有展示代码55 行 · 1.6 KB展开 ▼
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,当价格从 P0 变动到 P1 时:

$$IL = 1 - \frac{2\sqrt{P_1/P_0}}{1 + P_1/P_0}$$
PYTHON30 行 · 957 B
📄此处有展示代码30 行 · 957 B展开 ▼
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 交易问题:做市商赚取手续费,但需要不断调仓以适应价格变动。

最优做市区间选择

PYTHON31 行 · 1.2 KB
📄此处有展示代码31 行 · 1.2 KB展开 ▼
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 需要决定是否提取流动性并重新部署在新区间:

PYTHON30 行 · 1.2 KB
📄此处有展示代码30 行 · 1.2 KB展开 ▼
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 收益模拟与优化

PYTHON59 行 · 2.1 KB
📄此处有展示代码59 行 · 2.1 KB展开 ▼
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 成本和操作复杂度之间找到平衡点——这本质上是一个随机最优控制问题。