AMM 數學公式完整指南:從基礎常數乘積到進階穩定幣模型
深入剖析各類自動做市商(AMM)的數學基礎,從 Uniswap 的常數乘積模型到 Curve 的 StableSwap 演算法,提供完整的公式推導與實務應用指南,包含無常損失計算、Gas 優化與 LP 收益策略。
AMM 數學公式完整指南:從基礎常數乘積到進階穩定幣模型
概述
自動做市商(Automated Market Maker,AMM)是去中心化金融(DeFi)的核心基礎設施。不同於傳統交易所的訂單簿模型,AMM 採用數學公式來決定交易價格,其定價機制的優劣直接影響流動性效率、交易滑點與資金利用率。本文深入剖析各類 AMM 的數學基礎,從最基礎的常數乘積公式到最新的穩定幣 DEX 演算法,提供完整的推到過程與實務應用指南。
理解這些數學模型對於流動性提供者(LP)優化收益、交易者降低滑點、以及協議設計者構建高效市場至關重要。我們將使用詳細的數學推導與實際數值範例,幫助讀者建立直觀的理解。
一、常數乘積模型(Constant Product Model)
1.1 基礎公式推導
常數乘積模型是 Uniswap V2 採用的核心機制,其名稱來源於以下恒等式:
x × y = k
其中:
- x:代幣 X 的儲備量
- y:代幣 Y 的儲備量
- k:常數(恒定乘積)
這個公式的直覺理解是:交易不改變兩個資產儲備量的乘積。當投資者向池子添加流動性時,k 值會相應增加;而當交易發生時,k 值保持不變。
為什麼選擇乘積而非其他函數?
從數學角度而言,乘積函數具有以下特性:
- 當 x 或 y趨近於 0 時,價格趨近於無窮大,防止流動性完全耗盡
- 函數圖像為雙曲線,在整個定義域內連續且平滑
- 對稱性:兩種資產的定價權重相等
1.2 交易價格計算
根據微分幾何,價格可以定義為邊際變化率。對於常數乘積模型,邊際價格(Marginal Price)為:
dy/dx = y/x
這意味著購買一單位 X 所需的 Y 數量,等於當前 Y 儲備量除以 X 儲備量。
實際交易計算
假設:
- 初始儲備:x₀ = 1000 USDC,y₀ = 10 ETH
- 投資者希望購買 dx = 1 ETH
根據恒等式:
(x₀) × (y₀) = (x₀ + dx') × (y₀ - dy)
其中 dx' 為輸入的 USDC 數量,dy 為輸出的 ETH 數量。
求解 dy:
y₀ - dy = k / (x₀ + dx')
dy = y₀ - k / (x₀ + dx')
代入 k = x₀ × y₀ = 10000:
dy = 10 - 10000 / (1000 + dx')
若使用常規滑點計算,假設輸入 dx' = 100 USDC:
dy = 10 - 10000 / 1100 = 10 - 9.09 = 0.91 ETH
實際匯率:100 USDC / 0.91 ETH = 110 ETH/USDC(優於報價)
這解釋了為何大額交易會造成嚴重滑點——隨著交易進行,儲備比例偏離初始狀態,價格顯著變動。
1.3 滑點與價格影響分析
滑點(Slippage)是交易實際成交價格與預期價格的偏差,其根本原因是 AMM 的邊際定價機制。
滑點公式推導
對於常數乘積模型,滑點可以精確計算:
實際價格 / 初始價格 = (y₀ / (y₀ - dy)) × (1 - dy/y₀)
簡化後得到滑點率:
滑點率 ≈ dy / y₀ + (dy / y₀)² + ...
當 dy/y₀ << 1 時,一次近似為:
滑點率 ≈ dy / y₀
數值範例
假設池子配置為 50/50(價值相等),則每種資產佔總價值的 50%。若進行一筆佔總流動性 1% 的交易:
- 初始報價:1 ETH = 2000 USDC
- 交易後價格:1 ETH ≈ 2020 USDC
- 滑點:約 1%
這解釋了為何 LP 傾向於提供足夠的流動性——流動性越高,相同交易規模產生的滑點越低。
1.4 流動性深度與價格曲線
常數乘積模型的價格曲線呈現雙曲線特性,其斜率隨價格變動:
斜率 = dy/dx = y/x = 1/價格
這種設計的優點是價格永遠不會達到無窮大(流動性不會完全耗盡),但缺點是在極端價格區間,流動性極度匱乏。
實際影響
| 交易規模(佔池子比例) | 預估滑點 |
|---|---|
| 0.1% | ~0.1% |
| 1% | ~1% |
| 10% | ~11% |
| 25% | ~33% |
| 50% | ~100% |
從數據可見,大額交易在常數乘積模型中極不經濟,這催生了後續的集中流動性模型。
二、集中流動性模型(Concentrated Liquidity)
2.1 Uniswap V3 的創新
Uniswap V3 引入的集中流動性機制允許 LP 將資金集中在特定價格區間,而非均勻分佈在整個 0 到 ∞ 的範圍內。這一創新來自於一個簡單的觀察:大多數交易發生在特定價格區間。
核心公式
在區間 [Pₐ, Pᵦ] 內提供流動性時,等效的常數乘積為:
k = (√Pᵦ - √P) × (√P - √Pₐ) / (√Pᵦ - √Pₐ) × L²
其中 L 為流動性數量(Virtual Liquidity),定義為:
L = √(x × y)
2.2 虛擬儲備與流動性計算
虛擬儲備概念
在集中流動性模型中,即使某個區間內的實際儲備為零,系統仍會根據數學公式計算「虛擬儲備」。這允許交易在區間內進行,即使物理上的代幣已經耗盡。
流動性數量(L)計算
對於位於 [Pₐ, Pᵦ] 的頭寸,流動性 L 的計算方式為:
L = Δx × √Pᵦ / (√Pᵦ - √Pₐ) = Δy / (√Pᵦ - √Pₐ)
其中 Δx, Δy 為實際存入的代幣數量。
實際範例
假設 LP 欲在 ETH/USDC 價格區間 1500-2500 USDC 內提供流動性:
- 存入:1 ETH + 2000 USDC
- 當前價格:2000 USDC/ETH
- √P = √2000 ≈ 44.72
- √Pₐ = √1500 ≈ 38.73
- √Pᵦ = √2500 = 50
計算 L:
L = 1 × 50 / (50 - 38.73) = 50 / 11.27 ≈ 4.44
2.3 區間頭寸的價格變動風險
集中流動性雖然提高了資本效率,但也帶來了「範圍內」(in-range)和「範圍外」(out-of-range)的風險。
當價格離開區間時
當交易價格突破 Pₐ 或 Pᵦ 時,LP 的頭寸將完全由單一資產構成:
- 價格高於上限:頭寸 100% 為 USDC
- 價格低於下限:頭寸 100% 為 ETH
無常損失(Impermanent Loss)計算
假設初始價格為 P₀,終止價格為 P₁,在區間 [Pₐ, Pᵦ] 內的無常損失為:
IL = 2 × √(P₁/P₀) - P₁/P₀ - 1 (當 P₀, P₁ 都在區間內)
數值範例
假設:
- 初始價格:2000 USDC/ETH
- 最終價格:2500 USDC/ETH
- 區間:1500-2500 USDC
IL = 2 × √(2500/2000) - 2500/2000 - 1
= 2 × √1.25 - 1.25 - 1
= 2 × 1.118 - 2.25
= 2.236 - 2.25
= -0.014 = -1.4%
在這種情況下,LP 仍能獲得部分收益,因為價格上漲帶來了資本利得。
三、穩定幣 AMM 與 StableSwap
3.1 常數和模型的問題
對於穩定幣交易對(如 USDC/USDT),傳統常數乘積模型存在嚴重缺陷:
- 穩定幣設計上應該保持 1:1 掛鉤
- 常數乘積模型在價格接近 1:1 時定價效率極低
- 即使兩個代幣價值完全相等,交易仍會產生不必要的滑點
數據說明
假設池子為 1,000,000 USDC + 1,000,000 USDT:
- 交易 10,000 USDC 換 USDT
- 常數乘積模型產生的滑點約為 1%
- 這對本應「穩定」的交易對而言是不可接受的
3.2 Curve 的 StableSwap 公式
Curve Finance 引入的 StableSwap 機制結合了常數乘積與常數和模型的優點:
D = A × nⁿ × Σuᵢ + Σ(uᵢⁿ⁺ⁿ)
簡化版本(針對雙代幣池):
D = A × x × y × (x² + y²) + x² × y²
其中:
- A:放大係數(Amplification Coefficient),控制曲線形狀
- x, y:兩種代幣的數量
3.3 放大係數(A)的作用
放大係數 A 是 StableSwap 模型中最關鍵的參數,它決定了曲線在何處開始偏離常數和模型。
A 與曲線形狀
- 當 A → ∞:曲線趨近於常數和模型(x + y = D)
- 當 A = 1:曲線趨近於常數乘積模型
實務選擇
| 資產類型 | 建議 A 值 | 說明 |
|---|---|---|
| 穩定幣 1:1 掛鉤 | 100-500 | 高 A 值使曲線更接近直線 |
| 類似資產(如stETH/ETH) | 10-50 | 中等 A 值平衡效率與穩定性 |
| 波動性資產 | 1-5 | 低 A 值類似傳統 AMM |
3.4 交易計算實務
輸入輸出計算
在 StableSwap 中,給定輸入 dx,輸出 dy 的精確計算需要求解二次方程:
Ax² + Bx + C = 0
其中係數根據當前狀態動態計算。實際實現中,通常使用、牛頓法或二分搜尋進行數值求解。
簡化近似公式
當交易量相對於池子很小時,可以使用以下近似:
dy ≈ dx × (1 - (x + dx) / (y - dy)) / (1 + A × (x + y) / D²)
實際範例
假設:
- 池子:5,000,000 USDC + 5,000,000 USDT
- A = 100
- 交易:100,000 USDC 換 USDT
使用近似公式計算:
dy ≈ 100,000 × (1 - 5100000/4900000) / (1 + 100 × 10000000/25000000000)
≈ 100,000 × (-0.04) / (1 + 0.04)
≈ 100,000 × (-0.0385)
≈ 38,500 / 1.04
≈ 37,019 USDT
實際滑點:~0.98%(遠優於常數乘積的 ~2%)
3.5 流動性頭寸計算
LP 份額計算
LP 在 StableSwap 中存入資產後,獲得的份額(tokens)計算為:
shares = D × (1 - (vD/D₀)ⁿ)
其中 vD 為提取的價值(扣除費用後)。
收益來源
StableSwap LP 的收益來自三個部分:
- 交易手續費(通常 0.04-0.1%)
- CRV 激勵代幣(額外收益)
- 套利收益(維持價格穩定)
四、動態 AMM 與自適應曲線
4.1 為何需要動態曲線
傳統 AMM 的曲線是靜態的,無法適應市場條件變化。在以下場景中,靜態曲線表現不佳:
- 市場劇烈波動時需要更平滑的價格曲線
- 低流動性時期需要更好的深度
- 特定協議需要客製化定價邏輯
4.2 KyberDMM 的動態乘積
Kyber Network 的動態AMM(DMM)引入時間加權的流動性概念:
k(t) = k₀ × f(t)
其中 f(t) 根據以下因素動態調整:
- 近期交易量
- 波動率
- 池子利用率
4.3 Saddle Finance 的調整公式
Saddle Finance 針對比特幣錨定資產(如 renBTC/WBTC/sBTC)採用可調參數的 StableSwap:
修正系數 = 1 + β × |p - 1|
其中 β 為敏感性參數,p 為偏離錨定價格的比率。
4.4 實作考量
動態參數的挑戰
- 預言機依賴:需要可靠的價格輸入
- 操縱風險:參數更新可能被攻擊
- 複雜性:增加合約漏洞風險
最佳實踐
- 參數更新應有時間鎖延遲
- 設置合理的參數邊界
- 使用時間加權平均避免瞬間波動影響
五、費用模型與 LP 收益優化
5.1 交易費用結構
固定費用模型
Uniswap V2 採用 0.3% 的固定費用,這筆費用歸 LP 所有:
收入 = 0.3% × 交易額
動態費用模型
部分協議根據波動率或池子利用率調整費用:
費用率 = 基礎費率 × 波動率因子 × 利用率因子
5.2 LP 收益率計算
年化收益率(APY)公式
APY = (年度交易收入) / (鎖定流動性價值) × 100%
實際計算
假設:
- 池子流動性:1,000,000 USDC
- 日均交易量:200,000 USDC
- 費用率:0.3%
日收入 = 200,000 × 0.3% = 600 USDC
年收入的 = 600 × 365 = 219,000 USDC
APY = 219,000 / 1,000,000 = 21.9%
現實中,交易量會波動,APY 也隨之變化。
5.3 無常損失量化
完整 IL 公式
對於常數乘積池,無常損失為:
IL = 2 × √(P₁/P₀) / (1 + P₁/P₀) - 1
表格查詢
| 價格變動 | 無常損失 |
|---|---|
| ±25% | -1.0% |
| ±50% | -5.7% |
| ±75% | -13.4% |
| ±100% | -25.5% |
| +200% | -43.4% |
| -50% | -25.5% |
5.4 收益優化策略
1. 集中流動性優化
選擇交易密集的價格區間:
// 選擇區間的簡易邏輯
function calculateOptimalRange(
uint256 currentPrice,
uint256 historicalVolatility
) internal pure returns (uint256, uint256) {
uint256 width = historicalVolatility * currentPrice / 100;
uint256 lower = currentPrice - width;
uint256 upper = currentPrice + width;
return (lower, upper);
}
2. 多元化分散
將流動性分配到多個池子:
- 主要池子:50% 資金,窄區間
- 次要池子:30% 資金,寬區間
- 備用池子:20% 資金,極寬區間
3. 收益聚合
使用 Yearn 等收益優化器自動再投資:
// 收益聚合邏輯
function harvest() external {
// 收集交易費用
uint256 fees = pendingFees();
// 自動複投
if (fees > threshold) {
addLiquidity(fees);
}
}
六、進階數學:路徑依賴與滑點優化
6.1 多跳交易的路徑依賴
當交易透過多個池子進行時,最終輸出取決於所選擇的路徑。這就是所謂的「路徑依賴」問題。
範例:USDC → ETH → DAI
路徑 1:USDC → ETH → DAI
- USDC/ETH 池:1000 USDC → 0.5 ETH
- ETH/DAI 池:0.5 ETH → 850 DAI
路徑 2:USDC → DAI(直接)
- USDC/DAI 池:1000 USDC → 995 DAI
顯然,直接路徑效率更高。這催生了 1inch、Paraswap 等聚合器的需求。
6.2 最優路徑算法
貪心算法的局限性
簡單的貪心算法(在每一步選擇最優輸出)可能陷入局部最優:
貪心選擇:A→B→C 可能優於 A→C
動態規劃解法
定義狀態:
dp[i][j] = 從代幣 i 交換到代幣 j 的最大輸出
轉移方程:
dp[i][j] = max(dp[i][k] × dp[k][j]) for all k
複雜度:O(n³),其中 n 為代幣數量。
6.3 滑點預測模型
機器學習輔助
傳統公式無法預測套利行為帶來的價格變動。進階系統使用:
# 滑點預測特徵
features = [
'trade_size_ratio', # 交易規模/流動性
'volatility_24h', # 24小時波動率
'utilization_change', # 利用率變化
'recent_trade_count' # 近期交易次數
]
# 滑點預測模型
predicted_slippage = model.predict(features)
安全邊際建議
基於預測結果,建議設置的安全邊際:
| 預測滑點 | 建議安全邊際 |
|---|---|
| <0.5% | +20% |
| 0.5-2% | +50% |
| >2% | +100% 或分批交易 |
七、協議設計的數學考量
7.1 初始流動性設定
新 AMM 池的初始流動性設定至關重要。考慮以下數學問題:
目標:初始價格合理性
初始價格 = 初始代幣A數量 / 初始代幣B數量
應根據外部市場價格設定,避免套利空間過大。
流動性深度規劃
根據預期交易量,所需流動性:
L = 預期日交易量 × (1 / 目標滑點)²
範例:目標日交易量 1,000,000 USDC,目標滑點 0.5%
L = 1,000,000 × (1/0.005)² = 1,000,000 × 40,000 = 40,000,000
7.2 激勵代幣分配數學
費用補貼公式
協議通常使用代幣激勵吸引流動性。分配公式:
補貼率 = 目標APY - 費用收入APY
年度代幣支出 = 鎖定價值 × 補貼率
線性釋放 vs 遞減
- 線性釋放:每期固定數量
- 遞減釋放:早期高,後期低
遞減模式更有利於長期穩定性,但需要更精細的經濟模型設計。
7.3 脆弱性分析
價格操縱防範
AMM 的定價機制使其容易受到價格操縱攻擊。關鍵指標:
操縱成本 ≈ 流動性 × 期望價格偏移
閃電貸攻擊向量
攻擊流程:
- 透過閃電貸大量借貸
- 在 AMM 中大額交易操縱價格
- 在其他市場套利
- 償還閃電貸
防範措施:
- 設置最大交易限制
- 引入價格偏差保護
- 使用時間加權平均價格(TWAP)
八、實務工具與代碼範例
8.1 價格計算合約
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract AMMPricing {
// 獲取輸出數量(常數乘積)
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut,
uint256 fee
) public pure returns (uint256) {
require(amountIn > 0, "Invalid input amount");
require(reserveIn > 0 && reserveOut > 0, "Insufficient liquidity");
uint256 amountInWithFee = amountIn * (10000 - fee) / 10000;
uint256 numerator = amountInWithFee * reserveOut;
uint256 denominator = reserveIn + amountInWithFee;
return numerator / denominator;
}
// 獲取輸入數量(常數乘積)
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut,
uint256 fee
) public pure returns (uint256) {
require(amountOut > 0, "Invalid output amount");
require(reserveIn > 0 && reserveOut > 0, "Insufficient liquidity");
uint256 numerator = reserveIn * amountOut * 10000;
uint256 denominator = (reserveOut - amountOut) * (10000 - fee);
return numerator / denominator + 1;
}
// 批量獲取多跳路徑輸出
function getAmountsOut(
uint256 amountIn,
address[] memory path,
mapping(address => (uint256, uint256)) memory reserves,
uint256 fee
) public pure returns (uint256[] memory amounts) {
require(path.length >= 2, "Invalid path");
amounts = new uint256[](path.length);
amounts[0] = amountIn;
for (uint256 i = 0; i < path.length - 1; i++) {
(uint256 reserveIn, uint256 reserveOut) = reserves[path[i]];
amounts[i + 1] = getAmountOut(
amounts[i],
reserveIn,
reserveOut,
fee
);
}
}
}
8.2 流動性頭寸計算
// 計算集中流動性的價值變化
contract LiquidityPosition {
struct Position {
uint256 liquidity;
uint256 lowerTick;
uint256 upperTick;
uint256 lastTimestamp;
}
// 計算頭寸價值
function positionValue(
Position memory pos,
uint256 currentPrice,
uint256 token0Reserve,
uint256 token1Reserve
) public pure returns (uint256 value0, uint256 value1) {
if (currentPrice <= pos.lowerTick) {
// 價格低於區間,全部為 token1
uint256 amount1 = pos.liquidity * (sqrt(pos.upperTick) - sqrt(pos.lowerTick));
return (0, amount1);
} else if (currentPrice >= pos.upperTick) {
// 價格高於區間,全部為 token0
uint256 amount0 = pos.liquidity * (sqrt(pos.upperTick) - sqrt(pos.lowerTick));
return (amount0, 0);
} else {
// 價格在區間內
uint256 amount0 = pos.liquidity * (sqrt(currentPrice) - sqrt(pos.lowerTick));
uint256 amount1 = pos.liquidity * (sqrt(pos.upperTick) - sqrt(currentPrice));
return (amount0, amount1);
}
}
// 簡化版 sqrt 函數
function sqrt(uint256 x) public pure returns (uint256 y) {
uint256 z = (x + 1) / 2;
y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
}
}
}
8.3 StableSwap 計算
// Simplified StableSwap D calculation
function calculateD(
uint256[] memory balances,
uint256 A
) public pure returns (uint256 D) {
uint256 n = balances.length;
uint256 sum = 0;
uint256 i;
for (i = 0; i < n; i++) {
sum += balances[i];
}
if (sum == 0) return 0;
uint256 Dprev = 0;
D = sum;
// Newton-Raphson iteration
for (uint256 i = 0; i < 255; i++) {
uint256 D_P = D;
for (uint256 j = 0; j < n; j++) {
D_P = D_P * D / balances[j];
}
uint256 Dnext = (D * (n - 1) + D_P / (A * n ** n)) * sum / ((n + 1) * D_P / (n * n) + D);
if (Dnext > D) {
Dnext -= (Dnext - D) / 2;
} else {
D += (D - Dnext) / 2;
}
if (Dprev == D) break;
Dprev = D;
}
}
九、未來發展方向
9.1 v4 與 Hooks 架構
Uniswap V4 引入的 Hooks 機制允許開發者自定義 AMM 曲線:
- 動態費用調整
- 自定義價格預言機
- 自動化頭寸管理
9.2 整合zk-Rollup
將 AMM 與 zk-Rollup 結合可以:
- 降低交易成本
- 提高隱私保護
- 實現更複雜的定價邏輯
9.3 機構級流動性
傳統金融機構的進入將推動:
- 更大規模的流動性池
- 合規的做市商機制
- 專業級風險管理工具
結論
AMM 的數學原理是 DeFi 生態的基石。從常數乘積到 StableSwap,每種模型都代表了在效率、穩定性與安全性之間的不同權衡。理解這些數學公式不僅有助於 LP 優化收益,更能幫助開發者設計更健壯的金融協議。
隨著技術演進,我們將看到更多創新的 AMM 形態出現,但核心的流動性提供與價格發現機制將持續演進。建議讀者實際動手計算、部署測試合約,以深化對這些數學模型的理解。
延伸閱讀
相關文章
- DeFi 流動性提供完整指南:AMM 機制、收益計算與風險管理 — 深入解析 AMM 技術機制、流動性提供的收益計算、無常損失分析,並提供主流協議比較、風險矩陣與實際操作流程,幫助讀者全面掌握 DeFi 流動性提供的技術與商業邏輯。
- DeFi 合約風險檢查清單 — 上鏈前先看權限、預言機、流動性與清算機制。
- Uniswap V4 深度解析 — 深入解析 Uniswap V4 的技術架構、核心創新、與 v3 的比較、以及對 DeFi 生態的深遠影響,包括 Hooks 與 Flash Accounting。
- Uniswap V4 鉤子完整指南 — 深入介紹 Uniswap V4 的架構變化、鉤子機制的技術原理、常見鉤子應用場景,以及如何開發自定義鉤子。
- Curve Finance 穩定幣 DEX 深度解析 — 深入解析 Curve 的 StableSwap 機制、CRV 代幣經濟學、crvUSD 演算法穩定幣設計,以及其在 DeFi 生態中的核心基礎設施地位。
延伸閱讀與來源
- Ethereum.org 以太坊官方入口
- EthHub 以太坊知識庫
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!