ETH-USDC pool_design; uni4 quotes refactor
This commit is contained in:
@@ -7,14 +7,15 @@ import numpy as np
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
LMSR_FEE = 0.0025
|
||||
# UNISWAP_GAS=0
|
||||
# LMSR_GAS=0
|
||||
UNISWAP_GAS=115_000
|
||||
LMSR_GAS=119_000
|
||||
ETH_PRICE=4500
|
||||
LMSR_GAS=150_000
|
||||
ETH_PRICE=4000
|
||||
UNISWAP_GAS_COST=UNISWAP_GAS*ETH_PRICE/1e9
|
||||
LMSR_GAS_COST=LMSR_GAS*ETH_PRICE/1e9
|
||||
|
||||
LMSR_FEE = 0.000010
|
||||
|
||||
print(f' LMSR gas: ${LMSR_GAS_COST:.2}')
|
||||
print(f'Uniswap gas: ${UNISWAP_GAS_COST:.2}')
|
||||
@@ -96,9 +97,9 @@ def lmsr_swap_amount_out(
|
||||
# No available output to withdraw
|
||||
return 0.0
|
||||
|
||||
# Compute r0 = exp((q_i - q_j) / b)
|
||||
# Compute r0 = exp((q_j - q_i) / b) so small-trade out/in ≈ marginal price p_j/p_i
|
||||
try:
|
||||
r0 = math.exp((qi - qj) / b)
|
||||
r0 = math.exp((qj - qi) / b)
|
||||
except OverflowError:
|
||||
raise ArithmeticError("exponential overflow in r0 computation")
|
||||
|
||||
@@ -138,24 +139,81 @@ def lmsr_swap_amount_out(
|
||||
|
||||
return float(amount_out)
|
||||
|
||||
def lmsr_marginal_price(balances, base_index, quote_index, kappa):
|
||||
"""
|
||||
Compute the LMSR marginal price ratio p_quote / p_base for the given balances state.
|
||||
|
||||
def compare():
|
||||
kappa = 10
|
||||
balance0 = 10_000_000 # estimated from the production pool
|
||||
balances = [balance0, balance0]
|
||||
X = np.geomspace(1, 10_000_000, 100)
|
||||
Y = [max(0, 1 -
|
||||
(lmsr_swap_amount_out(balances, float(amount_in), 0, 1, LMSR_FEE, kappa) - LMSR_GAS_COST)
|
||||
/ amount_in)
|
||||
for amount_in in X]
|
||||
plt.plot(X, Y, label=f'LMSR {kappa:.2f}')
|
||||
Formula:
|
||||
b = kappa * S, where S = sum(balances)
|
||||
price = exp((q_quote - q_base) / b)
|
||||
|
||||
d = pd.read_csv('swap_results_block_23640998.csv')
|
||||
d.columns = ['block', 'price0', 'price1', 'in0', 'out0', 'in1', 'out1']
|
||||
uniswap_slippage0 = 1 - (d.out0 - UNISWAP_GAS_COST) / d.in0 / d.iloc[0].price0
|
||||
plt.plot(d.in0, uniswap_slippage0, label='CP0')
|
||||
# uniswap_slippage1 = 1 - (d.out1 - UNISWAP_GAS_COST) / d.in1 / d.iloc[0].price1
|
||||
# plt.plot(d.in1, uniswap_slippage1, label='CP1')
|
||||
Parameters:
|
||||
- balances: iterable of per-token balances (q_i)
|
||||
- base_index: index of the base token
|
||||
- quote_index: index of the quote token
|
||||
- kappa: liquidity parameter κ (must be positive)
|
||||
|
||||
Returns:
|
||||
- float: marginal price p_quote / p_base
|
||||
"""
|
||||
try:
|
||||
q = [float(x) for x in balances]
|
||||
k = float(kappa)
|
||||
except (TypeError, ValueError) as e:
|
||||
raise ValueError("Invalid numeric input") from e
|
||||
|
||||
n = len(q)
|
||||
if not (0 <= base_index < n and 0 <= quote_index < n):
|
||||
raise IndexError("token indices out of range")
|
||||
if k <= 0.0:
|
||||
raise ValueError("kappa must be positive")
|
||||
|
||||
S = sum(q)
|
||||
if S <= 0.0:
|
||||
raise ValueError("size metric (sum balances) must be positive")
|
||||
|
||||
b = k * S
|
||||
if b <= 0.0:
|
||||
raise ValueError("computed b must be positive")
|
||||
|
||||
return float(math.exp((q[quote_index] - q[base_index]) / b))
|
||||
|
||||
|
||||
|
||||
def compare(file, tvl, kappa):
|
||||
d = pd.read_csv(file)
|
||||
d.columns = ['block', 'price0', 'price1', 'in0', 'out0', 'rate']
|
||||
|
||||
# Calibrate LMSR balances so that exp((q1 - q0)/b) equals the initial price
|
||||
p0 = float(d.iloc[0].price0)
|
||||
S = float(tvl) # choose the LMSR size metric
|
||||
b = kappa * S
|
||||
delta = b * math.log(p0) # q1 - q0
|
||||
q0 = 0.5 * (S - delta)
|
||||
q1 = 0.5 * (S + delta)
|
||||
if q0 <= 0.0 or q1 <= 0.0:
|
||||
raise ValueError("Invalid LMSR calibration: choose kappa such that kappa * ln(price0) < 1.")
|
||||
balances = [q0, q1]
|
||||
print(balances)
|
||||
X = np.geomspace(1, 1_000_000, 100)
|
||||
orig_price = lmsr_marginal_price(balances, 0, 1, kappa)
|
||||
in_out = [(float(amount_in), lmsr_swap_amount_out(balances, float(amount_in), 0, 1, LMSR_FEE, kappa)) for amount_in in X]
|
||||
print(in_out)
|
||||
# Relative execution price deviation from the initial marginal price:
|
||||
# slippage = |(amount_out/amount_in)/orig_price - 1|
|
||||
eps = 1e-12
|
||||
Y = [max(eps, abs((amount_out / amount_in) / orig_price - 1.0))
|
||||
for amount_in, amount_out in in_out]
|
||||
plt.plot(X, Y, label=f'LMSR {LMSR_FEE:.2%} κ={kappa:.2f}', color='cornflowerblue')
|
||||
|
||||
# Uniswap execution price deviation from its initial quoted price:
|
||||
# slippage = |(out/in)/initial_price - 1|
|
||||
uniswap_exec_price0 = d.out0 / d.in0
|
||||
uniswap_slippage0 = (uniswap_exec_price0 / d.iloc[0].price0 - 1.0).abs().clip(lower=1e-12)
|
||||
uniswap_fee = round(uniswap_slippage0.iloc[0], 6)
|
||||
plt.plot(d.in0, uniswap_slippage0, label=f'Uniswap {uniswap_fee:.2%}', color='hotpink')
|
||||
# uniswap_slippage1 = |(out1/in1)/price1 - 1|
|
||||
# plt.plot(d.in1, (d.out1 / d.in1 / d.iloc[0].price1 - 1.0).abs().clip(lower=1e-12), label='CP1')
|
||||
|
||||
# Interpolate Uniswap slippage to match LMSR x-coordinates
|
||||
interp_uniswap = np.interp(X, d.in0, uniswap_slippage0)
|
||||
@@ -166,6 +224,7 @@ def compare():
|
||||
plt.yscale('log')
|
||||
plt.gca().xaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: '{:g}'.format(x)))
|
||||
plt.gca().yaxis.set_major_formatter(plt.FuncFormatter(lambda y, _: '{:.2%}'.format(y)))
|
||||
plt.gca().set_ylim(top=.1)
|
||||
plt.xlabel('Input Amount')
|
||||
plt.ylabel('Slippage')
|
||||
plt.title('Pool Slippages')
|
||||
@@ -197,5 +256,7 @@ def plot_kappa():
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
compare()
|
||||
# compare('uni4_quotes/swap_results_block_23640998.csv')
|
||||
# compare('uni4_quotes/ETH-USDC-30.csv', 53_000_000, 0.1)
|
||||
compare('uni4_quotes/ETH-USDC-30.csv', 1_00_000, .1)
|
||||
# plot_kappa()
|
||||
|
||||
Reference in New Issue
Block a user