Order types and slippage: what happens when your bot sends an order

How market, limit, stop and stop-limit orders actually fill, where slippage comes from, and what an automated trading system should log and handle.

Algorithmic Trading7 min read

Your backtest says the strategy bought at the close. Your live bot sent an order a few seconds after its signal, and the broker reports a fill somewhere else, sometimes in three pieces at three prices. Multiply that gap across hundreds of trades and it can be the whole difference between the equity curve you tested and the one you're living with.

The gap has a name, slippage, and most of it is decided by which order type you send and how your code reacts to what comes back. Here's what each common order type promises, what it doesn't, and what an automated system should do about it.

From signal to fill#

When a strategy decides to trade, there's a price it "saw" at that moment. Between that decision and the final fill, a few things happen. Your code builds an order, the broker receives and validates it, the order is routed to a venue, and it either matches against resting orders or waits in the book. Each step takes time, and the market keeps moving.

Slippage is the difference between the price your strategy expected and the average price you actually got. The broader version of this idea is called implementation shortfall. Mittal's ITG paper, citing André Perold's 1988 work, defines it as the difference in return between a theoretical portfolio and the one you actually implemented. The theoretical portfolio is the backtest. The implemented one is your brokerage statement.

The first cost you hit is the spread. The bid is the highest price a buyer is offering, the ask is the lowest price a seller will accept, and the gap between them is the spread. If your backtest prices trades at the last trade or the midpoint, every buy that crosses to the ask and every sell that hits the bid costs you something the backtest never charged.

Market orders: certain to fill, uncertain price#

A market order says "fill me now at whatever's available". The SEC's investor bulletin on understanding order types is blunt about the trade-off: the execution price of a market order isn't guaranteed, and it can differ from the last traded price. It also notes that parts of a large market order can fill at different prices when there isn't enough liquidity at the best price.

A worked example makes this concrete. Say the best bid is 10.00 and the best ask is 10.02 for 2,000 shares and the next level is 10.03 for 5,000 shares. Your bot sends a market buy for 5,000 shares. It gets 2,000 at 10.02 and 3,000 at 10.03, for an average of 10.026. If the backtest assumed the 10.01 midpoint, that's 1.6 cents a share of slippage before commission, on an order that looks small. In a thinly traded stock the book can be much shallower than this.

Brokers also warn about spikes. Alpaca's order documentation says market orders may fill at unexpected prices because of short-term price spikes. For a bot, that means a market order is the right tool when getting out matters more than the price (closing a position on a risk limit, say), and a poor default for routine entries.

Limit orders: price protected, fill not guaranteed#

A limit order sets the worst price you'll accept. Per the same SEC bulletin, a buy limit can only execute at the limit price or lower, a sell limit only at the limit or higher, and a limit order isn't guaranteed to execute at all.

That last part is the cost people forget. If your bot posts a buy limit below the ask and the price runs away, you get nothing. Your slippage on that trade is zero, and so is your profit on the move you wanted. A strategy that only fills when the market comes back to it can end up filling mostly on trades that are going against it. So when you compare limit and market orders in testing, count missed trades as well as price.

A practical middle ground is a limit order priced at or slightly through the current ask (for a buy). It behaves like a market order in normal conditions, but it puts a ceiling on how far into the book it can go if liquidity disappears. The ceiling is the point: you're choosing how much slippage you'll tolerate before you'd rather not trade.

Stop and stop-limit orders: the ones that surprise people#

A stop order sits dormant until the price reaches the stop price. Then, in the words of the SEC's stop order bulletin, it becomes a market order, and the execution price can deviate significantly from the stop price. A stop at 95 doesn't mean you sell at 95. It means that once the market trades at 95, you send a market sell into whatever bids are left.

The bulletin also warns that a short-term intraday move can trigger a stop, and that trailing stops (where the stop price follows the market by a set amount or percentage instead of sitting at a fixed level) can be set off by short-term fluctuations. FINRA's note on stop orders in volatile markets makes the same point: rapid price moves can trigger a stop, and the fill can be markedly different from the stop price. FINRA adds that the risks have led certain stock exchanges to stop accepting stop orders. Check how your broker accepts and triggers stop orders before your bot relies on one.

A stop-limit order swaps the market order for a limit order once the stop is reached. That caps the price, but the SEC bulletin notes it may not execute if the price moves away from your limit. For a protective exit, that's a hard trade-off. A stop-limit that doesn't fill during a fast drop leaves you holding the position you were trying to leave. If you use them, your bot needs a rule for what happens next, such as escalating to a market order after a set time or a further price move.

Time in force and the session#

Every order also says how long it should live. The SEC order types bulletin describes the common ones. Day orders generally cancel at the end of regular trading hours and don't carry over to the extended session or the next day. Good-til-cancelled (GTC) orders last until filled or cancelled, although brokers may cap how long. Immediate-or-cancel (IOC) fills what it can at once and cancels the rest. Fill-or-kill (FOK) must fill in full immediately or not at all. All-or-none (AON) must fill completely, but unlike FOK it can stay working.

Brokers add their own rules. In Alpaca's documentation, for example, extended-hours orders must be limit orders with a time in force of day or GTC, and opening and closing auction orders use separate opg and cls values. Read your broker's version of this page before you write the order code, because an order your bot assumes is live may have been rejected or expired.

Time in force matters for bots because of state. A GTC order left over from yesterday's run can fill this morning, after your strategy has already decided it wants something else. Unless you have a reason to persist orders, day or IOC orders keep the system's state easier to reason about.

What your code has to handle#

The order you send is a request. What comes back is a stream of status changes, and your bot has to treat it that way. Alpaca's docs list statuses including new, partially_filled, filled, canceled, expired, replaced, pending_cancel and rejected. Other brokers use different names for the same ideas. A few habits prevent most of the expensive surprises:

  • Track position from fills reported by the broker, not from orders you sent. A partially filled order leaves you with a position size your strategy didn't plan for.
  • Give every order your own unique client order ID, so a retried request after a timeout can be matched to the original instead of becoming a second order.
  • Treat a cancel as a request too. Until the broker confirms it, the order can still fill.
  • Know how linked orders behave. In Alpaca's bracket orders (an entry plus take-profit and stop-loss exits), cancelling one order cancels the rest of the group, and a partial take-profit fill shrinks the stop-loss to the remaining quantity.
  • Reconcile on startup. When the process restarts, ask the broker for open orders and positions before doing anything else.

This is also where we spend a lot of the effort when we build trading automation at TheAILAB. The signal logic is often a few hundred lines. The order-state handling around it is usually more, and it's where the tests matter most.

Measuring slippage in your own system#

You can't manage slippage you don't record. For every order, log the price at the moment of the signal, the bid and ask when the order was sent, the time sent, every fill with its price, size and time, and the final status. From that you can compute slippage per trade against the signal price and against the arrival midpoint, split by order type, instrument and time of day.

Then feed it back. Replace the flat cost assumption in your backtest with the slippage you actually measured, ideally per instrument. If the strategy's edge per trade is about the same size as your measured slippage, the live results are telling you something the backtest couldn't.

Start with a week of small live orders, measure every fill, and only then decide which order types your strategy should use by default.

This article is for education only and isn't financial advice. Trading involves risk of loss.

Sources

  1. Understanding Order Types – Investor Bulletin — U.S. SEC Office of Investor Education and Assistance, Investor.gov (2017, updated August 2026) (checked 2026-10-21)
  2. Stop, Stop-Limit, and Trailing Stop Orders – Investor Bulletin — U.S. SEC Office of Investor Education and Assistance, Investor.gov (2017, updated August 2026) (checked 2026-10-21)
  3. Stop Orders: Factors to Consider During Volatile Markets — FINRA (March 2025) (checked 2026-10-21)
  4. Ask price (glossary) — U.S. SEC, Investor.gov (checked 2026-10-21)
  5. Placing Orders — Alpaca API documentation (checked 2026-10-21)
  6. Implementation Shortfall – One Objective, Many Algorithms — Hitesh Mittal, ITG Inc. (2005) (checked 2026-10-21)

Trading a strategy by hand?

If you have rules you already follow and want them automated, tell us about them. You define the strategy; we help automate it.

Get in touch