Trailing Stop vs Trailing Stop-Limit Orders
Trailing stop vs trailing stop-limit: the trigger ratchets the same way in both, and the gap down is where they split. Worked on real SPY and AAPL sessions.
Trailing stop vs trailing stop-limit: both are stop orders whose trigger price ratchets upward with the market, and the only difference between them is what the trigger sends. A trailing stop sends a market order, which fills at whatever price the book holds. A trailing stop-limit sends a limit order at a preset offset, which fills at that price or better, or does not fill while the position stays open.
The base stop mechanics are covered in stop order vs stop-limit order, and the market versus limit distinction in market order vs limit order. What follows is the trailing part, worked on real sessions.
Trailing stop vs trailing stop-limit: the one real difference
Picture a long position with a 10% trailing stop attached. The order records the highest price reached while it is live, the high-water mark, and holds a trigger 10% under it. A new high lifts the trigger. No new high leaves it alone. The level never moves down.
Up to the trigger, the two orders are identical. At the trigger they split. A trailing stop releases a market order to sell, which will almost certainly fill, at the best price available that instant. A trailing stop-limit releases a limit order to sell at a price you set when placing it, usually a short distance under the trigger, and that order fills at the limit or better, or not at all. One side buys fill certainty. The other buys price certainty.
Example one: an orderly decline
An orderly decline is the case both orders handle well. The price steps lower, every level between the high-water mark and the trigger actually trades, and the trigger is reached inside a liquid regular session. The panel below takes a real one: AAPL's daily closes through the first ten weeks of 2022, with the running high-water close and a 10% trail drawn under it.
| session_date | calendar_label | close_px | high_water_close | trail_10pct_level |
|---|---|---|---|---|
| 2022-01-03 | Jan 3, 2022 | 182.01 | 182.01 | 163.81 |
| 2022-01-04 | Jan 4, 2022 | 179.7 | 182.01 | 163.81 |
| 2022-01-05 | Jan 5, 2022 | 174.92 | 182.01 | 163.81 |
| 2022-01-06 | Jan 6, 2022 | 172 | 182.01 | 163.81 |
| 2022-01-07 | Jan 7, 2022 | 172.17 | 182.01 | 163.81 |
| 2022-01-10 | Jan 10, 2022 | 172.19 | 182.01 | 163.81 |
| 2022-01-11 | Jan 11, 2022 | 175.08 | 182.01 | 163.81 |
| 2022-01-12 | Jan 12, 2022 | 175.53 | 182.01 | 163.81 |
| 2022-01-13 | Jan 13, 2022 | 172.19 | 182.01 | 163.81 |
| 2022-01-14 | Jan 14, 2022 | 173.07 | 182.01 | 163.81 |
| 2022-01-18 | Jan 18, 2022 | 169.8 | 182.01 | 163.81 |
| 2022-01-19 | Jan 19, 2022 | 166.23 | 182.01 | 163.81 |
| 2022-01-20 | Jan 20, 2022 | 164.51 | 182.01 | 163.81 |
| 2022-01-21 | Jan 21, 2022 | 162.41 | 182.01 | 163.81 |
| 2022-01-24 | Jan 24, 2022 | 161.62 | 182.01 | 163.81 |
| 2022-01-25 | Jan 25, 2022 | 159.78 | 182.01 | 163.81 |
| 2022-01-26 | Jan 26, 2022 | 159.69 | 182.01 | 163.81 |
| 2022-01-27 | Jan 27, 2022 | 159.22 | 182.01 | 163.81 |
| 2022-01-28 | Jan 28, 2022 | 170.33 | 182.01 | 163.81 |
| 2022-01-31 | Jan 31, 2022 | 174.78 | 182.01 | 163.81 |
The exact SQL behind every number
WITH daily AS
(
SELECT
date,
toFloat64(any(close)) AS close_px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'AAPL'
AND date >= '2022-01-03'
AND date < '2022-03-16'
GROUP BY date
),
marked AS
(
SELECT
date,
close_px,
max(close_px) OVER (ORDER BY date ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS peak_close
FROM daily
)
SELECT
toString(date) AS session_date,
formatDateTime(date, '%b %e, %Y') AS calendar_label,
round(close_px, 2) AS close_px,
round(peak_close, 2) AS high_water_close,
round(peak_close * 0.9, 2) AS trail_10pct_level
FROM marked
ORDER BY date ASCThe window opens on Jan 3, 2022 at $182.01, which stood as the high-water mark for the whole stretch. The running peak still reads $182.01 on the final session shown, so the 10% trail held at $163.81 throughout, and by Mar 15, 2022 the close had reached $155.09.
Follow the two lines and the orderly part is visible. The close works down through the trail level during regular hours, with prints on both sides of it. A trailing stop sends its market order into that book and fills close to the trigger in a name this liquid. A trailing stop-limit placed a short distance under the trigger fills as well, at its limit or better. On a decline shaped like this, the two orders are near enough to interchangeable.
Trail by amount, or trail by percent
A trail is quoted one of two ways. A trail by amount keeps the trigger a fixed dollar distance under the high-water mark, $5 below at any price. A trail by percent keeps it a fixed proportion below, so 10% is $18 on a $180 stock and $13 on a $130 one. A percent trail holds its width as the price moves. A dollar trail tightens in percentage terms as the price rises.
Width is a separate decision from the stop versus stop-limit choice. The panel below extends the same AAPL window through the first half of 2022 and asks when each trail width would first have been reached.
| label | first_trigger_day | days_into_window | closes_at_or_below_trail |
|---|---|---|---|
| 5% trail | Jan 6, 2022 | 3 | 104 |
| 8% trail | Jan 19, 2022 | 16 | 82 |
| 10% trail | Jan 21, 2022 | 18 | 65 |
| 15% trail | Mar 14, 2022 | 70 | 38 |
| 20% trail | May 12, 2022 | 129 | 25 |
The exact SQL behind every number
WITH daily AS
(
SELECT
date,
toFloat64(any(close)) AS close_px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'AAPL'
AND date >= '2022-01-03'
AND date < '2022-07-01'
GROUP BY date
),
marked AS
(
SELECT
date,
close_px,
max(close_px) OVER (ORDER BY date ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS peak_close
FROM daily
),
widths AS
(
SELECT arrayJoin([5, 8, 10, 15, 20]) AS trail_pct
)
SELECT
concat(toString(w.trail_pct), '% trail') AS label,
formatDateTime(min(m.date), '%b %e, %Y') AS first_trigger_day,
dateDiff('day', toDate('2022-01-03'), min(m.date)) AS days_into_window,
count() AS closes_at_or_below_trail
FROM marked AS m
CROSS JOIN widths AS w
WHERE m.close_px <= m.peak_close * (1 - w.trail_pct / 100)
GROUP BY w.trail_pct
ORDER BY w.trail_pct ASCThe 5% trail was first reached on Jan 6, 2022, 3 calendar days into the window, and the close sat at or under that level on 104 of its sessions. The 20% trail waited until May 12, 2022, 129 days in. Tighter trails reach their trigger earlier and more often. Wider trails sit through more of the move. Neither width changes what happens once the trigger is reached.
Example two: the same position, into a gap
Now the case that separates them. A gap is a session that opens away from the previous close, with nothing traded in between. A release before the bell, or news while the market is shut, and the first print of the day simply arrives lower. Every level inside the gap went untraded. Gaps are not exotic, as twenty years of SPY opens show.
| gap_bucket | gap_count | share_pct |
|---|---|---|
| opened 3% or more below | 18 | 0.35 |
| opened 2% to 3% below | 45 | 0.86 |
| opened 1% to 2% below | 218 | 4.18 |
| opened 0.5% to 1% below | 440 | 8.43 |
| opened less than 0.5% below | 1617 | 30.99 |
| opened flat or higher | 2879 | 55.18 |
The exact SQL behind every number
WITH daily AS
(
SELECT
date,
toFloat64(any(open)) AS open_px,
toFloat64(any(close)) AS close_px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2006-01-01'
AND date < '2026-10-01'
GROUP BY date
),
sessions AS
(
SELECT
date,
open_px,
lagInFrame(close_px) OVER (ORDER BY date ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prior_close
FROM daily
),
gaps AS
(
SELECT round(100 * (open_px / prior_close - 1), 4) AS gap_pct
FROM sessions
WHERE prior_close > 0
)
SELECT
multiIf(gap_pct <= -3, 'opened 3% or more below',
gap_pct <= -2, 'opened 2% to 3% below',
gap_pct <= -1, 'opened 1% to 2% below',
gap_pct <= -0.5, 'opened 0.5% to 1% below',
gap_pct < 0, 'opened less than 0.5% below',
'opened flat or higher') AS gap_bucket,
count() AS gap_count,
round(100 * count() / sum(count()) OVER (), 2) AS share_pct
FROM gaps
GROUP BY gap_bucket
ORDER BY min(gap_pct) ASCThe open came in flat or higher on 55.18% of those sessions. Deep gaps are rare and entirely real: 18 sessions opened 3% or more under the prior close, 0.35% of the total. Single names gap harder than an index fund does, since an index spreads any one company's move across hundreds of holdings.
On a gap morning the trigger can be jumped outright. The next panel takes the ten deepest gap-down opens in that SPY history and measures each session's open and its two intraday extremes as distances under the prior close.
| label | gap_below_prior_close_pct | intraday_high_below_prior_close_pct | intraday_low_below_prior_close_pct |
|---|---|---|---|
| Mar 16, 2020 | 10.45 | 4.61 | 11.87 |
| Oct 24, 2008 | 8.32 | 1.93 | 8.39 |
| Mar 9, 2020 | 7.45 | 4.46 | 8.07 |
| Mar 12, 2020 | 6.69 | 2.81 | 9.72 |
| Mar 18, 2020 | 6.55 | 1.75 | 9.8 |
| Aug 24, 2015 | 5.23 | 0.18 | 7.8 |
| Oct 10, 2008 | 4.34 | -3.57 | 7.85 |
| Aug 5, 2024 | 3.99 | 1.75 | 4.25 |
| Apr 1, 2020 | 3.79 | 0.04 | 5.37 |
| Jan 22, 2008 | 3.67 | -0.28 | 4.59 |
The exact SQL behind every number
WITH daily AS
(
SELECT
date,
toFloat64(any(open)) AS open_px,
toFloat64(any(high)) AS high_px,
toFloat64(any(low)) AS low_px,
toFloat64(any(close)) AS close_px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2006-01-01'
AND date < '2026-10-01'
GROUP BY date
),
sessions AS
(
SELECT
date,
open_px,
high_px,
low_px,
lagInFrame(close_px) OVER (ORDER BY date ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prior_close
FROM daily
)
SELECT
formatDateTime(date, '%b %e, %Y') AS label,
round(100 * (1 - open_px / prior_close), 2) AS gap_below_prior_close_pct,
round(100 * (1 - high_px / prior_close), 2) AS intraday_high_below_prior_close_pct,
round(100 * (1 - low_px / prior_close), 2) AS intraday_low_below_prior_close_pct
FROM sessions
WHERE prior_close > 0
ORDER BY open_px / prior_close ASC
LIMIT 10Take the worst of them, Mar 16, 2020. The open printed 10.45% under the prior close, the low reached 11.87% under, and the best price the session ever saw still sat 4.61% under it. Even the tenth-deepest gap on the list opened 3.67% under its prior close.
Drop both orders into that session with the same high-water mark and the same trail, say a trigger 5% under the mark. The trailing stop triggers at the opening print, releases its market order, and fills somewhere in the opening range, far under the trigger. That is the mechanic in why stop orders fill below the stop price, and the trailing part changes none of it.
The trailing stop-limit does something else. Its limit, a modest distance under the trigger, sits above every price the session traded. The order goes live, rests unfilled, and the position stays open while the price keeps moving away. The order worked as specified. The market never came back up to the limit. Under a day time in force it expires that afternoon, and as good-til-canceled it keeps resting at a level the market has left behind, which is why order time in force belongs in this decision.
Where the high-water mark is tracked
At most retail brokers the trailing stop does not live at the exchange, and the exchange has no concept of your high-water mark. The broker holds the order, watches the price feed, lifts the trigger as new highs print, and sends a live order only once the trigger is reached. Two consequences follow, both broker-neutral:
- The trigger updates on the prices your broker observes for that purpose. A high printed in a session the broker does not track for the trail leaves the trigger where it was.
- Nothing is queued in advance. Queue position starts when the order is actually sent, which is after the trigger, and on a fast move that is well behind a limit order already resting in the book.
Overnight and extended sessions
Two questions hide in one. First, does the trail keep ratcheting outside regular hours? Common retail behaviour tracks the high-water mark on regular-session prices only, so an extended-hours spike does not lift the trigger. Second, can the order trigger and fill outside regular hours? A trailing stop that reaches its trigger while the market is shut has nowhere to send a market order, so it goes in at the next open, which on a gap morning is the far-below-trigger fill described above. The move happens while the trail is not watching, and both orders meet the gap with the trigger sitting where it was at the prior close. Contract-level quirks for options sit in stop orders on options.
Fill certainty or price certainty
The choice reduces to which failure you would rather own.
- A trailing stop accepts whatever price exists at the trigger. The exit happens, and the price is unknown: a few cents of slippage on an orderly decline, most of the gap on a gap morning.
- A trailing stop-limit fixes the worst price you will accept and accepts that the exit may not happen, leaving the position open while the market moves away.
Both behave identically until the trigger. The whole difference appears on the days the market moves fastest.
FAQ
Is a trailing stop-limit safer than a trailing stop?
Neither is safer in general. They fail in opposite directions: a trailing stop can fill far under its trigger, and a trailing stop-limit can fail to fill and leave the position open. On the deepest gap in the panel above, the entire session traded below where a limit a short distance under the trigger would have rested.
Does a trailing stop move down when the price falls?
No. The trigger moves one way, up for a long position's sell stop. It tracks the highest price seen while the order is live and holds the trail distance under that high-water mark. A falling price leaves the trigger exactly where it was.
Is a percent trail the same as a dollar trail?
Same mechanism, different measure. A percent trail keeps a constant proportional distance from the high-water mark, while a dollar trail keeps a constant absolute distance that narrows in percentage terms as the price rises.
Does a trailing stop work overnight or in extended hours?
Usually the trail tracks regular-session prices and the released order is routed while the market is open. A move that happens while the market is shut is met at the next open, with the trigger at the level it held the previous session. The exact sessions a trail watches vary by broker and are stated in the order's terms.
What limit offset does a trailing stop-limit use?
The offset is set when the order is placed, and it defines the worst price the order will accept. A wide offset behaves more like a plain trailing stop, filling more often and further from the trigger. A narrow offset defends the price and raises the chance of no fill at all.
Every panel here ships with the SQL underneath it. Open one to see how the gaps and the trail levels were counted, or ask the same question in plain English on the Strasmore terminal.