APR Calculations for CLMM pools
In a CLMM pool, when price trades within an individual tick, fees are distributed proportionally to the liquidity provided by in-range positions. An accurate APR can be found for an individual tick based on trading volume within a time period, however, extrapolating this to all of the ticks in the pool and among multiple LPs is extremely complex. Traditional constant product pool APR calculations can not be directly applied to CLMM pools.
Note: Projected returns for CLMMs should be considered as an estimate at best.
There are three methods for estimating APRs for CLMM pools displayed on Sailor, each with its own calculation described in the following sections:
Overall Pool Estimated APR
Estimated APR for a user position (two methods of calculation below)
Overall Pool Estimated APR
In order to estimate an overall APR for the pool, the following is assumed:
Trading fees and emissions per block are extrapolated across all of the liquidity in the pool, including liquidity positions that are out of range.
Where A P R = â ( d 365 , h 24 , s 3600 , b 0.5 ) â ( p e r B l o c k R e w a r d â r e w a r d P r i c e ) + t o t a l T r a d i n g F e e t o t a l L i q u i d i t y V a l u e \begin{align*}
& \text{Where } APR = \sum(d_{365}, h_{24}, s_{3600}, b_{0.5}) * \frac{(perBlockReward * rewardPrice) + totalTradingFee}{totalLiquidityValue} && \\
\end{align*}
â Where A PR = â ( d 365 â , h 24 â , s 3600 â , b 0.5 â ) â t o t a l L i q u i d i t y Va l u e ( p er Bl oc k R e w a r d â re w a r d P r i ce ) + t o t a lT r a d in g F ee â â â â Estimated APR for Specific User Positions
Delta Method
The Delta Method applies the implied change (delta) in pool liquidity, as determined by a user specified position price range and size, to calculate an estimated APR.
The total amounts of each token can be calculated by using the following formulas:
If i l ⤠i c < i u Where: i l = l o w e r T i c k I d i c = c u r r e n t T i c k I d i u = u p p e r T i c k I d d e l t a Y = d e l t a L â ( s q r t ( P ) â s q r t ( P l ) ) d e l t a X = d e l t a L â ( 1 s q r t ( P ) â 1 s q r t ( P u ) ) \begin{align*}
& \text{If } i_l \leq i_c < i_u &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& \\[10pt]
& \text{Where:} \\
& i_l = lowerTickId \\
& i_c = currentTickId \\
& i_u = upperTickId \\[10pt]
& deltaY = deltaL * (sqrt(P) - sqrt(P_l)) \\[10pt]
& deltaX = deltaL * (\frac{1}{sqrt(P)} - \frac{1}{sqrt(P_u)})
\end{align*}
â If i l â ⤠i c â < i u â Where: i l â = l o w er T i c k I d i c â = c u rre n tT i c k I d i u â = u pp er T i c k I d d e lt aY = d e lt a L â ( s q r t ( P ) â s q r t ( P l â )) d e lt a X = d e lt a L â ( s q r t ( P ) 1 â â s q r t ( P u â ) 1 â ) â For estimation of the amounts of tokenA (deltaX ) and tokenB (deltaY ) we need to know deltaL :
( d e l t a Y â p U S D Y ) + ( d e l t a X â p U S D X ) = t a r g e t A m o u n t So we take: ( d e l t a L â ( s q r t ( P ) â s q r t ( P l ) ) â p U S D Y ) + ( d e l t a L â ( 1 s q r t ( P ) â 1 s q r t ( P u ) ) â p U S D X ) = t a r g e t A m o u n t s Then: d e l t a L = t a r g e t A m o u n t s ( s q r t ( P ) â s q r t ( P l ) ) â p U S D Y + ( 1 s q r t ( P ) â 1 s q r t ( P u ) ) â p U S D X \begin{align*}
& (deltaY * pUSDY) + (deltaX * pUSDX) = targetAmount \\
& \\
& \text{So we take:} \\
& (deltaL * (sqrt(P) - sqrt(P_l)) * pUSDY) + (deltaL * (\frac{1}{sqrt(P)} - \frac{1}{sqrt(P_u)}) * pUSDX) = targetAmounts \\
& \\
& \text{Then:} \\
& deltaL = \frac{targetAmounts}{(sqrt(P) - sqrt(P_l)) * pUSDY} + (\frac{1}{sqrt(P)} - \frac{1}{sqrt(P_u)}) * pUSDX \\
\end{align*}
â ( d e lt aY â p U S D Y ) + ( d e lt a X â p U S D X ) = t a r g e t A m o u n t So we take: ( d e lt a L â ( s q r t ( P ) â s q r t ( P l â )) â p U S D Y ) + ( d e lt a L â ( s q r t ( P ) 1 â â s q r t ( P u â ) 1 â ) â p U S D X ) = t a r g e t A m o u n t s Then: d e lt a L = ( s q r t ( P ) â s q r t ( P l â )) â p U S D Y t a r g e t A m o u n t s â + ( s q r t ( P ) 1 â â s q r t ( P u â ) 1 â ) â p U S D X â After calculating for deltaL , we can calculate deltaX and deltaY using:
d e l t a Y = d e l t a L â ( s q r t ( P ) â s q r t ( P l ) ) d e l t a X = d e l t a L â ( 1 s q r t ( P ) â 1 s q r t ( P u ) ) \begin{align*}
& deltaY = deltaL * (sqrt(P) - sqrt(P_l))\\
& \\
& deltaX = deltaL * (\frac{1}{sqrt(P)} - \frac{1}{sqrt(P_u)}) &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& \\
\end{align*}
â d e lt aY = d e lt a L â ( s q r t ( P ) â s q r t ( P l â )) d e lt a X = d e lt a L â ( s q r t ( P ) 1 â â s q r t ( P u â ) 1 â ) â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â The estimated daily fee can be calculated by:
F e e = f e e T i e r â v o l u m e 24 H â d e l t a L L + d e l t a L Where: v o l u m e 24 H = averageof24hvolume L = total liquidity(cumulativeofliquidityNetfromallticksthati l ⤠i c ) d e l t a L = deltaliquidity \begin{align*}
& Fee = feeTier * volume24H * \frac{deltaL}{L + deltaL} &&&&&&&&&&&&&&&&&&&&&&&&&&&&\\
& \\
& \text{Where:} \\
& volume24H = \text{averageof24hvolume} \\
& L = \text{total liquidity(cumulativeofliquidityNetfromallticksthati}_l \leq ic) \\
& deltaL = \text{deltaliquidity}
\end{align*}
â F ee = f ee T i er â v o l u m e 24 H â L + d e lt a L d e lt a L â Where: v o l u m e 24 H = averageof24hvolume L = total liquidity(cumulativeofliquidityNetfromallticksthati l â ⤠i c ) d e lt a L = deltaliquidity â And can be calculated from:
l i q u i d i t y A m o u n t 0 = a m o u n t 0 â s q r t ( p u ) â s q r t ( p l ) s q r t ( p u ) â s q r t ( p l ) l i q u i d i t y A m o u n t 1 = a m o u n t 1 s q r t ( p u ) â s q r t ( p l ) If i c < i l : d e l t a L = l i q u i d i t y A m o u n t 0 If i c > i u : d e l t a L = l i q u i d i t y A m o u n t 1 If i c ⼠i l  && i c ⤠i u : d e l t a L = m i n ( l i q u i d i t y A m o u n t 0 , l i q u i d i t y A m o u n t 1 ) \begin{align*}
& liquidityAmount0 = amount0 * \frac{sqrt(p_u)*sqrt(p_l)}{sqrt(p_u)-sqrt(p_l)} &&&&&&&&&&&&&&&&&&&&\\
& liquidityAmount1 = \frac{amount1}{sqrt(p_u)-sqrt(p_l)} \\
& \\
& \text{If } i_c < i_l: deltaL = liquidityAmount0 \\
& \text{If } i_c > i_u: deltaL = liquidityAmount1 \\
& \text{If } i_c \geq i_l \text{ \&\& } i_c \leq i_u: deltaL = min(liquidityAmount0, liquidityAmount1) \\
\end{align*}
â l i q u i d i t y A m o u n t 0 = am o u n t 0 â s q r t ( p u â ) â s q r t ( p l â ) s q r t ( p u â ) â s q r t ( p l â ) â l i q u i d i t y A m o u n t 1 = s q r t ( p u â ) â s q r t ( p l â ) am o u n t 1 â If i c â < i l â : d e lt a L = l i q u i d i t y A m o u n t 0 If i c â > i u â : d e lt a L = l i q u i d i t y A m o u n t 1 If i c â ⼠i l â  && i c â ⤠i u â : d e lt a L = min ( l i q u i d i t y A m o u n t 0 , l i q u i d i t y A m o u n t 1 ) â Multiplier Method
The Multiplier Method applies a multiplier, determined by the intersection of the position price range and the historical price range of the pool to calculate an estimated APR.
In order to estimate the future reward and fee APR, the following is assumed:
Historical price data is used to extrapolate future price data, practically this is not the best indicator of future price performance but it does help to provide a decent estimate.
Price fluctuation within the historical price range is consistent in volume across the entire time interval, and resembles a periodic function with an amplitude equalling the magnitude of the upper and lower price boundaries.
We retrieve the following variables:
u l o w e r = Lower bound of userâs concentrated liquidity price range u u p p e r = Upper bound of userâs concentrated liquidity price range h l o w e r = Lower bound of historical price range across a specific time period h u p p e r = Upper bound of historical price range across a specific time period Where: r l o w e r = m a x ( u l o w e r , h l o w e r ) r u p p e r = m i n ( u u p p e r , h u p p e r ) \begin{align*}
& u_{lower} = \text{Lower bound of user's concentrated liquidity price range} &&&&&&&&&&&&&&&&&&&&&\\
& u_{upper} = \text{Upper bound of user's concentrated liquidity price range} \\
& \\
& h_{lower} = \text{Lower bound of historical price range across a specific time period} \\
& h_{upper} = \text{Upper bound of historical price range across a specific time period} \\
& \\
& \text{Where:} \\
& r_{lower} = max(u_{lower}, h_{lower}) \\
& r_{upper} = min(u_{upper}, h_{upper}) \\
\end{align*}
â u l o w er â = Lower bound of userâs concentrated liquidity price range u u pp er â = Upper bound of userâs concentrated liquidity price range h l o w er â = Lower bound of historical price range across a specific time period h u pp er â = Upper bound of historical price range across a specific time period Where: r l o w er â = ma x ( u l o w er â , h l o w er â ) r u pp er â = min ( u u pp er â , h u pp er â ) â For ease of understanding, we will denote the following ranges as such:
u s e r R a n g e = u u p p e r â u l o w e r h i s t R a n g e = h u p p e r â h l o w e r r e t r o R a n g e = r u p p e r â r l o w e r \begin{align*}
& userRange = u_{upper} - u_{lower} &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\\
& histRange = h_{upper} - h_{lower} \\
& retroRange = r_{upper} - r_{lower} \\
\end{align*}
â u ser R an g e = u u pp er â â u l o w er â hi s tR an g e = h u pp er â â h l o w er â re t ro R an g e = r u pp er â â r l o w er â â W here retroRange is the retroactive intersection between userRange and histRange
Let m = multiplier of reward or fees that user will receive If r e t r o R a n g e ⤠0 , m = 0 If u s e r R a n g e = r e t r o R a n g e , m = h i s t R a n g e r e t r o R a n g e If h i s t R a n g e = r e t r o R a n g e , m = r e t r o R a n g e u s e r R a n g e Else m = r e t r o R a n g e t r a d e R a n g e â r e t r o R a n g e u s e r R a n g e \begin{align*}
& \text{Let } m = \text{multiplier of reward or fees that user will receive} &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\\
& \\
& \text{If } retroRange \leq 0, m = 0 \\
& \\
& \text{If } userRange = retroRange, m = \frac{histRange}{retroRange} \\
& \\
& \text{If } histRange = retroRange, m = \frac{retroRange}{userRange} \\
& \\
& \text{Else } m = \frac{retroRange}{tradeRange} * \frac{retroRange}{userRange} \\
\end{align*}
â Let m = multiplier of reward or fees that user will receive If re t ro R an g e ⤠0 , m = 0 If u ser R an g e = re t ro R an g e , m = re t ro R an g e hi s tR an g e â If hi s tR an g e = re t ro R an g e , m = u ser R an g e re t ro R an g e â Else m = t r a d e R an g e re t ro R an g e â â u ser R an g e re t ro R an g e â â
Last updated 4 months ago