Pool Equations
Price vs. Depth Dynamics
Last updated
Price vs. Depth Dynamics
Last updated
The Dyson pool equations focus on parametric concentration of liquidity near the price. With the slope parameter s
, a pool can be anywhere on a spectrum from: optimized for stablecoin swaps, all the way to: optimized for high volatility, low market cap price discovery. Liquidity on either side of the mark price is proportional to the respective token balances, and there is no additional forcing action to preserve token ratios within a pool.
Depth equations:
Base token side (i.e. SOL in a SOL/USDC pair):
Quote token side (i.e. USDC in a SOL/USDC pair):
Where d
is the token depth (base or quote), b
is the amount of base tokens in the pool, q
is the amount of quote tokens in the pool, m
is the current mark price, p
is the resulting price after a swap, and s
is the slope parameter (ranging from 0 to 1).
Below are a few price<>depth plots for different s
values.
Traditionally it has been impossible to use pool equations which are not either linear or quadratic, (others lacking simple closed-form solutions), largely due to computational restrictions and high gas costs. The equations described in these docs along with the compute capacity on Solana enable these dynamics (more below).
The average token cost for a swap, given an initial mark price and a final mark price, is represented by the following equation (derived from the price<>depth equations).
Where m_init
is the initial mark price, m_final
is the final mark price after the swap and p_avg
is the average cost per token (quote per base).
The s
parameter is currently programmed to be a function of the ratio of internal arbitrage volume vs. standard swap volume. A ratio of 1 indicates that every swap transaction is met with an equal and opposite internal arbitrage transaction (best case scenario), and in this case it is safe to put lots of liquidity near the midpoint. A ratio closer to 0 indicates that price changes are driven entirely by external arbitrage to external markets, and in this case the model is more cautious, putting much less liquidity near the midpoint.
The equations can be explored interactively via the Desmos online graphing calculator: https://www.desmos.com/calculator/usxndq6vcd
The power function pricing equations do not have a closed form solution (unlike all linear or quadratic functions used in DeFi up until now). For this reason, an iterative solution is required.
Initially the protocol was using Newton's Method to find a solution to the price/liquidity equations. Ok but what does this mean? Well, if I have 100 USDC and want to buy SOL, how much SOL do I get? What is the mark price of the pool after the swap?
For a constant product pool the math is simple, but Dyson uses a power formula (mentioned above) to adjust the liquidity near the mark price. Ideally there is lots of liquidity near the mark price for stable swaps, and very little for low cap tokens (which are volatile). This can be dynamic.
Newton's Method requires calculating the above formula and the derivate at each iteration, seen in the animation below. This was how the first version of the protocol worked, but these calculations can get expensive.
So what does v2 look like? The first thing to understand is how the average token price for a given swap is calculated. To find the average swap price, we need to transform the above equations into something that represents cumulative liquidity, weighted by price.
Step 1 - take the equations in (3) and differentiate, to get change-in-cumulative liquidity, a.k.a. liquidity at every price.
Step 2 - multiply the result by price to get price-weighted liquidity.
Step 3 - re-integrate to get price-weighted cumulative liquidity.
Step 4 - divide the result by our original equations in (3), i.e. price-weighted cumulative liquidity divided by cumulative liquidity, and voila! This simplifies beautifully to get the average token price. Note: this does not depend on token amounts!
Great, so back to the algorithm:
In the 100 USDC for SOL example, we can poorly estimate the amount of SOL purchased by using the mark price. That is, for a mark of $20, $100 / $20 = 5 SOL. We know this is wrong because SOL gets more expensive as ask liquidity is removed.
Nevertheless, using the equations in (3) we can find the resulting mark price if 5 SOL of liquidity is removed. With this new mark price we can estimate an average swap price from (7), which will be much more accurate than the $20 estimate used above! And repeat.
The above algorithm converges very very quickly to the correct price.
An outline for the proof of convergence for this algorithm is below.
(Copied from the thread here)
We can use the Banach Fixed Point theorem, which states: for any function g(x) ∈ [a, b] that maps x ∈ [a, b] onto itself, if |'g(x)| is between 0 and 1 on [a, b], then the iteration will converge.
What is our g(x)? The algorithm described in the previous thread uses two separate equations which we will combine into one. First, the estimate for the after-swap mark price, and second, the average token price for the swap. These will be combined to iterate through average token prices.
Before we combine them, it is easier to conceptualize the g: [a, b] → [a, b] mapping by considering them separately. In the algorithm (considering ask-side liquidity first), the initial estimate of the average token price taken as the mark price is the lowest it will ever be. Since we are dividing the quote tokens used in the swap by this cheapest amount, then the highest base token liquidity ever taken will be in the first pass. So, the average token price in the 2nd equation forms the upper bound on [a, b]. The maximum theoretical liquidity allowed in a swap would be 100%, which would be a price of 2*mark_price, and for s=1 would result in an average token price of 1.5*mark_price. For any s<1 the average would be less than 1.5*mark_price due to the convexity.
Similarly, if we suppose that the average swap price in an iteration is 2*mark_price (or even.. infinity), then dividing the quote amount by this high average results in near-zero base token liquidity being removed, and would mean an average swap price in the following iteration of approximately the mark price. This puts a lower bound on [a, b], and we now see that g(x) ∈ [mark_price, 1.5mark_price].
Eq 1 below is the price/liquidity equations (rearranged to solve for final mark price after a swap)
Eq 2 is the average token price equation
Eq 3 is the combination of (1) and (2) and taking the derivative. Where t_q is the number of quote tokens for the swap, and x is the average swap price.
Going back to the fixed point theorem, we need to ascertain whether or not (3) satisfies: |'g(x)| is between 0 and 1 on [a, b]. Since s+1 is in both the numerator and denominator (and that alone would be equal to 1) the question lies in the first two terms in the numerator. Pulling out the root we get: root*(s-1) where the root ∈ [0, 1].
From this we can see that (3) is less than 1 for s < 1 :) which means that the algorithm converges for s < 1.
In the edge case of s=1 however, the solution is found in the first step, since the price<>liquidity depth chart is just a triangle!
QED