Skip to content
Course contents
The order and the order manager

When one order is really many

A large order rarely fills all at once and at one price; it fills in pieces, and pushing too much size at once moves the price against you. This chapter explains partial fills and average fill price, and why traders slice a big order into smaller ones, with a tested example that fills an order in parts and measures the market impact.

9 min readChapter 11 of 28
What you will learn
  • Explain partial fills and how to compute an average fill price across them
  • Explain market impact and why large orders are sliced
  • Track a partially filled order to completion in code

You ask for 100 shares. You get 40 now, 40 in a moment, 20 after that, each perhaps at a slightly different price. This is a partial fill, and it is the normal way a real order of any size behaves. The tidy fiction of the backtest, where you buy your whole quantity at one clean price, does not survive contact with the market. This chapter is about what really happens when an order meets the available supply, and what it costs.

An order fills in pieces

A large order fills in pieces at different prices, and pushing too much size at once moves the price against you, so traders slice a big order into smaller ones.
A large order fills in pieces at different prices, and pushing too much size at once moves the price against you, so traders slice a big order into smaller ones.

Why does an order fill in pieces? Because at any instant there is only so much offered at the best price. If you want more than that, the rest of your order waits, or reaches for the next price level. So a single order can produce several fills, at possibly several prices, and the number you care about is the average fill price: the quantity-weighted average of all the pieces. Your program must track a partly filled order, adding up how much has filled and at what average, until it is either fully filled or you cancel the rest. Here is a single order filling across several ticks.

ExampleA partial fill tracked to completion, and the market impact of a sliced orderch11/slicing.py
# Two truths about large orders. First, one order can fill in several pieces (a
# partial fill), and you track it to completion with a running average price.
# Second, a big order moves the price against you as it fills, so traders slice
# it into smaller child orders. Slicing does not remove that market impact; it
# spaces it out and lets you see it.
from paper_broker import PaperBroker

print("Part A: one order, filled in pieces (a partial fill)")
# liquidity=50 fills a resting limit order 50 shares at a time.
broker = PaperBroker(cash=5_000_000, prices={"RELIANCE": 1400}, liquidity=50)
order = broker.place_order("RELIANCE", "BUY", 150, "LIMIT", price=1400)
print(f"  placed:    {order.filled_quantity}/{order.quantity}  avg {order.average_price}")
for tick in [1400, 1400]:
    broker.feed_price("RELIANCE", tick)
    print(f"  filled:    {order.filled_quantity}/{order.quantity}  avg {order.average_price}"
          f"  ({order.status})")

print("\nPart B: slicing a big buy, and the market impact you still pay")
broker = PaperBroker(cash=50_000_000, prices={"RELIANCE": 1400})
child_prices = [1400, 1401, 1402, 1403, 1404]     # each slice nudges the price up
total_qty, total_cost = 0, 0.0
for i, price in enumerate(child_prices, start=1):
    broker.feed_price("RELIANCE", price)          # the market has moved
    child = broker.place_order("RELIANCE", "BUY", 200, "MARKET")
    total_qty += child.filled_quantity
    total_cost += child.filled_quantity * child.average_price
    print(f"  slice {i}: bought {child.filled_quantity} @ {child.average_price}")

blended = total_cost / total_qty
first_price_cost = 1400 * total_qty
print(f"\n  Bought {total_qty} shares at an average of {blended:.2f}")
print(f"  At the first price 1400 it would have cost {first_price_cost:,}")
print(f"  Actual cost {int(total_cost):,}, so market impact was "
      f"{int(total_cost) - first_price_cost:,} rupees")
Output
Part A: one order, filled in pieces (a partial fill)
  placed:    50/150  avg 1400.0
  filled:    100/150  avg 1400.0  (PARTIALLY_FILLED)
  filled:    150/150  avg 1400.0  (FILLED)

Part B: slicing a big buy, and the market impact you still pay
  slice 1: bought 200 @ 1400.0
  slice 2: bought 200 @ 1401.0
  slice 3: bought 200 @ 1402.0
  slice 4: bought 200 @ 1403.0
  slice 5: bought 200 @ 1404.0

  Bought 1000 shares at an average of 1402.00
  At the first price 1400 it would have cost 1,400,000
  Actual cost 1,402,000, so market impact was 2,000 rupees

Look at Part A. The order for 150 shares fills 50 at a time as prices arrive, moving from 50 to 100 to 150, and the program reports the running fill and average at each step. Until that last fill, the order is only partly done, and a program that treated the first 50 as the whole 150 would have its size badly wrong. Tracking the partial to completion is not optional bookkeeping. It is how the program knows what it actually holds.

Big orders move the price

Part B shows the other half of the problem. A large order does not just wait for supply, it consumes it, and in doing so pushes the price. Buy aggressively and you lift the price as you go, so each slice costs a little more than the last. That gap, between the price you first saw and the average price you paid because of your own buying, is called market impact. In the example, buying 1,000 shares in five slices as the price ticks up from 1,400 to 1,404 gives an average of 1,402, and the difference from the first price, 2,000 rupees on this trade, is the impact you paid for size.

This is why traders slice a large order into smaller child orders and feed them in over time, rather than sending one giant order that would sweep the book and pay a large impact all at once. Slicing does not make impact vanish, as Part B shows plainly. It spreads the buying out so you pay it gradually and can stop if the price runs away. The deeper lesson, which the reality chapters return to, is that size itself is a cost: the bigger your order relative to the market, the more your own trading moves the price against you.

What to carry forward

A real order fills in pieces, so your program must track the running quantity and the quantity-weighted average fill price until the order completes, never treating a partial as done. A large order also pays market impact: by consuming the available supply it pushes the price against itself, which you saw as a 2,000-rupee gap on a 1,000-share buy. Slicing spreads that impact over time rather than erasing it, and the broader truth is that size is a cost that grows with how much you trade relative to the market. Keeping all this order state straight, across many orders, is a job of its own, and the next chapter builds the order manager that does it.