Order Types Explained: Market, Limit, Stop and More

Order types are the protocol-level primitives your strategy uses to express intent to a matching engine, and the choice among them is a microstructure decision with direct PnL consequences. The same alpha, expressed through a marketable order versus a passive resting order, can flip from net-positive to net-negative once you account for spread capture, queue position, fee tier, and adverse selection. This guide treats order types as an execution-engineering problem: how each one interacts with the limit order book, what it costs in expectation, and where its failure modes live.

The control surface: price, time, and display

Every order is a tuple of decisions that the matching engine enforces deterministically. The three axes that matter most:

  • Price condition — unconditional (market), bounded (limit), or triggered (stop, stop-limit).
  • Time-in-force — how long the order is eligible to rest and whether partials are permitted.
  • Display and flags — visible size, post-only, reduce-only, hidden, and similar venue-specific attributes that change priority and fee treatment.

A market order maximizes fill probability and surrenders price; a passive limit maximizes price control and spread capture while taking on fill uncertainty and adverse selection. There is no order that dominates on all axes. Selecting one is equivalent to choosing a point on the impact-vs-timing-risk frontier that the execution algorithms literature formalizes.

Market orders and book-walking

A market order is matched against resting liquidity in price-time priority until filled. The realized cost is not the touch price but the size-weighted average across consumed levels. Model it explicitly rather than assuming you trade at the top of book.

def walk_book(levels, qty):
    """levels: list of (price, size) best-first. Returns avg fill and slippage vs touch."""
    touch = levels[0][0]
    filled, cost = 0.0, 0.0
    for price, size in levels:
        take = min(size, qty - filled)
        cost += take * price
        filled += take
        if filled >= qty:
            break
    if filled < qty:
        raise ValueError("insufficient displayed depth")
    avg = cost / qty
    return avg, (avg - touch) / touch * 1e4  # slippage in bps

asks = [(50.01, 300), (50.03, 200), (50.06, 600)]
avg, slip = walk_book(asks, 1000)   # ~50.043, ~6.5 bps over touch

Two caveats professionals never skip. First, displayed depth understates or overstates true depth depending on hidden/iceberg liquidity and the cancel rate of fast quoters — your simulated walk is an upper bound on certainty, not a guarantee. Second, market orders are unconditionally takers and pay the taker fee on every share, so the all-in cost is half-spread + impact + taker_fee. Use market orders when the option value of immediacy exceeds that sum: protective exits, hard deadlines, and fast-decaying signals.

Limit orders, queue position, and adverse selection

A limit order rests at a price and fills only at that price or better. Its economics are dominated by two effects that beginners ignore: queue position and adverse selection.

Under price-time priority, your fill probability at a level depends on how much size sits ahead of you. If 8,000 shares rest ahead at your price and the level typically trades 3,000 before the quote moves, your resting order rarely fills unless the market is about to trade through — which is precisely when you are being adversely selected. The passive trader's payoff is a short option: you collect the half-spread plus any maker rebate when uninformed flow crosses to you, and you lose when informed flow picks you off right before the mid moves against your fill.

A back-of-envelope condition for a passive quote to be profitable:

E[passive edge] = P(fill | uninformed) * (half_spread + maker_rebate)
                - P(fill | informed)  * E[adverse move | informed]

If your fills cluster immediately before unfavorable mid moves, the second term dominates and you should widen, reduce size, or step back. A marketable limit (limit buy above the ask) caps worst-case price while crossing immediately — useful to bound slippage on urgent entries — but it pays taker fees because it removes liquidity. See transaction costs and slippage for how these terms aggregate, and market microstructure for the queue mechanics in depth.

Stop and stop-limit: trigger semantics matter

A stop order is dormant until a trigger condition on a reference price is met, then it converts. The reference is venue-specific and worth verifying: a sell stop usually triggers off the bid (or last), a buy stop off the ask. The distinction between a stop-market and a stop-limit is the difference between guaranteed exit at an uncertain price and uncertain exit at a bounded price.

  • Stop-market: fires a market order on trigger. Guarantees the exit, exposes you to gap slippage. In a fast dislocation your fill can be several levels past the stop.
  • Stop-limit: fires a limit on trigger. Bounds the fill price, but if the book gaps through your limit you are left holding the position with no protection — the worst outcome for a risk control.

For protective stops, the asymmetry usually favors stop-market: a guaranteed exit at a bad price beats an unfilled limit while the position runs. Reserve stop-limits for entries or for situations where a non-fill is genuinely preferable to a bad fill. Note also that resting stop orders are often visible to the venue's matching engine and clustered stops at round numbers are a known liquidity-event trigger.

Trailing stops and volatility scaling

A trailing stop ratchets in the favorable direction by a fixed offset and never retreats. The only engineering decision that matters is the offset: a fixed percentage churns you out in noisy regimes and leaves too much on the table in quiet ones. Scale the trail to realized volatility — for example an ATR multiple — so the stop respects the instrument's current noise rather than a static guess. This is standard in trend-following systems, where exit discipline drives most of the realized edge, and it connects directly to how you measure volatility.

Time-in-force and partial-fill handling

Time-in-force governs eligibility and partial behavior. The differences are operationally significant for any automated system.

TIFPartial fillsRests on bookPrimary use
GTCYesYesPassive accumulation, market making
DayYesYes (until close)Session-bounded working orders
IOCYesNoSweep available liquidity, leave no footprint
FOKNo (all-or-nothing)NoAtomic fills where partials are unmanageable

IOC is the workhorse for liquidity sweeps: it takes whatever is available up to your limit and cancels the remainder, avoiding a resting order that signals intent. FOK is stricter and useful when a partial would leave an awkward hedge leg unfilled (multi-leg arbitrage). Critically, your order manager must treat partial fills as the normal case: track filled quantity, weighted average price, and remaining size, and reconcile against the venue rather than assuming an order is either fully open or fully done.

Advanced order types and venue flags

  • Iceberg / reserve: displays a slice of total size, refilling as each tranche fills. Reduces signaling but note that each refill typically loses time priority — you go to the back of the queue at that price. The displayed slice is a tradeoff between concealment and queue decay.
  • Post-only: rejects or reprices any order that would cross, guaranteeing maker status. Essential for rebate-dependent strategies; budget for rejections when the quote you wanted is already marketable.
  • Reduce-only: prevents an order from increasing net exposure, a safety primitive for derivatives where a stale signal could otherwise flip you long-to-short.
  • OCO (one-cancels-other): brackets a take-profit and protective stop so exactly one executes. Prevents the double-exit race condition.
  • Pegged: tracks a reference (mid, best bid) so quotes stay competitive without manual re-quoting, at the cost of more message traffic against rate limits.

Fee tiers and the maker/taker economics

For high-turnover strategies, order type is mostly a fee decision. Maker rebates and taker fees are tiered by 30-day volume, and the spread between them determines whether a thin edge survives. Consider a desk doing 1,000,000 USD notional per day, comparing always-taker versus always-maker on a 0.10% taker / 0.02% maker-rebate schedule.

StylePer 1M notionalDailyAnnual (252d)
Always taker-1,000-1,000-252,000
Always maker+200+200+50,400
Mixed (60% maker)-280-280-70,560

The taker-to-maker swing here is roughly 300,000 per year on identical volume — frequently larger than the strategy's gross alpha. This is why scalping and market-making systems default to post-only and treat any taker fill as a tracked, budgeted cost rather than a default.

A routing decision, in code

A practical order router encodes the urgency-vs-cost tradeoff explicitly rather than hardcoding one order type.

def route(side, qty, book, urgency, fee_taker=10, rebate_maker=-2):
    """urgency in [0,1]. Returns an order spec. Fees in bps."""
    best_bid, best_ask = book["bid"][0][0], book["ask"][0][0]
    spread_bps = (best_ask - best_bid) / best_bid * 1e4
    if urgency > 0.8:
        return {"type": "market", "qty": qty, "exp_cost_bps": spread_bps / 2 + fee_taker}
    if urgency > 0.4:
        cap = best_ask if side == "buy" else best_bid
        return {"type": "limit", "tif": "IOC", "price": cap, "qty": qty,
                "exp_cost_bps": spread_bps / 2 + fee_taker}
    px = best_bid if side == "buy" else best_ask  # join passive side
    return {"type": "limit", "tif": "GTC", "post_only": True, "price": px, "qty": qty,
            "exp_cost_bps": -spread_bps / 2 + rebate_maker}

This is deliberately simple; a production router also weighs queue length, recent fill rate, and remaining schedule from the parent execution algorithm.

Honest limits

Order-type modeling has hard boundaries. Displayed depth is not executable depth: hidden liquidity, latency, and fast cancels mean your pre-trade book walk is an estimate, not a fill guarantee. Queue-position models are approximations — most venues do not reveal your exact rank, so passive fill probability must be inferred empirically from your own fill logs. Fee schedules change with volume tiers and venue promotions, so yesterday's maker/taker math may not hold this month. The discipline is to log intended order type, intended price, and realized fill for every trade, then compute realized slippage and reconcile it against your assumptions. You cannot optimize an execution layer you do not measure.

Conclusion

Order types are the lowest-level lever on execution cost, and at high turnover they often determine whether an edge clears its own frictions. Default to post-only/maker where the strategy tolerates fill uncertainty, use IOC and marketable limits to bound slippage on urgent flow, reserve market orders for genuine immediacy, and prefer stop-market over stop-limit for protection. Tie trail and stop distances to realized volatility, treat partial fills as the norm, and reconcile every fill against the venue. Combined with disciplined transaction cost analysis and a working knowledge of market microstructure, order-type selection becomes a measurable, optimizable part of the system rather than a button you press by reflex — which is exactly what a thin edge needs to survive contact with the market in an automated trading bot.

#order types #limit order #stop loss #market order #execution