Outlines a strategy for maximizing expected yield on active liquidity for Uniswap-style concentrated liquidity LPs.
optimize.py
uses scipy
to determine the solution numerically, given the complexity of full expressions.optimize.py
) that solvesGiven a pair of tokens
This is an inherently probabilistic question relying on the nature of the stochastic price process
I'll start general by not assuming any particular model for the stochastic price process. Then I'll focus on results for standard but unrealistic GBM.
The LP employs a strategy of deploying liquidity in a set tick range over fixed periods of time
From a vault perspective, this is easier to implement with keepers vs what I've seen from existing work on this topic where LPs rebalance only when price moves out of a range. The latter strategy seems prone to LPs chasing price. Gas costs are less variable in the former as one roughly knows when the rebalance transactions will happen regardless of where the price has gone. It's also easier to analyze analytically.
Assume the LP provides liquidity in a set tick range over a fixed period of time
The LP aims to maximize their excess fee revenues relative to principal losses caused by rebalancing costs. The value of the LP's position will be the principal plus cumulative fee revenues gained over the period less swap fees and slippage incurred on the portion of principal that needs to be rebalanced at the end of the period due to swaps on the pool.
For each time period
I'll examine portfolio values assuming
From this portfolio value expression,
I calculate the yield of the LP's portfolio value over the period. I then maximize the expected value of the yield to determine an appropriate choice of tick width.
I take the LP to be providing active liquidity in an on-chain vault that does not hedge on other venues. Information the vault has access to is constained to the individual pool the LP is providing liquidity on.
The pool sees
Cumulative fees between rebalances taken by the pool are
But the LP only sees a fraction of these fees based on whether the current price is in range
Assume before the LP provides liquidity, the virtual liquidity on the pool is
Further, assume token volumes in are roughly constant throughout the rebalance period, with
Taking the external active liquidity and volumes to each be roughly constant between rebalances avoids estimating liquidity and volume distributions.
The LP receives fees on volume at time
where
for a full tick range width of
for
where I've introduced shorthand
for fee volume per unit of external virtual liquidity (excluding the LP) and the amount of physical tokens the LP contributes to the pool per unit of external virtual liquidity, respectively.
Note that the "payoff" of the future LP fee revenues looks like a portfolio of double digital options with expiries at each successive time
I assume the LP holds the accumulated fees until the end of the rebalance period, at which point they reinvest the fees into principal for the next period. Accumulated
Total value of the fees accumulated in quote terms at the end of the period will be
given prior assumptions on volume.
As a Uniswap V3 liquidity provider, token balances attributed to the LP change as price moves. At any time
At rebalance time
Post rebalance swap, the LP holds token balances of
Principal balances after the swap must satisfy
for the LP to rebalance around the current price at the end of the period. The LP removes their full liquidity contribution then swaps through the remaining external virtual liquidity
where
are virtual token balances ignoring possible changes in external liquidity distribution between ticks (roughly ok for smaller LP sizes).
and
This leads to a principal value at the end of the period post-swap of
Each term represents
The LP optimizes their expected gains at the end of the period from information known at the beginning of the period
Assume the price process abides by GBM
where
To simplify expressions, let
I find for the fee revenue term (see Appendix A)
and below for the principal value terms (see Appendix B).
Principal before rebalance swap:
Swap fees paid on rebalance:
Slippage paid on rebalance:
Hard to have clarity about these expressions from just looking at them. Desmos plots make life easier:
Solid black line is the expected LP value
Optimization for half tick width choice reduces to finding the critical point
at which the yield peaks. Script optimize.py
in the Kodiak simulations repo uses the scipy.optimize
package to find this value.
When ignoring drift
or to first order
I used the Ethereum mainnet Uniswap V3 USDC/ETH 5 bps pool history to fit and set parameters in the Desmos plot above, ignoring drift param results. For a 7 day rebalance period providing about $10M of physical liquidity to a pool with virtual liquidity of about $1.6B and assuming 24h fees of about $500K, a tick width of approximately 0.14 * 2 / log(1.0001) = 2800
(i.e. ~ +/- 15% around current price) appears optimal under GBM with an expected yield at the end of the period after rebalancing of 37 bps.
Need to take the expectation of
From earlier assumptions of GBM
and symmetric LP tick range
Which means
But given the Gaussian increments of the Wiener process,
Need to be a bit more careful with the second term to separate out independent r.v.s. Using Wiener process properties of stationary and independent increments
Leads to
To second order in
I'll divide into separate sections for each term.
From the end of principal losses section,
as
Taking each expectation separately,
Leads to
Also have at the end of principal losses section,
First two expectations can be found in the prior section. Last expectation separates into two terms
which individually evaluate to
Leads to
Finally,
Taking expectations separately,
Leads to