30 min

AMMs: trading against a formula

An automated market maker replaces the human market maker with a pooled pair and an invariant, so the price is a formula over two balances and your own trade moves it against you.

Where you are. Module 4 built a market maker: a firm quoting both sides, managing inventory, earning the spread and carrying the risk of being picked off. This lesson replaces that firm with about four lines of arithmetic.

There is a pool holding cash tokens and bond tokens. Nobody is watching it. There is no quote, no order book, no dealer with a view.

You want bonds, so you send cash to the pool and it sends bonds back. How many? Whatever keeps the product of its two balances from falling. That is the entire rule.

The idea in one paragraph

An automated market maker holds a pair of assets and prices trades by an invariant over its own balances rather than by anybody’s judgement. In the constant-product design, the product of the two balances must not fall, so putting cash in means the pool can release exactly enough of the other asset to keep that true. The price is therefore the ratio of the balances, which means your own trade changes the price while you are making it: buy more and you push the ratio further, and pay a worse average as you go. Nobody quoted you anything, nobody can refuse you, and there is no inventory decision to make, because the formula has already made it.

image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 100 150 200 pooled cash, millions 400 600 800 1000 1200 1400 1600 pooled bonds, thousands the pool sits here every point on this curve has the same product 0 20 40 trade size, percent of the pool 0 10 20 30 40 50 paid above spot, percent 50%
The constant-product curve with the pool's position on it, and the price paid above spot against trade size

Wider than the screen; scroll it sideways.

What the ladder shows

The exercise runs a ladder of trades against a fresh pool each time and records what each paid.

A trade worth a tenth of a percent of the pool pays about a tenth of a percent over the spot price. One worth five percent of the pool pays about five percent. One worth half the pool pays fifty percent over, which is not a bug and not a fee: it is the formula stating, correctly, that taking half a pool’s inventory is expensive.

trade size, share of poolpaid above spot
0.1%0.10%
1%1.01%
5%5.00%
20%20.00%
50%50.00%

n = 5 trials · constant-product pool, one trade each against a fresh pool

The relationship is close to linear in the trade’s share of the pool, which is a genuinely useful rule of thumb: the percentage you pay over spot is roughly the percentage of the pool you are taking. That single sentence lets you size a trade against a pool without doing any arithmetic at all.

How much of the market this is

Check yourself

1. Who decides the price at which a pool trades with you?

Nobody. The invariant does: the product of the two balances must not fall, so the amount the pool can release is determined arithmetically. There is no quote, no judgement and no ability to decline.

2. Why does a larger trade get a worse average price?

Because the trade moves the balances the price is computed from, while it is happening. Taking more of one asset makes the remaining ratio less favourable, so each successive unit costs more. The rule of thumb is that the percentage paid over spot is roughly the percentage of the pool taken.

3. A pool holds a hundred million. Can it absorb a fifty million trade?

It can execute it, at about fifty percent over the spot price, which for most purposes means no. The pool’s total says nothing on its own; the trade as a fraction of the pool is the number that decides the cost.

4. What does the pool lose by having no judgement?

The ability to stop. A market maker with a view can widen, withdraw or refuse when it suspects the person trading knows something it does not. A pool always answers, at a price computed from its own balances, which is exactly what makes it reliable and exactly what makes it exploitable.

Do this

Implement the swap and measure the impact.

python3 code/amm.py

The starter builds the pool on the miniledger and leaves you quote_buy_bonds: work out how many whole token units the pool can release while keeping the product of its balances from falling, rounding down so that rounding never breaks the invariant. The assertions check that a bigger trade always pays worse, that a small trade barely moves the price, and that the invariant never falls.

The completed version is in solutions/amm.py.

What you can now do. You can implement a constant-product swap, explain why the price is a formula rather than a quote, and size a trade against a pool using the share-of-pool rule of thumb. The next lesson asks what the people who funded that pool actually earn.

What you can now do

You can implement a constant-product swap and measure how price impact grows with trade size.