mirror of
https://github.com/FlipsideCrypto/uniswap-forecast.git
synced 2026-02-06 10:47:16 +00:00
Liquidity Calcs must also be flexible to x/y y/x options
Affects the math. Solved the sqrtpriceX96 issue and liquidity seems correct. Next step is real world swap math and then go backwards to the simulated pool b/c there isn't really any good math on simulated pool w/ liquidity spread across 1+ positions.
This commit is contained in:
parent
8bbaeb403a
commit
7eafbdd3dc
145
concept.Rmd
145
concept.Rmd
@ -5,6 +5,7 @@ date: "`r Sys.Date()`"
|
||||
output:
|
||||
html_document:
|
||||
code_folding: hide
|
||||
toc: true
|
||||
editor_options:
|
||||
chunk_output_type: console
|
||||
---
|
||||
@ -236,23 +237,32 @@ Tick spacing matters significantly and changes by price tier. The USDC-WETH 0.3%
|
||||
|
||||
```{r, warning=FALSE, message=FALSE}
|
||||
|
||||
tick_to_price <- function(tick, decimal_adjustment = 1){
|
||||
sqrt(1.0001)^(2*tick) * decimal_adjustment
|
||||
# Assumes price is desired in X/Y format, e.g., WBTC/ETH.
|
||||
tick_to_price <- function(tick, decimal_adjustment = 1, yx = FALSE){
|
||||
|
||||
p <- sqrt(1.0001)^(2*tick) * decimal_adjustment
|
||||
if(yx == TRUE){
|
||||
p <- p^-1
|
||||
}
|
||||
return(p)
|
||||
}
|
||||
|
||||
get_closest_tick <- function(desired_price, tick_spacing = 60, decimal_adjustment = 1){
|
||||
# Assumes price is in X/Y format, e.g., WBTC/ETH
|
||||
get_closest_tick <- function(desired_price, tick_spacing = 60, decimal_adjustment = 1, yx = FALSE){
|
||||
# base = sqrt(1.0001)
|
||||
# y = sqrt(price / decimal_adjustment)
|
||||
# base^tick = y
|
||||
# tick = log(y, base)
|
||||
# price = decimal_adjustment*(base^tick)^2
|
||||
|
||||
# assumes x/y pricing
|
||||
|
||||
r <- list(
|
||||
desired_price = desired_price,
|
||||
actual_price = NULL,
|
||||
tick = NULL
|
||||
)
|
||||
|
||||
|
||||
initial_tick <- log( sqrt(desired_price / decimal_adjustment), sqrt(1.0001) )
|
||||
|
||||
if(initial_tick %% tick_spacing == 0){
|
||||
@ -264,6 +274,10 @@ if(initial_tick %% tick_spacing == 0){
|
||||
r$actual_price <- sqrt(1.0001)^(2*final_tick) * decimal_adjustment
|
||||
}
|
||||
|
||||
if(yx == TRUE){
|
||||
r$note <- "v3 assumes X/Y format, your tick may need to be made negative, or price inversed."
|
||||
}
|
||||
|
||||
return(r)
|
||||
|
||||
}
|
||||
@ -505,7 +519,7 @@ Consider the included image of Uniswap v3 WBTC-ETH 0.3% Pool. With the following
|
||||
- Min Price = 0.006 WBTC/ETH
|
||||
- Max Price = 0.249 WBTC/ETH
|
||||
|
||||
Using the previously defined formulas, let's confirm that the min price 0.006 for this range.
|
||||
Using the previously defined formulas, let's confirm that the min price pa = 0.006 for this range.
|
||||
|
||||
`price_all_tokens(x = 100, y = 1000.44, P = 0.068, pa = NULL, pb = 0.249, yx = FALSE)`
|
||||
|
||||
@ -531,12 +545,125 @@ still apply, just use `yx = TRUE` and note the new `Price`, `Min Price` and `Max
|
||||
|
||||
# Spreading Liquidity
|
||||
|
||||
```{r}
|
||||
min_tick <- get_closest_tick(0.05, tick_spacing = 60, decimal_adjustment = 1e10)$tick
|
||||
max_tick <- get_closest_tick(0.25, tick_spacing = 60, decimal_adjustment = 1e10)$tick
|
||||
To pull all 100 WBTC and 1000 ETH into the pool, with a max price of 0.25 WBTC/ETH range with a current price of 0.1 BTC/ETH
|
||||
|
||||
tick_spread <- seq(min_tick, max_tick, by = 60)
|
||||
`price_all_tokens(x = 100, y = 1000, P = 0.1, pa = NULL, pb = 0.25, yx = FALSE)`
|
||||
|
||||
Requires a minimum price of 0.04.
|
||||
|
||||
```{r}
|
||||
reactable(
|
||||
as.data.frame(
|
||||
price_all_tokens(x = 100, y = 1000, P = 0.1, pa = NULL, pb = 0.25, yx = FALSE)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
This range of 0.04 - 0.25 WBTC/ETH converted into actual ticks, with a decimal adjustment of 1e10
|
||||
(WBTC has 8 decimals, ETH has 18: 18 - 8 = 10) and 0.3% fee tier tick spacing of
|
||||
60 converts to tick -55200 and tick -36900.
|
||||
|
||||
```{r}
|
||||
min_tick <- get_closest_tick(0.04, tick_spacing = 60, decimal_adjustment = 10, yx = FALSE)
|
||||
max_tick <- get_closest_tick(0.25, tick_spacing = 60, decimal_adjustment = 10, yx = FALSE)
|
||||
|
||||
reactable(
|
||||
rbind.data.frame(
|
||||
min_tick, max_tick
|
||||
)
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
```{r}
|
||||
|
||||
tick_spread <- seq(min_tick$tick, max_tick$tick, by = 60)
|
||||
|
||||
```
|
||||
|
||||
```{r}
|
||||
|
||||
|
||||
plot(tick_spread, y = rep(1, length(tick_spread)), type = 'l')
|
||||
|
||||
```
|
||||
|
||||
# Real World Spreading Liquidity Example
|
||||
|
||||
Creating a brand new Uniswap v3 Pool on Optimism with a single liquidity position:
|
||||
[MKR/LINK](https://optimistic.etherscan.io/address/0x353ec75f40edb3b794e10bc049532e60d89d5d19) 0.3% Fee Tier
|
||||
with a range of -50100 tick to -39120 tick to prove out the relevant functions.
|
||||
|
||||
The pool was initialized with the following:
|
||||
|
||||
- x = 0.005 MKR (18 decimals)
|
||||
- y = 1.1392 LINK (18 decimals)
|
||||
- P = 0.009264495 MKR/LINK
|
||||
- pa = 0.00667 (tick -50100)
|
||||
- pb = 0.020004 (tick -39120)
|
||||
|
||||
This is the *only* position as of Optimism Block # 26514378.
|
||||
|
||||
```{r}
|
||||
library(gmp) # large numbers library
|
||||
|
||||
price_to_sqrtpx96 <- function(P){
|
||||
# Uniswap stores prices as square roots in 64.96 (64 bits integer, 96 bit fractional)
|
||||
# assume sqrt price is a rational and use gmp big integer
|
||||
|
||||
gmp::as.bigq(sqrt(P)) * gmp::as.bigz(2)^96
|
||||
|
||||
}
|
||||
|
||||
sqrtpX96_to_price <- function(sqrtpX96){
|
||||
p <- as.bigq(sqrtpX96)/as.bigz(2)^96
|
||||
as.numeric(p^2)
|
||||
}
|
||||
|
||||
# although Uni v3 presents ticks in in X/Y (here, MKR/LINK) format
|
||||
# math in related papers uses P = Y/X
|
||||
get_liquidity <- function(x, y, P, pa, pb, yx = FALSE){
|
||||
|
||||
f1 = as.bigq(sqrt(P)) * as.bigq(sqrt(pb))
|
||||
f2 = as.bigq(sqrt(pb)) - as.bigq(sqrt(P))
|
||||
|
||||
L = x * f1 / f2
|
||||
|
||||
return( as.bigz(L) )
|
||||
}
|
||||
|
||||
|
||||
get_liquidity_y <- function(y, P, pb){
|
||||
f1 = as.bigq(sqrt(P)) * as.bigq(sqrt(pb))
|
||||
f2 = as.bigq(sqrt(pb)) - as.bigq(sqrt(P))
|
||||
|
||||
L = y * f1 / f2
|
||||
|
||||
return( as.bigz(L) )
|
||||
}
|
||||
|
||||
get_liquidity_x <- function(x, P, pa){
|
||||
f1 = as.bigq(sqrt(P)) - as.bigq(sqrt(pa))
|
||||
|
||||
L = x / f1
|
||||
|
||||
return( as.bigz(L) )
|
||||
|
||||
}
|
||||
|
||||
x = as.bigz(0.005*1e18) # exact amount integer form
|
||||
y = as.bigz('1139289230675491064') # exact amount integer form
|
||||
# sqrtPriceX96 uint160: 7625888651129286871474510862
|
||||
P = 0.009264495 # taken from contract sqrtPriceX96
|
||||
min_tick <- -50100
|
||||
max_tick <- -39120
|
||||
pa = tick_to_price(min_tick) # price in x/y format
|
||||
pb = tick_to_price(max_tick)
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -30,14 +30,40 @@
|
||||
# 0.005 * 1e18
|
||||
# 5000000000000000
|
||||
|
||||
x = 1.139289230675491064 * 1e18 # decimal adjustment
|
||||
y = 0.004999 * 1e18 # decimal adjustment
|
||||
P = 0.0092645
|
||||
pa = 0.0066726
|
||||
pb = 0.020004
|
||||
y = as.bigq(1.139289230675491064)*1e18 # decimal adjustment
|
||||
x = as.bigq(0.005)*1e18 # decimal adjustment
|
||||
P = 0.009264495
|
||||
min_tick <- -50100
|
||||
max_tick <- -39120
|
||||
pa = 0.006672574
|
||||
pb = 0.02000437
|
||||
|
||||
L = as.bigz("343255264548669212") # actual liquidity
|
||||
sqrtpX96 = as.bigz('7625888651129286871474510862')
|
||||
tick = -46818
|
||||
|
||||
L1 = x*(sqrt(P)*sqrt(pb))/( sqrt(pb) - sqrt(P)) # within 0.02% of L
|
||||
L2 = y / ( sqrt(P)-sqrt(pa) )
|
||||
L2
|
||||
tick_to_price(tick, decimal_adjustment = 1, yx = FALSE)
|
||||
|
||||
library(gmp)
|
||||
L = as.bigz("343255264548669212") # actual liquidity from contract
|
||||
|
||||
get_liquidity_y <- function(y, P, pb){
|
||||
f1 = as.bigq(sqrt(P)) * as.bigq(sqrt(pb))
|
||||
f2 = as.bigq(sqrt(pb)) - as.bigq(sqrt(P))
|
||||
|
||||
L = y * f1 / f2
|
||||
|
||||
return( as.bigz(L) )
|
||||
}
|
||||
|
||||
get_liquidity_y(y, P, pb)
|
||||
|
||||
get_liquidity_x <- function(x, P, pa){
|
||||
f1 = as.bigq(sqrt(P)) - as.bigq(sqrt(pa))
|
||||
|
||||
L = x / f1
|
||||
|
||||
return( as.bigz(L) )
|
||||
|
||||
}
|
||||
|
||||
get_liquidity_x(x, P, pa)
|
||||
|
||||
BIN
proxy_pool_optimism_1.png
Normal file
BIN
proxy_pool_optimism_1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 248 KiB |
@ -1,8 +1,8 @@
|
||||
Version: 1.0
|
||||
|
||||
RestoreWorkspace: Default
|
||||
SaveWorkspace: Default
|
||||
AlwaysSaveHistory: Default
|
||||
RestoreWorkspace: No
|
||||
SaveWorkspace: No
|
||||
AlwaysSaveHistory: No
|
||||
|
||||
EnableCodeIndexing: Yes
|
||||
UseSpacesForTab: Yes
|
||||
|
||||
Loading…
Reference in New Issue
Block a user