Self-Correcting Virtual Pools
The context: we want to create an internal AMM because keeping an order book requires too much computation and storage. Let’s assume we are working with a simple, constant product AMM (google it, or read this if you aren’t familiar with them).
The problem: an AMM has a slope representing implicit supply and demand curves, but there is inherent reason to believe that the slope of the AMM is accurate (i.e., that faithfully represents actual supply and demand).
Traditionally, an AMM operates by letting people stake liquidity in exchange for a portion of the fees generated when people trade tokens. If demand is really thin, stakers will earn less. If demand is great, stakers will earn more. So there is at least some tendency (although imperfect) for the pool to grow and shrink based on demand.
A virtual pool could, theoretically, constantly adjust its depth to better simulate the contours of an order book, but it may not even have the imperfect market mechanism of a regular AMM to determine how deep it should be. (For a reminder of what a virtual pool is, see here).
So what do we do?
The first thing to note is that there are two types of “errors” a virtual pool can make: 1) it can be too big (which will result in a shallow slope, or too little price impact), and 2) it can be too small (which will result in a steep slope, or too much price impact).
If the virtual pool is too big, when the market price changes, it will take a large volume of trades for the pool price to catch up to the market price. A typical trade will tend to undershoot the market price, so consecutive trades will tend to line up in the same direction.
If the virtual pool is too small, trades will tend to overshoot the market price, so consecutive trades will push the price back and forth around the market price.
We can use this insight to create a self-correcting virtual pool. Basically, all we need to do is keep some average price (e.g., a time weighted average price — TWAP) and then adjust the size of the virtual pool after each trade based on whether the trade overshoots or undershoots the average price.
If a bunch of consecutive trades push the price away from the recent historical average, we can conclude that the pool is too big, so it makes itself smaller. If a bunch of consecutive trades push the price back and forth, above and below the historical average the pool is too small, so it makes itself bigger.
The two main parameters to optimize here are: 1) how far back to we keep the average price, and 2) how much do we resize the pool in response to each trade?