Mattheus Public Preview

Join Waitlist

Mattheus Public Preview

Current Blog

How to Model Stop Orders in a Trading Backtest

A stop-order backtest separates the trigger event from the market or limit order created after the trigger, then models latency, liquidity, partial fills, and gaps.

Published Updated
A cobalt market block crosses a warm cream trigger gate and activates an orderly sequence of blue and violet execution blocks

By alyc

This article was prepared with AI assistance and checked through automated editorial and source review. No named human review is recorded.

A stop-order backtest should model two separate events. First, an eligible market event reaches the stop price and triggers the instruction. Second, the resulting market or limit order enters the execution model after any broker, network, and venue latency. The stop price is a trigger, not a promised fill price.

Record the trigger rule, triggering event, event timestamp, order conversion timestamp, child order type, arrival timestamp, available liquidity, fills, fees, and any unfilled quantity. If the data does not show whether a trade or quote was eligible to trigger the order, keep the result uncertain instead of treating a bar high or low as proof of an immediate fill.

Represent the order as a state machine

The SEC defines a stop order as an order to buy or sell once the security reaches a specified stop price. When triggered, a standard stop order becomes a market order. A buy stop is normally placed above the current market price, while a sell stop is normally placed below it.

That definition suggests a simple state machine. A submitted order becomes accepted, then rests as unelected. An eligible event can move it to triggered. The system then creates a child market order or limit order, which can be acknowledged, partially filled, filled, canceled, rejected, or expired. Store each transition separately. A single status called filled hides the events that determine the result.

Choose the trigger source before testing

The SEC's Trading Basics bulletin notes that brokerage firms can use different standards to determine whether a stop price has been reached. Some may use last-sale prices while others may use quotations. Historical venue and broker rules therefore belong in the research inputs.

Define whether the trigger uses a consolidated trade, a venue trade, a bid, an offer, or another broker rule. Add conditions for regular-hours eligibility, odd lots, corrections, canceled trades, and crossed markets when the source data supports them. A quote touching the stop is not valid trigger evidence when the historical instruction required a trade.

Timestamp ordering matters. When an eligible trade and an order cancellation share the same millisecond, use sequence numbers or message order. Do not let the backtest choose the outcome that helps the strategy.

Worked sell-stop example

Consider a synthetic US equity example in Eastern Time. A strategy holds 100 shares and has an accepted sell stop at $48.00. The last quote is $48.10 bid and $48.20 offered. At 10:02:03.125, an eligible trade prints at $47.95 and triggers the stop. After 40 milliseconds of modeled broker and network latency, the child market order reaches bids of 40 shares at $47.90 and 60 shares at $47.75.

The model fills 40 shares at $47.90 and 60 shares at $47.75. Total proceeds before fees are $4,781.00. The volume-weighted execution price is $47.81 per share. Measured against the $48.00 stop, price slippage is $0.19 per share, or $19.00 for 100 shares. Fees and market impact are separate trading-cost inputs.

The numbers are illustrative, not empirical results. They assume the trigger trade is valid, the order was accepted before the trade, latency is 40 milliseconds, displayed bids remain available until arrival, no hidden liquidity participates, and no competing order consumes that liquidity first.

Stop-limit orders can remain unfilled

A stop-limit order converts to a limit order after the trigger. The SEC bulletin explains that this controls the worst permitted price but does not guarantee execution. FINRA's order-type guidance describes the same tradeoff between price control and execution certainty.

Change the worked example to a sell stop at $48.00 with a $47.80 limit. The order can sell the 40 shares bid at $47.90. It cannot sell the remaining 60 shares at $47.75 because that price is below the limit. The backtest should keep the remainder active or expire it according to its time-in-force rule. It must not assume the full 100 shares filled at the stop price.

Once triggered, send the child order through the same limit-order model used elsewhere. That includes queue priority, partial fills, cancellations, and venue-specific handling.

Handle gaps, halts, and opening prints

A market can cross a stop price without trading at it. If a stock closes at $50.00 and opens at $45.00, a sell stop at $48.00 may trigger at the first eligible opening event and execute near available prices, not at $48.00. Bar-based logic that fills at the stop creates a price that may never have been tradable.

A trading halt also interrupts the sequence. Do not trigger or fill from an aggregate bar that spans the halt unless the source proves the event timing. Follow the separate halt and reopening state, then evaluate the stop against eligible reopening or post-resumption events.

Trailing stops need point-in-time state

A trailing stop depends on a running reference such as the highest eligible price since entry. Update that reference only with data available at that timestamp. If a sell trailing stop is 5 percent below the running high, both the high-water mark and the derived stop must be stored after every eligible event.

Do not calculate the day's high first and apply it to earlier timestamps. That is look-ahead bias. Also define rounding, tick size, reset behavior, session boundaries, corporate-action adjustments, and whether quotes or trades move the reference.

Validate trigger and execution separately

Test the model with explicit invariants.

  • No fill occurs before a valid trigger event.

  • The stop price is never treated as a guaranteed execution price.

  • The child order arrives after modeled latency.

  • A stop-limit fill respects its limit price and may remain partial or unfilled.

  • A gap can trigger an order without producing a trade at the stop price.

  • Halted intervals produce no invented executions.

  • A trailing reference uses only point-in-time eligible data.

  • Fees, spread, and impact are reported separately from trigger slippage.

Run cases for a brief price spike, an overnight gap, a halt and reopening, a trigger followed by a canceled trade, a partial stop-limit fill, a cancel racing the trigger, and missing quote or trade sequence data. If the simulation cannot identify both the trigger evidence and the later execution evidence, the fill is not auditable.

Explore Markets with Infinite Context.

Explore Markets with Infinite Context.

Browse the public preview. Join the waitlist for gated trading features.

Browse the public preview. Join the waitlist for gated trading features.

Browse the public preview. Join the waitlist for gated trading features.

Dashboard interface preview