Imp Loss V3
Impermanent Loss
Section titled “Impermanent Loss”from uniswappy import *import numpy as npimport datetimeimport matplotlib.pyplot as plt# Instantiation Parametersn_steps = 500 # Number of stepsstart_price = 10 # Initial price SYS/USDmu = 0.1; sigma = 0.5n_paths = 1 # Number of simulationed pathsseconds_year = 31536000
# Brownian Modelbm = BrownianModel(start_price)p_arr = bm.gen_gbms(mu, sigma, n_steps-1, n_paths).flatten()
dt = datetime.timedelta(seconds=seconds_year/n_steps)dates = [datetime.datetime.strptime("2024-09-01", '%Y-%m-%d') + k*dt for k in range(n_steps)]user_nm = 'user0'tkn1_amount = 1000tkn2_amount = p_arr[0]*tkn1_amount
fee = UniV3Utils.FeeAmount.MEDIUMtick_spacing = UniV3Utils.TICK_SPACINGS[fee]lwr_tick = UniV3Utils.getMinTick(tick_spacing)upr_tick = UniV3Utils.getMaxTick(tick_spacing)tkn1_nm = 'TKN1'tkn2_nm = 'TKN2'
tkn1 = ERC20(tkn1_nm, "0x09")tkn2 = ERC20(tkn2_nm, "0x111")
exchg_data = UniswapExchangeData(tkn0 = tkn1, tkn1 = tkn2, symbol="LP", address="0x011", version = 'V3', tick_spacing = tick_spacing, fee = fee)
factory = UniswapFactory("ETH pool factory", "0x2")lp = factory.deploy(exchg_data)
Join().apply(lp, user_nm, tkn1_amount, tkn2_amount, lwr_tick, upr_tick)lp.summary()Exchange TKN1-TKN2 (LP)
Real Reserves: TKN1 = 999.9999999999999, TKN2 = 10000.0
Gross Liquidity: 3162.277660168379
tick_size = 10000lwr_tick = UniV3Helper().get_price_tick(lp, -1, lp.get_price(tkn1), tick_size)upr_tick = UniV3Helper().get_price_tick(lp, 1, lp.get_price(tkn1), tick_size)out = AddLiquidity().apply(lp, tkn1, user_nm, 10, lwr_tick, upr_tick)lp.summary()
dL = lp.last_liquidity_depositiLoss = UniswapImpLoss(lp, dL, lwr_tick, upr_tick)Exchange TKN1-TKN2 (LP)
Real Reserves: TKN1 = 1009.9999999999999, TKN2 = 10100.262769858964
Gross Liquidity: 3242.81759104987
tkn1_init_amt = iLoss.get_init_amt(tkn1)tkn2_init_amt = iLoss.get_init_amt(tkn2)tkn1_hold_amt = iLoss.hold_value(tkn1)tkn2_hold_amt = iLoss.hold_value(tkn2)
print(f'Initial {tkn1.token_name} amount: {tkn1_init_amt:.2f}, Initial {tkn2.token_name} amount: {tkn2_init_amt:.2f}')print(f'Hold {tkn1.token_name} amount: {tkn1_hold_amt:.2f}, Hold {tkn2.token_name} amount: {tkn2_hold_amt:.2f}')Initial TKN1 amount: 10.00, Initial TKN2 amount: 100.26
Hold TKN1 amount: 20.03, Hold TKN2 amount: 200.26
Simulate AMM
Section titled “Simulate AMM”tick_size = 100000arb = CorrectReserves(lp, x0 = p_arr[0])TKN_amt = TokenDeltaModel(100)pTKN1_TKN2_arr = [];
for k in range(n_steps):
# ***************************** # ***** Random Swapping ****** # ***************************** Swap().apply(lp, tkn1, user_nm, TKN_amt.delta()) Swap().apply(lp, tkn2, user_nm, p_arr[k]*TKN_amt.delta())
# ***************************** # ***** Rebalance ****** # *****************************
lwr_tick = UniV3Helper().get_price_tick(lp, -1, lp.get_price(tkn1), tick_size) upr_tick = UniV3Helper().get_price_tick(lp, 1, lp.get_price(tkn1), tick_size) arb.apply(p_arr[k], lwr_tick, upr_tick)
# ***************************** # ******* Data Capture ******** # ***************************** pTKN1_TKN2_arr.append(LPQuote().get_price(lp, tkn1))
lp.summary()Exchange TKN1-TKN2 (LP)
Real Reserves: TKN1 = 1146.3148635861073, TKN2 = 13671.93074026191
Gross Liquidity: 3865.0031366001244
Calculate Imp. Loss
Section titled “Calculate Imp. Loss”tkn1_hold_amt = iLoss.hold_value(tkn1)tkn2_hold_amt = iLoss.hold_value(tkn2)tkn1_pos_amt = iLoss.current_position_value(tkn1, lwr_tick, upr_tick)tkn2_pos_amt = iLoss.current_position_value(tkn2, lwr_tick, upr_tick)
print(f'{tkn1.token_name} hold amt: {tkn1_hold_amt:.2f}, {tkn2.token_name} hold amt: {tkn2_hold_amt:.2f}')print(f'{tkn1.token_name} position amt: {tkn1_pos_amt:.2f}, {tkn2.token_name} position amt: {tkn2_pos_amt:.2f}')print(f'Start price: {p_arr[0]:.2f}, End price: {p_arr[-1]:.2f}')TKN1 hold amt: 25.06, TKN2 hold amt: 166.85
TKN1 position amt: 61.26, TKN2 position amt: 407.92
Start price: 10.00, End price: 6.66
iloss_calc = iLoss.apply(lwr_tick, upr_tick, fees = False)returns_calc = iLoss.apply(lwr_tick, upr_tick, fees = True)
print(f'Imp Loss: {100*iloss_calc:.2f}%, returns: {100*returns_calc:.2f} %')Imp Loss: -2.08%, returns: 144.49 %
n_steps = 1000alphas = np.linspace(0, 5, num=n_steps)alpha_deltas = alphas-1
imp_losses = []r_arr = np.exp(np.linspace(0.5, 4, num=5))for r in r_arr: imp_loss = np.array([iLoss.calc_iloss(alpha, r) for alpha in alphas]) imp_losses.append(imp_loss)
m0 = 20; m1 = 500fig, (lp_ax) = plt.subplots(nrows=1, sharex=True, sharey=False, figsize=(12, 5))fig.suptitle(f'Impermanent Loss: Uni V3', fontsize=20)
for k, imp_loss in enumerate(imp_losses): #lp_ax.plot(100*alphas[m0:-m1]-100, 100*imp_loss[m0:-m1]/max(imp_loss[m0:-m1])-1, label = f'Uni V3: r={r_arr[k]:.3f}') lp_ax.plot(100*alphas[m0:-m1]-100, 100*imp_loss[m0:-m1], label = f'Uni V3: r={r_arr[k]:.3f}') lp_ax.set_xlabel("Price Chg (%)", fontsize=12) lp_ax.set_ylabel("Impermanent Loss (%)", fontsize=14)lp_ax.legend(fontsize=10, facecolor="lightgray", loc='lower right')<matplotlib.legend.Legend at 0x157c13f10>
fig, (TKN_ax) = plt.subplots(nrows=1, sharex=False, sharey=False, figsize=(15, 8))
TKN_ax.plot(dates, p_arr, color = 'r',linestyle = 'dashed', linewidth=1, label=f'{tkn1_nm} Price (Global Market)')TKN_ax.scatter(dates, pTKN1_TKN2_arr, s=10, marker='o', color = 'b',linestyle = '-', linewidth=0.7, label=f'{tkn1_nm} Price (LP)')
TKN_ax.set_title('Price comparison: Market vs LP price', fontsize=20)TKN_ax.set_ylabel('Price (USD)', size=20)TKN_ax.legend(fontsize=12)TKN_ax.grid()