---
# System prepended metadata

title: Uniswap V3 Special Case

---

# Uniswap V3 Special Case


## Curve Equations

Variable definitions:
* `f` : proportion of capital allocated to price in `[lo, hi]`
* `g` : +/- margin of band around the target price
* `t` : target price
* `L` : liquidity

Let `virtual_L = f L / sqrt( (1/slo - 1/shi) * (shi - slo) )`

---
NOTE AB: I think $$V_L = f L \frac{\sqrt{1+g}}{g }$$ no?

---


For a given `f, g, t,` and `L`, the liquidity (isoutility) curve is given by the following piecewise function:

SIMPLIFIED:

`x (y - f*L*(hi*lo)^{1/4}) = (1-f)^2L^2` for `p < lo`

`(x - f*L/(hi*lo)^{1/4}) y = (1-f)^2L^2` for `p > hi`



UNSIMPLIFIED:

`f(x) :=`

`(x + virtual_L slo)(y + virtual_L / shi) = ( virtual_L + (1-f)L )^2`
on the range: `(1-f) * L * slo <= x <= (1-f)*L*shi + V*(shi - slo)`
(i.e. `p in [lo,hi]`)


`(x - virtual_L (shi - slo)) y = (1 - f)^2 L^2`
on the range: `(1-f)*L*shi + V*(shi - slo) < x`
(i.e. `p < lo`)


`x (y - virtual_L (1 / slo - 1 / shi) ) = (1 - f)^2 L^2`
on the range: `0 < x < (1-f)*L*slo`
(i.e. `p > hi`)

## Difference Equations
Given `(x,y)`, we can derive `L` and from there derive the difference equations.

In all of the following, `V' := f / sqrt((1/slo - 1/shi) * (shi - slo))`

### Find which zone `(x,y)` is in

Based on `(x,y)` you can tell your price is in `(lo, hi)`, `p < lo`, or `p > hi`.

There are two lines that demarcate the difference between these different zones. 

`L1` : between `p < lo` and `p \in (lo,hi)`
`y = ( (1-f) / shi ) / ( (1-f)*shi + V' * (shi - slo) ) * x`


`L2` : between `p \in (lo,hi)` and `p > hi`
`y = ( (1-f)/slo + V' * (1/slo - 1/shi) ) / ( (1-f)*slo ) * x`


Given `(x,y)`, if: 
* `y/x < slope(L1) => p < lo`
* `y/x > slope(L2) => p > hi`
* else => `p /in [lo,hi]`

### `p \in [lo,hi]`
`L` is the root of the following polynomial:

`(V'^2 slo / shi - (V' + (1-f))^2) L^2 + `
`(xV'/shi + y V' slo) L +  xy`

so we're simulating a curve of the form `xy = k` where:
`k = f^2 * L^2 / ((1/slo - 1/shi)(shi - slo))`.

### `p < lo`
`L` is the root of the following polynomial:

`(1-f)^2 L^2 + (V' y (shi - slo)) L - xy`

and we're simulating the curve `xy = k` where `k = (1-f)^2 L^2`


### `p > hi`
`L` is the root of the following polynomial:

`(1-f)^2 L^2 + (V' x (1/slo - 1/shi)) L - xy`

and we're simulating the curve `xy = k` with `k = (1-f)^2 L^2`

### Difference Equations

Once you've found your `k`, since you know which region you're in (below the band, above the band, in the band), you can derive `virtual_x` and `virtual_y` which has the property that `virtual_y / virtual_x = p`.

* `(x,y)` in `p > hi` : `virtual_x = x` and `virtual_y = y + V*(1/slo - 1/shi)`
* `(x,y)` in `p \in [lo, hi]` : `virtual_x = x - V * slo` and `virtual_y = y - V / shi`
* `(x,y)` in `p < lo` : `virtual_x = x + V*(shi - slo)` and `virtual_y = y`

We have that `p = virtual_y / virtual_x`.

For trades that don't cross a tick, calculate the trade using `k` from above.

Given `∆x`: `∆y = k / (virtual_x + ∆x) - virtual_y`
Given `∆y`: `∆x = k / (virtual_y + ∆y) - virtual_x`

If the trade exceeds the tick then separate the trade recursively into two trades, where the second is across the tick and the first trade moves the price to `lo` or `hi`.


## Closed Form Pseudocode
Given `(x, y)`, `f`, `g` and `t`:

IF `y/x < slope(L1)` (i.e. `p < lo`)
: `simulated_L := root_of (p(L) = (1-f)^2 L^2 + (V' y (shi - slo)) L - xy)`
: `k := (1-f)^2 L^2`
: `virtual_x := x + V*(shi - slo)` 
: `virtual_y := y`
: `p := virtual_y / virtual_x`
: IF `∆ = ∆x` THEN `∆y = k / (virtual_x + ∆x) - virtual_y`
: ELSE `∆x = k / (virtual_y + ∆y) - virtual_x`
: IF `(y + ∆y)/(x + ∆x) < lo` or `> hi`, recursively split into two trades such that the first results in `(y + ∆y)/(x + ∆x) = lo` or `= hi`. Return total `∆x` or `∆y`.

ELSE IF `y/x > slope(L2)` (i.e. `p > hi`)
: `simulated_L := root_of (p(L) = (1-f)^2 L^2 + (V' x (1/slo - 1/shi)) L - xy)`
: `k := (1-f)^2 L^2`
: `virtual_x := x`
: `virtual_y := y + V*(1/slo - 1/shi)`
: `p := virtual_y / virtual_x`
: IF `∆ = ∆x` THEN `∆y = k / (virtual_x + ∆x) - virtual_y`
: ELSE `∆x = k / (virtual_y + ∆y) - virtual_x`
: IF `(y + ∆y)/(x + ∆x) < lo` or `> hi`, recursively split into two trades such that the first results in `(y + ∆y)/(x + ∆x) = lo` or `= hi`. Return total `∆x` or `∆y`.

ELSE (i.e. `p \in [lo,hi]`)
: `simulated_L := root_of (p(L) = (V'^2 slo / shi - (V' + (1-f))^2) L^2 + (xV'/shi + y V' slo) L +  xy)`
: `k := f^2 * simulated_L^2 / ((1/slo - 1/shi)(shi - slo))`
: `virtual_x := x - V * slo`
: `virtual_y := y - V / shi`
: `p := virtual_y / virtual_x`
: IF `∆ = ∆x` THEN `∆y = k / (virtual_x + ∆x) - virtual_y`
: ELSE `∆x = k / (virtual_y + ∆y) - virtual_x`
: IF `(y + ∆y)/(x + ∆x) < lo` or `> hi`, recursively split into two trades such that the first results in `(y + ∆y)/(x + ∆x) = lo` or `= hi`. Return total `∆x` or `∆y`.


## Adding Liquidity
Liquidity has to be added in proportion of the *price*, which must be calculated as `virtual_y/virtual_x` or the (magnitude of the) derivative of the isoutility curve at `(x,y)`. This is different from the current value of `y/x`.

## TODO
* Give more details on finding `∆` such that it only hits the tick, not crossing it.