Applied Mathematics on Product Function Type AMM Liquidity Pools and Volatility

Abstract

Here, we discuss the properties and mechanics of different types of automated market making liquidity pools including constant product, constant mean and bounded liquidity. From there, we define and show how to calculate impermanent losses for theses pools. We then show that we can equate impermanent loss as projected APR from fees and rewards and derive a model to find this. We then discuss some pitfalls and remedies of calculation for bounded type pools such as narrow price ranges as well as additional considerations such as interest rates. Practical examples of calculations on live pools are shown to conclude.

Introduction

Automated market making (AMM) liquidity pools are a innovation from cryptocurrencies and decentralized finance (DEFI). Due to the nature of blockchain technology, where transactions can only be processed at the speed at which a new block is minded, a traditional limit order book type of exchange would not be very effective for price discovery nor very friendly towards market makers. For example, the Ethereum blockchain mines a new block around every 12 sec, meaning a traditional order book could only update its pricing quotes at that frequency. Obviously for most higher frequency type of trading that is simply way too slow. There has of course been ways to get around this in the past. For example, one could build the exchange on a much faster blockchain or layer 2 or even to host the actual exchange engine off chain and to periodically clear batch trades on the actual blockchain.
However, there is a third option that allows a robust market to exist natively on slower blockchains through AMM. Here instead of traditional market makers who post and cancel prices between asset pairs, pricing in these pools is defined through a mathematical invariant as a function of the quantity of the assets in the pool. As trades are done that deposit / withdrawal these assets, the price will dynamically update.

There has already been much work in investigating the theoretical properties of these types of pools, details of some can be found in the conclusion. However, the goal of this article is to provide an overview that is both broad and practical in not only understanding the theory but also some practical results and corollaries of these properties, most notably in evaluating the risk-reward profile of different types of pools through a derived implied volatility measure.

Price Derivation

For a given pair i, j, we can define the price of asset i in terms of asset j, p^j_i as the instantaneous rate in which q_i unit of asset i can by exchanged for q_j units of asset j. Taking the limit of this yields

p^j_i = -\frac{dq_j}{dq_i}(1)

Constant Product

Our most basic type of product based AMM is the constant product market maker pioneered by Uniswap V2 and is still used by many other forks. Here we have the formula q_iq_j = k where q_i is the quantity of asset i in the pool and k is an constant. To derive this we apply the definition p^j_i = - \frac{dq_j}{dq_i}. We require an invariance that at any given time the total value of each of these set of assets inside the pool is the same.

p^j_i * q_i = q_j \Rightarrow -\frac{dq_j}{dq_i} = \frac{q_j}{q_i} (2)

Solving this differential equations yields

ln(q_i) + ln(q_j) = c \Rightarrow q_i*q_j = k (3)

Constant Mean

Two Assets

Now suppose that instead of enforcing that both sides of the pool must have equal value, we fix their ratio to something else. For example, in an 80-20 type of pool, we enforce 80% of the equity of the pair in asset i and 20% in asset j. More generally supposing we have a two asset pool where r\% of the equity is in asset i and (1-r)\% of the asset is in asset j. Making these modifications to (2) yields

\frac{p^j_i * q_i}{r} = \frac{q_j}{1-r} \Rightarrow -\frac{dq_j}{dq_i} = \frac{q_jr}{q_i(1-r)} (4)

Again solving and rearranging yields

\frac{r}{1-r}ln{q_i} + ln{q_j} = c \Rightarrow q_j^{1-r}*q_i^{r} = k  (5)

Multiple Assets

Finally let us assume the general case of N assets. WLOG we can consider the j^{th} asset as a numeraire. We then have quantity Q = [q_1,\cdots, q_n], ratio R = [r_1, \cdots, r_n] and price P = [p_1, \cdots, p_n].

We reuse (4) and replace the total derivatives with partials.

-\frac{\partial q_j}{\partial q_i} =\frac{q_{j}r_{i}}{q_{i}r_{j}} \Rightarrow q_i^{r_i}q_j^{r_j} = k for each asset pair i,j. Taking this product across each pair and multiplying them together yields \prod_{i,j = 1}^{n}{q_{i}^{r_i}q_{j}^{r_j}} = {(\prod_{i=1}^{n}{q_{i}^{r_i}})}^{2} = k', which simplifies to

\prod_{i=1}^{n}{q_{i}^{r_i}} = V with constraint \sum{r_i} = 1 (6)

In the limit case of 2 assets and r_1 = r_2 = 0.5, this reduces to the constant product equation.

Bounded Liquidity

We now introduce Uniswap V3 bounded liquidity provision, a special application of the constant product pool. Instead of covering an entire range of p \in (0, \infty), individuals are able to provide liquidity in specific ticks between [p_l, p_h] where at:

i. p < p_l the entire position is held in the volatille asset;

ii. p > P_l, the entire position is held in the numeraire asset;

iii. p_l \leq p \leq p_h the position is held in a mix of each asset

Case iii is specified by a modified virtual constant product liquidity curve that shifts the standard curve such that its endpoints will intersect at 0 for each asset at the respective price p_l, p_u points. More details of the ticks and derivations are specified in the Uniswap V3 white-paper and technical note.

Given constant L, we have:

(q_i + \frac{L}{\sqrt{p_h}})(q_j + L\sqrt{p_l}) = L^2  (7)

Applying boundary cases where either where p < p_l and p > p_h where q_j and q_i are 0 respectively we can also find:

p < p_l \Rightarrow q_i = L (\frac{1}{\sqrt(p_l} - \frac{1}{\sqrt{p_h}}) (8)
p > p_h \Rightarrow q_j = L (\sqrt{p_h} - \sqrt{p_l}) (9)

Finally given L is a constant, we can find the values of q_i, q_j for p_l \leq p \leq p_l

p_l \leq p_i \leq p_h \Rightarrow q_i = L \frac{\sqrt{p_h} - \sqrt{p_i}}{\sqrt{p*p_l}}, q_j = L(\sqrt{p} - \sqrt{p_l})  (10)

It can be seen \lim_{p_l \to 0, p_h\to\infty}(q_i + \frac{L}{\sqrt{p_h}})(q_j + L\sqrt{p_l}) = L^2 \Rightarrow L^2 = q_iq_j recovers the constant product equation.

Impermanent Loss

Price conventions

In most papers and blog posts, the convention for an asset group x-y is to treat the first x-asset as a volatile asset and the y-asset as the numeraire, the unit of account of the pairs. By convention and in practice in many financial markets, the de-facto numeraire that is used is the US Dollar due to a range of historical and economic reasons. However many currency pairs, like ETH-BTC, or even multi-asset pools like ETH-BTC-UNI-DOGE, do not have the dollar as a reference. In these, it is then common practice to treat one of them as a numeraire. However, I am of the opinion that using this convention is not optimal.

There are a few reasons for this. The first is that despite the pipe-dream of every crypto maximalist, BTC, ETH, or any crypto asset is not at the stage of a universally accepted unit of account. Knowing a PnL in ETH is useful, but for practical purposes of using said PnL to pay for housing or buy foods, it’s generally necessary to have it in dollars. This is especially true given the relative volatility of said digital assets. The second reason is in terms of comparing different pools and opportunities it is necessary to have a standard unit of account. For example how would one compare a ETH-BTC pair vs a UNI-DOGE pair. In the case where there’s no common currency between both pools, an intermediate currency needs to be used anyways. Of course that intermediate currency can be ETH, but if we’re going through the effort why not just make it dollars anyways?

Two things can be done. The first is performing calculations with different numeraire assets for each pool and then converting everything in terms of dollars at the end. The second is normalizing all the assets in dollars to begin with, and perform the calculations afterward. I am generally a fan of the second as it’s more direct in terms of keepign track of PnL and balances across each step and less prone to currency conversion mistakes.

Therefore for the rest of this article, a price P_i is the price of asset i denoted in USD unless otherwise specified.

Equity based calculation

There’s already a plethora of resources that instruct how IL is calculated for both standard x-y pools and bounded liquidity pools. Although useful resources I’ve found them to not do an intuitive job of showing what is happening. This is my attempt at a clearer explanation.

IL is the difference between what your PnL would be if you just held your assets compared to what your equity actually is after being transformed in these pools.

IL = \frac{E_f - E_h}{E_f} (11)
Here equity is E = \sum_{i=1}^{n}{p_iq_i} (12)

At the inception of the pool we should also know the vector of initial prices, quantities, ratios of assets, and price bounds of liquidity (if a bounded liquidity pool), P_i, Q_i, R_i, B = [p_l, p_h] .

Note given any 2 of P, Q, R (and B if it’s bounded), the remaining vector is implied.

IL will depend solely on the \% change from initial price vector P^0 to final price vector P^1, with the only computable value being the final quantity vector Q^1 from the equations above.

Constant Mean

Define

S = \prod {({q^0_i})^{r_i}}
t_a = {\frac{r_a}{p^1_a}} 
U = \prod{(t_i)^{r_i}} 
q_a^1 = \frac{S}{U}t_a = \frac{\prod {({q^0_i})^{r_i}}}{\prod{({\frac{r_i}{p^1_i}})^{r_i}}} {\frac{r_a}{p^1_a}} (13)

The proof of (13) as follows.

We equate the initial and final states of the pool \prod{(q^0_{i})^{r_i}} = \prod{(q^1_{i})^{r_i}} due to (6).

For constant mean pools we have the relationship r_a = \frac{p_aq_a}{\sum{p_iq_i}}.

Furthermore to keep a pool in constant ratio r_a = \frac{p^0_aq^0_a}{\sum{p^0_iq^0_i}} = \frac{p^1_aq^1_a}{\sum{p^1_iq^1_i}}.

Therefore we see t_a = \frac{q^1_a}{\sum{p^1_iq^1_i}}.

Furthermore we get U = \frac{\prod{(q_a^1)^{r_a}}}{{\sum{p^1_iq^1_i}}} . Note that the denominator remains the same as \sum{r_i} = 1.

From there it is evident that \frac{t_a}{U} = \frac{q^1_a}{\prod{(q_a^1)^{r_a}}} . Using the equality relationship, the RHS denominator of this term can be substituted S = \prod {({q^0_i})^{r_i}}, which when multiplied recovers the desired quantity q^1_a.

Bounded Liquidity

The final state quantities follow directly from equations (7)-(10) by first finding L from the initial state and using that value to solve for the quantities in the final state.

Treating Impermanent Loss as APR

The impermanent loss is strictly negative. As compensation for this divergence loss, protocols will compensate the providers of this with trading fees and/or token rewards. Generally this compensation will vary on both trading volume and pool policy. Fees are generally a function of trading volume. Token issuers may provide additional incentives for providers on their specific pools. For our purposes we will treat these as exogenous fixed variables.

Oftentimes this variable is reported as a historical APR rate by the protocol. If not, we can use the rules and data of the protocol ourselves to create our own model. For example, rewards based on trading volume can simply be calculated by

\text{fee\_rate} * \text{expected\_trading value} * \text{percent\_stake\_in\_pool}.

We notice that APR is strictly negative. Therefore the profitability of a pool is ultimately dependent on whether the rewards are enough compensation for the loss in IL. In other words, we can ask the question: For a given expected APR, how much IL does it compensate for?

\text{APR} = -{IL} (14)

Given an initial relative price p^j_i between two assets, what new relative prices {p^j_i}' creates a breakeven point for this given APR for a delta-neutral initial position. Note that due to the symmetry of the IL loss function there will be two prices for this, one above the initial p^j_i and another below.

In order to find this we utilize the same equation (11) as before. However, this time the LHS is known, and we are solving for the price vectors P^1 on the RHS by inverting the equation.

Constant Mean

We restrict our case to only evaluating two assets at a given time. For a given IL value with more than two assets, there is an infinite number of relative price combinations that can be taken.

Therefore we will use (5), q_j^{1-r}*q_i^{r} = V , as our invariance and (11), (14) to find APR.

It is thus evident:

\frac{p_iq_i}{r} = \frac{p_jq_j}{1-r} (15)

We now employ a trick by creating a new synthetic asset k that is a basket of \frac{p_i^0}{p_j^0} units of asset j. From this we can see that p_k = \frac{p_i^0}{p_j^0}p_j and q_k = \frac{p_j^0}{p_i^0} q_j.

Rewriting (15) with asset k yields \frac{q_i}{r}=\frac{q_k}{(1-r)}.

Because of this normalization we can pick any p_i as well as any combination q_i, q_k that satisfy \frac{q_i}{q_k} = \frac{r}{1-r}.

For our case we will pick q_i^0 = r, q_k^0=1-r and p_i^0 = p_k^0 = 1

Next we can use equations 11-14 to calculate the IL and APR.

We fix asset i as the numeraire asset and vary p_k. As before, the final quantity vector Q^1 given final price p_k^1.

Q^1 = \frac{(1-r)^{r}r^{1-r}}{(\frac{r}{1})^{r}(\frac{1-r}{p_k^1})^{1-r}} [\frac{r}{1},\frac{1-r}{p^1_k}] 

Taking Q^{1} \cdot P^{1} where P^{1} = [1, p^1_k] yields equity:

E^{1} = \frac{(r)^{r}(1-r)^{1-r}}{(\frac{r}{1})^{r}(\frac{1-r}{p_k^1})^{1-r}} = {p^1_k}^{1-r}
E^{held} = (r)1 + (1-r)p^1_k
IL = \frac{{p^1_k}^{1-r}}{r + (1-r)p^1_k} - 1
APR = 1 - \frac{{p^1_k}^{1-r}}{r + (1-r)p^1_k}

We see p_k = \frac{p_i^0}{p_j^0}p_j \Rightarrow \frac{p_k^1}{p_k^0} = \frac{p_j^1}{p_j^0}. Since p_k^0 = 1 by definition, p_k^1 = \frac{p_j^1}{p_j^0}, which is the relative ratio of the initial and final prices of asset j.

APR = -IL = 1 - \frac{({\frac{p_j^1}{p_j^0})}^{1-r}}{r + (1-r)\frac{p_j^1}{p_j^0}} (16)

Notice that the APR and impermanent loss is solely dictated by the ratio of the equity in the pool and the change in relative price. It is irrespective of the actual prices of the assets. This follows from how there are only two degrees of freedom of the pool from 3 variables, price, ratio and that the price of one asset can always be written in terms of the other.

Now suppose there are n assets with ratios R = [r_1, r_2 \cdots r_n] and prices normalized to asset 1:

E^1 = \prod^{n}_{i=2} (\frac{{p_i^{1}}}{p_i^0})^{r_i}  (17)
E^{held} = \sum^{n}_{i=1} \frac{r_ip^{1}_i}{p^{0}_i}  (18)
APR = -IL = 1 - \frac{E^1}{E^{held}} (19)

Bounded Liquidity

A similar process can be done with bounded liquidity pools using equations 7-10. Again q^0_i = 1 can be applied. Additionally, outside the range [p_l p_h], APR = IL = 0. Prices outside the range means that the asset is not providing liquidity. Therefore they will will neither earn fees nor suffer impermanent loss.

Price can also be normalized, remapping p_j^0 \rightarrow p_k^0 = 1 , with the bounds of liquidity transforming B' = \frac{1}{p_j^0}[p_l, p_h] = [p_a, p_b].

Utilizing (10) finds L and q_j^0; keeping in mind p_k^0 = q^0_i = 1.

Afterwards, we find Q^1 and E^1 in terms of B', L, p_k^1 and again apply (11) to find:

L = \frac{\sqrt{p_b}}{\sqrt{p_b} - 1} 
APR = -IL = 1-\frac{\frac{p_k^{1}L(\sqrt{b} - \sqrt{p_k^1})}{\sqrt{bp_k^1}}+L(\sqrt{p_k^1}-\sqrt{a})}{p_k^1+L(1-\sqrt{p_a})} (20)

Two Solutions

Notice that {p_k^1} should always yield two solutions (s_h, s_l). One where the relative price is higher than the initial p^{k}_0 and one in which it is lower. To find these two solutions, numerical root finding algorithms such as Secant’s method can be used. To recover the actual prices of asset j, we then reintroduce the factor \frac{p_j^0}{p_i^0}.

(S_h, S_l) = \frac{p_j^0}{p_i^0} (s_h, s_l)  (21)

Impermanent Loss as Volatility

Notice that impermanent loss is suffered as a result of two assets diverging in price from each other. Another way of describing divergence is with volatility \sigma which is a very useful metric in options trading and pricing. In this case we can ask, “Assuming that the IL suffered is a certain amount, what is this implying about the volatility of the pair?” To answer this we compute the volatility of log prices. Conventionally, this \sigma is already normalized due to the work that was done before.

\sigma = \sigma([\ln{s_h}, \ln{s_l}]) (22)

Using APR = -IL implies that any given APR will yield an implied volatility due to the rewards. The pool provider will come out ahead if the realized volatility is less than calculated value and come out behind if it is more. Note that the timeframe of this APR is synonymous with the timeframe of volatility. A quoted 1 year APR will return 1 year implied volatility while a 1 day APR will return a 1 day implied volatility.

Limits of Bounded Liquidity

When dealing with a bounded liquidity pool, there is a big problem Suppose there is a particularly big APR \alpha but a very fairly small price bound range [p_l, p_h]. As before, inverting (20) can be used to see for this \alpha value, what prices s_l or s_h does the relative price have to move to breakeven? However, in certain cases, the requisite s_l < p_l or s_h > p_h. What should be done then?

First, consider what happens if we just take the derived prices as is? This doesn’t work. Once the price escapes the price bounds, the position will neither accrue more returns (collect APR), nor will it suffer impermanent loss. As a result, the APR value will be over stated for the periods outside the range. Naively, the model assume think it’s collecting a return and suffering impermanent loss even if it is not.

Another way to think about this is that equation (20) makes the assumption that the price is within the price range 100% of the time. However, if the bounds are small enough, the portfolio will venture outside of the bounds x% of the time. During this x% of the time, the position is “doing nothing” and therefore not collecting the stated APR.

Most directly, we derived equation (20) using the (10) as a starting assumption. Therefore, if the price at any point escape the bounds of equation (10), then the assumptions and therefore results are no longer valid.

Renormalized APR by Time

There is a solution to this. We know that \sigma \propto \sqrt{T} where T is time. APR \propto T assuming simple compounding and APR \propto e^{T} assuming continuous compounding. Then, allow T \rightarrow 0 to find an APR_{adj}. Use this APR_{adj} to find an adjusted \sigma_{adj}. Then we find our \sigma = \frac{\sigma_{adj}}{\sqrt{T}}.

APR_{adj} = \lim_{T \rightarrow 0} {T * APR} \; \textsf{or} \; \lim_{T \rightarrow 0} ({1+APR})^{T} - 1  (22)
\sigma_{adj} = \sigma(ln{p_{kadj_1}^1}, ln{p_{kadj_2}^1})  (23)
\sigma = \lim_{T \rightarrow 0} \frac{\sigma_{adj}}{\sqrt{T}}  (24)

Very Narrow Ranges

For instances where your bounds selection is very narrow compared to the price, (24) will also start to break down. For these situations, it is better to just directly calculate the \sigma from a single tick detailed in this article.

\sigma = 2*\text{fee\_rate}\sqrt{\frac{\text{trading\_volume}}{\text{tick\_liquidity}}} (25)

Additionally, one can use a weighted sum of (25) and (24) with weights as a function of price width ratio.

Bounded Example

Suppose we have assets i,j with p^0 = 1, APR = 100\%, B = [0.5, 2.] . Naively using equation (20) will yield solutions of [0.315, 3.175], which are outside of our range and therefore invalid. However remapping with equations (22)-(24) can correct this. I typically like to use T = \frac{1}{365} as a balance between numerical stability and computational accuracy. Practically it converts a yearly rate into a daily rate which we can think of a daily rebalance hedge frequency. This we yield \sigma = 1.083. For a narrower range, (25) may be a better fit.

Borrow Rates

The last bit of mechanics we can talk about is the borrow costs of the securities. Thus far all of the calculations have been based on a delta neutral strategy. In order to do this in practice, one must borrow these securities or hedge by selling an underlying future. However different securities can have different rates of borrow. Assuming borrow rate c_s and ratio r_i for asset i, we must modify our APR by:

APR_{mod} = APR - \sum{r_i *c_s}  (26)

This APR_{mod} can be used in place of all APR previously. Note that in a constant mean pool r_i is constant while in a bounded liquidity pool r_i varies. For varying r_i, unless the borrow rates for each asset are very big and very different, then it’s “good enough” to just treat them as fixed to what they are when the position is initialized.

Examples

We now apply the methods above to analyze two examples. The first concerns a constant mean product type pool on Balancer, a BAL-WETH 80%-20% pool. The second is a Uniswap V3 bounded liquidity ETH-USDC pool.

To start we can find the prices and borrow rates for the affiliated assets.

BAL: \$3.53, -10.95\%

ETH: \$1702, 8.32\%

USDC: \$1.00, 5.08\%

For USDC, we use the most recent money market rate. For the coins we use the annualized funding rate on the most liquid exchange, Binance. Also note that the BAL funding rate is negative. This means that selling the future allows us to collect instead of pay the rate.

Balancer Pool

APR_{adj} = 5.223 + .810.95 - .28.32 = 12.32%. Using equations (16) and (22) we can find that this yields \sigma_{adj} = 133\%. This is a pretty impressive number, though a significant portion of this is from the “friendly” BAL funding rate. If we just used the raw APR without the funding rates, APR = 5.223\% \Rightarrow \sigma = 83\%.

Uniswap V3 Pool

We use this pool as an opportunity to demonstrate the value of renormalizing APR by time by selecting the thinnest possible width for our bounds of liquidity [1701.1005, 1702.8024]. Furthermore to find the fee rate, divide the 24h Fees by the total value locked at this given tick. Note, we do not divide by the TVL of the whole pool since at any given trade, the fees only go to the liquidity at the current tick, not the entire pool.

APR = \frac{85.36*10^3}{1702 * 438.55} * 365 = 4174\%

This not a typo and certainly looks very impressive as a raw APR figure. However, we keep in mind this is a dollar wide liquidity range on a \$ 1700 asset. This implies in practice this APR will only be collected a very tiny fraction of time. Instead, we can use (24) and (25) to get convert that APR into a \sigma. Note that since it is such a narrow bound, most of the legwork will be from (25).

\sigma = 29 \text{\%}

From this we can compare it to some recent historical ETH-USD realized volatilities of around 31% and 23% for 1 month and 1 week respectively.

Tradingview ETH realized vol
TradingView ETH realized vol

Conclusion

This details analytically way to derive pricing, IL, and volatility for various types of pools. We’ve provided an intuitive, mathematical, and algorithmic way to calculate the properties and impermanent loss risk dynamics of constant product, constant mean product and bounded liquidity type pools. We have also provided a framework to compare these pools to each other as well as other non-linear assets such as options.

There have been other works that further detail pricing mechanics as well as hybrid invariant pools like Curve. Furthermore there is also discussion on derivation of option-like greeks as well as replicating payoffs in general. Additionally, Uniswap has recently released a V4 of their pools which introduces new features such as hooks and flash accounting that adds further dimensions to the products and levying an additional swap fee on some pairs. These new features can generally be incorporated into this analysis.

Leave a Reply