How Much Can You Trade? Size, Fees and Slippage

Lesson 10 of the arbitrage course. Put fees and order book walking together, compute profit as a function of trade size, and find the size where the profit is highest. Short Python code with numbers you can check by hand.

Lesson 10 of the course "Build your own arbitrage bot". In lesson 9 you learned to walk an order book. Today you add fees and ask the question every bot must answer: how many coins should I trade?

Two forces that fight each other

Trading more coins brings two things.

  • More coins mean more money earned from the gap, if the gap exists.
  • More coins mean you reach deeper levels of the book, where prices are worse. That is slippage.

At a small size the gap wins. At a large size slippage wins. Somewhere between them is a size where the profit is highest. If even the smallest size loses money, there is no trade.

Fees sit on top. A fee is a percentage of the money in each trade. Say the fee is 0.1 percent (0.001) on both exchanges. When you buy, you pay the price plus 0.1 percent. When you sell, you receive the price minus 0.1 percent.

Profit for one size, by hand

Use the books from lesson 9:

  • Exchange A, asks: 2 coins at 100.00, then 3 coins at 100.20. You buy here.
  • Exchange B, bids: 1 coin at 100.30, then 5 coins at 99.90. You sell here.

Trade 1 coin.

  • Buy 1 on A: 100.00. With fee: 100.00 × 1.001 = 100.10.
  • Sell 1 on B: 100.30. With fee: 100.30 × 0.999 = 100.1997.
  • Profit: 100.1997 − 100.10 = 0.0997.

Trade 1.5 coins.

  • Buy 1.5 on A: all from the first level, 1.5 × 100.00 = 150.00. With fee: 150.15.
  • Sell 1.5 on B: 1 × 100.30 + 0.5 × 99.90 = 150.25. With fee: 150.0998.
  • Profit: 150.0998 − 150.15 = −0.0502. A loss.

The half coin that went to the second level of B sells at 99.90, which is below what you pay for it. Half a coin too much turned profit into loss.

Profit as a function of size

The head-on way to find the best size is to try many sizes and keep the best, which is what the code below does. It is fine for a few hundred sizes on one pair. A bot that checks thousands of pairs on every price update uses the marginal-profit rule from the next section to stop early.

Write the profit as a function: give it a size, get the money you make. The code uses walk from lesson 9.

def walk(levels, amount):
    money, left = 0.0, amount
    for price, size in levels:
        take = min(size, left)
        money += take * price
        left -= take
        if left <= 0:
            break
    return money, amount - left

asks_A = [(100.00, 2), (100.20, 3)]
bids_B = [(100.30, 1), (99.90, 5)]
FEE = 0.001

def profit(q):
    paid, got_a = walk(asks_A, q)
    received, got_b = walk(bids_B, q)
    if got_a < q or got_b < q:          # the book is too thin for this size
        return None
    return received * (1 - FEE) - paid * (1 + FEE)

for q in [0.5, 1, 1.5, 2, 3, 4, 5]:
    p = profit(q)
    print(q, None if p is None else round(p, 4))

best = max((q / 10 for q in range(1, 51)), key=lambda q: profit(q) if profit(q) is not None else -1e9)
print("best size", best, "profit", round(profit(best), 4))

Output:

0.5 0.0498
1 0.0997
1.5 -0.0502
2 -0.2002
3 -0.7003
4 -1.2004
5 -1.7005
best size 1.0 0.0997

The profit grows up to 1 coin (the size of the top level on B) and falls once the sale reaches 99.90. The best size is 1 coin, with a profit of 0.0997. That is about 0.1 percent of 100, and an ordinary trader's fee is of the same size. This is why arbitrage in liquid markets is a game of small margins.

The rule behind the shape

Walking the book means each extra coin has its own price: the price of the level it comes from. Call the extra profit of the next coin the marginal profit: what you get for it on B minus what you pay for it on A, after fees. While the marginal profit is positive, adding the coin helps. When it turns negative, stop. The best size is where the marginal profit crosses zero.

Check with the example. The first coin: B pays 100.30 × 0.999 = 100.1997, A charges 100.00 × 1.001 = 100.10. Marginal profit +0.0997. The second coin: B pays 99.90 × 0.999 = 99.8001, A charges 100.10. Marginal profit −0.2999. Stop at one coin.

This means you do not need to try every size. Walk both books together, one coin or one level at a time, and stop when the marginal profit is no longer positive. In a real bot the comparison of best prices from lesson 4 is the cheap first filter, and this walk is the second, exact check.

Other limits on size

Even the best size by the book can be too big or too small:

  • Your balance. You cannot buy more than you hold in quote currency.
  • Exchange rules. Every pair has a minimum order size and a step (you cannot trade 0.0000001 coin).
  • Your own risk limit. A bot with a 10 dollar budget does not trade 1000 dollars.

The final size is the smallest of all of these: min(best size by book, balance, risk limit), rounded down to the exchange step. If the result is below the exchange minimum, skip the trade.

Let an AI agent write and test it

A vague request:

Calculate the best trade size.

A request with numbers to check:

Write size.py. Reuse walk from book.py. Add profit(asks, bids, q, fee) returning profit after fees for size q, or None if either book is too thin. Test: asks [(100.00, 2), (100.20, 3)], bids [(100.30, 1), (99.90, 5)], fee 0.001. profit at q = 1 must be 0.0997, at q = 1.5 must be -0.0502, at q = 6 must be None. Then add best_size(asks, bids, fee, step) that tries sizes in multiples of step and returns the best one; for step 0.1 it must return 1.0. Do not use random numbers.

Recompute the first two test values by hand as in this lesson. If the agent's code gives a different profit at 1.5, ask it to show the walk for both sides.

Your exercise

  1. Run the code and compare with the table above.
  2. Change the fee to 0 and then to 0.003. What happens to the best size and the best profit? At which fee does the trade stop being profitable at all? (Hint: at one coin the profit is 0.30 − 200.3 × fee, so it reaches zero at a fee of about 0.15 percent.)
  3. Add a third bid level (99.95, 3) after the first one on B. Compute by hand what happens to the profit at 2 coins, then check in code.
  4. Change walk so that it also returns the average price, and print the average buy and sell prices at the best size.

What comes next

The bot now knows what to trade and how much, by the numbers on the screen. But the numbers on the screen are old by the time the order arrives, orders fill in part, and the second leg can fail. Lesson 11 is a reality check: what can go wrong between the plan and the money.