What Is a Liquidity Sweep in Trading?
A liquidity sweep is price pushing through a prior high or low where stop orders cluster, then reversing. What the tape shows, and base rates for SPY and QQQ.
A liquidity sweep is a move in which price pushes through a prior swing high or low, the level where resting stop orders cluster, and then reverses back through it. Traders who follow "smart money concepts" read that shape as a large player running the stops on purpose. The tape records something more ordinary: a burst of marketable orders at the level, then a close on the other side of it. Below are the mechanics, and a count of how often the simplest version showed up on SPY, QQQ and five large caps from 2021 through 2025.
What is a liquidity sweep?
In the smart-money-concepts (SMC) vocabulary, "liquidity" does not mean how easily a stock trades. It means a pool of orders waiting to fire. Above a recent swing high sit buy stops: exits placed by short sellers to cap a loss, and buy-stop entries from breakout traders. SMC traders call that cluster buy-side liquidity. Below a recent swing low sit sell stops from long holders and short-entry stops from breakdown traders: sell-side liquidity.
A liquidity sweep is price trading through one of those levels, firing the stops behind it, and then reversing. "Liquidity grab", "stop hunt", "stop run" and "raid" all name the same event. On a daily chart the simplest version is a bar whose high exceeds the prior bar's high while its close finishes back below that prior high, or the mirror for lows. That is the definition measured further down.
What happens on the tape during a liquidity sweep?
Three mechanical facts cover nearly everything about a sweep.
First, stop orders do not rest on the exchange order book. A stop is an instruction held at your broker: if the stock trades at this price, send my order. Until that moment nothing about it is visible to anyone else. A Level 2 screen shows resting limit orders and nothing else, so the pool above a high stays invisible right up until it fires. Our stop order versus stop-limit order guide covers the order types themselves.
Second, when the trigger price prints, a stop converts into a marketable order. A plain buy stop becomes a market order and takes whatever is offered: it prints at the ask, or walks up through several asks when it is large relative to the size behind the bid-ask spread. A cluster of stops at one price means a burst of buy prints at the ask in the seconds after the level trades. On the trade tape that is what a sweep looks like: a run of ask-side prints and a jump in volume, often with a briefly wider spread as the nearest offers are consumed. A sell-side sweep is the same picture inverted, with sell stops printing at the bid.
Third, a stop is spent the moment it fills. Much of the buying that carried price through the high was forced buying; once those orders have printed, the next prints depend on whoever is still willing to pay up. A reversal is the common case where nobody is. Nothing in that sequence requires a coordinated seller waiting above the high, though one can be there too, sometimes as an iceberg order showing only a slice of its size.
How often does a liquidity sweep happen?
The word "sweep" carries a sense of the unusual, so it helps to count. The panel below takes every session from 2021 through 2025 for SPY, QQQ, AAPL, MSFT, NVDA, JPM and KO and asks two questions of each day: did the high exceed the prior day's high while the close finished back below it (a high-side sweep), and did the low undercut the prior day's low while the close finished back above it (a low-side sweep)?
| ticker | session_count | high_sweep_count | high_sweep_pct | low_sweep_count | low_sweep_pct |
|---|---|---|---|---|---|
| AAPL | 1255 | 271 | 21.6 | 258 | 20.6 |
| JPM | 1255 | 282 | 22.5 | 259 | 20.6 |
| KO | 1255 | 288 | 22.9 | 302 | 24.1 |
| MSFT | 1255 | 266 | 21.2 | 267 | 21.3 |
| NVDA | 1255 | 251 | 20 | 256 | 20.4 |
| QQQ | 1255 | 246 | 19.6 | 248 | 19.8 |
| SPY | 1255 | 269 | 21.4 | 236 | 18.8 |
The exact SQL behind every number
SELECT
ticker,
count() AS session_count,
countIf(hi > prior_hi AND cl < prior_hi) AS high_sweep_count,
round(100.0 * countIf(hi > prior_hi AND cl < prior_hi) / count(), 1) AS high_sweep_pct,
countIf(lo < prior_lo AND cl > prior_lo) AS low_sweep_count,
round(100.0 * countIf(lo < prior_lo AND cl > prior_lo) / count(), 1) AS low_sweep_pct
FROM
(
SELECT
ticker,
date,
hi,
lo,
cl,
lagInFrame(hi) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prior_hi,
lagInFrame(lo) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prior_lo
FROM
(
SELECT
ticker,
date,
argMax(high, _ingest_time) AS hi,
argMax(low, _ingest_time) AS lo,
argMax(close, _ingest_time) AS cl
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('SPY', 'QQQ', 'AAPL', 'MSFT', 'NVDA', 'JPM', 'KO')
AND date >= '2020-12-31'
AND date < '2026-01-01'
GROUP BY ticker, date
)
)
WHERE date >= '2021-01-01'
AND prior_hi > 0
GROUP BY ticker
ORDER BY tickerOver those five years SPY printed a high-side sweep on 269 of 1255 sessions, 21.4% of the time, and a low-side sweep on 18.8% of sessions. QQQ measured 19.6% and 19.8%. Among the single stocks, AAPL came in at 21.6% and 20.6%, NVDA at 20% and 20.4%, and KO, the consumer staple on the list, at 22.9% and 24.1%. A sweep-shaped day, by the simplest definition, is a regular feature of the calendar for an index fund and a soft-drink company alike.
Is the rate a feature of one kind of market? The next panel splits SPY's count by year.
| year | high_sweep_pct | low_sweep_pct |
|---|---|---|
| 2021 | 24.6 | 16.3 |
| 2022 | 17.1 | 20.3 |
| 2023 | 19.2 | 21.6 |
| 2024 | 23.4 | 17.1 |
| 2025 | 22.8 | 18.8 |
The exact SQL behind every number
SELECT
toYear(date) AS year,
round(100.0 * countIf(hi > prior_hi AND cl < prior_hi) / count(), 1) AS high_sweep_pct,
round(100.0 * countIf(lo < prior_lo AND cl > prior_lo) / count(), 1) AS low_sweep_pct
FROM
(
SELECT
date,
hi,
lo,
cl,
lagInFrame(hi) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prior_hi,
lagInFrame(lo) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prior_lo
FROM
(
SELECT
date,
argMax(high, _ingest_time) AS hi,
argMax(low, _ingest_time) AS lo,
argMax(close, _ingest_time) AS cl
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2020-12-31'
AND date < '2026-01-01'
GROUP BY date
)
)
WHERE date >= '2021-01-01'
AND prior_hi > 0
GROUP BY year
ORDER BY yearSPY's high-side rate measured 24.6% in 2021 and 22.8% in 2025, with the low-side rate at 16.3% and 18.8% in the same two years. A trending year and a choppy one sit on the same chart at the same scale; the definition does not care which regime it is in.
What a sweep day looks like on SPY
Base rates describe the population. One day shows the tape. The panel below pulls the ten SPY sessions of 2025 with the widest push above the prior day's high that still closed below it, ranked by how far the high overshot the level.
| session_date | session_label | prior_day_high | session_high | session_close | poke_above_pct | close_below_pct |
|---|---|---|---|---|---|---|
| 2025-11-20 | November 20, 2025 | 667.34 | 675.56 | 652.53 | 1.23 | 2.22 |
| 2025-10-15 | October 15, 2025 | 665.83 | 670.23 | 665.17 | 0.66 | 0.1 |
| 2025-08-07 | August 7, 2025 | 633.44 | 636.98 | 632.25 | 0.56 | 0.19 |
| 2025-01-31 | January 31, 2025 | 606.6 | 609.96 | 601.82 | 0.55 | 0.79 |
| 2025-09-05 | September 5, 2025 | 649.15 | 652.21 | 647.24 | 0.47 | 0.29 |
| 2025-04-28 | April 28, 2025 | 551.05 | 553.55 | 550.85 | 0.45 | 0.04 |
| 2025-03-03 | March 3, 2025 | 594.72 | 597.34 | 583.77 | 0.44 | 1.84 |
| 2025-07-15 | July 15, 2025 | 625.16 | 627.86 | 622.14 | 0.43 | 0.48 |
| 2025-04-08 | April 8, 2025 | 523.17 | 524.98 | 496.48 | 0.35 | 5.1 |
| 2025-07-31 | July 31, 2025 | 637.68 | 639.85 | 632.08 | 0.34 | 0.88 |
The exact SQL behind every number
SELECT
toString(toDate(date)) AS session_date,
concat(monthName(date), ' ', toString(toDayOfMonth(date)), ', ', toString(toYear(date))) AS session_label,
round(toFloat64(prior_hi), 2) AS prior_day_high,
round(toFloat64(hi), 2) AS session_high,
round(toFloat64(cl), 2) AS session_close,
round(100.0 * (toFloat64(hi) - toFloat64(prior_hi)) / toFloat64(prior_hi), 2) AS poke_above_pct,
round(100.0 * (toFloat64(prior_hi) - toFloat64(cl)) / toFloat64(prior_hi), 2) AS close_below_pct
FROM
(
SELECT
date,
hi,
cl,
lagInFrame(hi) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prior_hi
FROM
(
SELECT
date,
argMax(high, _ingest_time) AS hi,
argMax(close, _ingest_time) AS cl
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2024-12-31'
AND date < '2026-01-01'
GROUP BY date
)
)
WHERE date >= '2025-01-01'
AND prior_hi > 0
AND hi > prior_hi
AND cl < prior_hi
ORDER BY (toFloat64(hi) - toFloat64(prior_hi)) / toFloat64(prior_hi) DESC, date DESC
LIMIT 10The widest came on November 20, 2025. SPY traded up to $675.56 against a prior-day high of $667.34, 1.23% above the level, and closed at $652.53, 2.22% below the high it had crossed. The last entry on the list, July 31, 2025, overshot by 0.34%. The next panel opens up that widest day in fifteen-minute slices of the regular session.
| et_time | slice_high | slice_low | volume_millions |
|---|---|---|---|
| 09:30 | 674.15 | 672.47 | 8.05 |
| 09:45 | 675.02 | 672.96 | 4.51 |
| 10:00 | 675.41 | 672.79 | 4.18 |
| 10:15 | 675.02 | 672.82 | 3.44 |
| 10:30 | 675.56 | 674.31 | 2.48 |
| 10:45 | 675.32 | 672.74 | 3.63 |
| 11:00 | 672.82 | 669.85 | 4.59 |
| 11:15 | 669.97 | 667.42 | 7.76 |
| 11:30 | 668.17 | 664.13 | 7.29 |
| 11:45 | 665.79 | 659.39 | 9.6 |
| 12:00 | 662.38 | 658.03 | 9.44 |
| 12:15 | 659.48 | 656.6 | 9.03 |
| 12:30 | 659.54 | 655.45 | 6.84 |
| 12:45 | 657.88 | 655.49 | 5.41 |
| 13:00 | 661.85 | 656.72 | 6.48 |
| 13:15 | 661.97 | 658.73 | 4.31 |
| 13:30 | 660 | 656.24 | 3.38 |
| 13:45 | 656.4 | 654.12 | 4.63 |
| 14:00 | 655.85 | 653.86 | 5.14 |
| 14:15 | 657.54 | 654.85 | 2.81 |
The exact SQL behind every number
SELECT
formatDateTime(toStartOfFifteenMinutes(toTimeZone(window_start, 'America/New_York')), '%H:%i') AS et_time,
round(toFloat64(max(high)), 2) AS slice_high,
round(toFloat64(min(low)), 2) AS slice_low,
round(toFloat64(sum(volume)) / 1e6, 2) AS volume_millions
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= '2025-01-01'
AND window_start < '2026-01-02'
AND toDate(toTimeZone(window_start, 'America/New_York')) =
(
SELECT toDate(date)
FROM
(
SELECT
date,
hi,
cl,
lagInFrame(hi) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prior_hi
FROM
(
SELECT
date,
argMax(high, _ingest_time) AS hi,
argMax(close, _ingest_time) AS cl
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2024-12-31'
AND date < '2026-01-01'
GROUP BY date
)
)
WHERE date >= '2025-01-01'
AND prior_hi > 0
AND hi > prior_hi
AND cl < prior_hi
ORDER BY (toFloat64(hi) - toFloat64(prior_hi)) / toFloat64(prior_hi) DESC, date DESC
LIMIT 1
)
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) >= 570
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) < 960
GROUP BY et_time
ORDER BY et_timeFollow the high column to its peak and read the volume beside it: that slice is where the stops above the prior high fired. For scale, the opening slice at 09:30 carried 8.05 million shares and the final slice at 15:45 carried 12.88 million, closing auction included. The panel below isolates the slice that printed the high and sets it beside the session's median and busiest slices.
| label | volume_millions |
|---|---|
| Fifteen minutes that printed the session high | 2.48 |
| Median fifteen-minute slice of the session | 4.63 |
| Busiest fifteen-minute slice of the session | 12.88 |
The exact SQL behind every number
SELECT
tupleElement(entry, 1) AS label,
tupleElement(entry, 2) AS volume_millions
FROM
(
SELECT
arrayJoin([
('Fifteen minutes that printed the session high', peak_slice),
('Median fifteen-minute slice of the session', median_slice),
('Busiest fifteen-minute slice of the session', busiest_slice)
]) AS entry
FROM
(
SELECT
round(argMax(volume_mm, (slice_high, slice_start)), 2) AS peak_slice,
round(quantileExact(0.5)(volume_mm), 2) AS median_slice,
round(max(volume_mm), 2) AS busiest_slice
FROM
(
SELECT
toStartOfFifteenMinutes(toTimeZone(window_start, 'America/New_York')) AS slice_start,
toFloat64(max(high)) AS slice_high,
toFloat64(sum(volume)) / 1e6 AS volume_mm
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= '2025-01-01'
AND window_start < '2026-01-02'
AND toDate(toTimeZone(window_start, 'America/New_York')) =
(
SELECT toDate(date)
FROM
(
SELECT
date,
hi,
cl,
lagInFrame(hi) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prior_hi
FROM
(
SELECT
date,
argMax(high, _ingest_time) AS hi,
argMax(close, _ingest_time) AS cl
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2024-12-31'
AND date < '2026-01-01'
GROUP BY date
)
)
WHERE date >= '2025-01-01'
AND prior_hi > 0
AND hi > prior_hi
AND cl < prior_hi
ORDER BY (toFloat64(hi) - toFloat64(prior_hi)) / toFloat64(prior_hi) DESC, date DESC
LIMIT 1
)
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) >= 570
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) < 960
GROUP BY slice_start
)
)
)The fifteen minutes that printed the high carried 2.48 million SPY shares, against 4.63 million for the median slice of that session and 12.88 million for the busiest. One caveat: if the high printed in the opening or closing slice, part of that volume is the auction itself rather than stops. That is why a sweep is read on the tape rather than from the bar.
Is a liquidity sweep evidence of manipulation?
The tape cannot show that, and the base rates argue against needing it. A sweep needs two ordinary ingredients: enough traders placed stops just beyond a visible level, and enough marketable interest arrived to trade through it. Stops cluster just past swing points for a plain reason: that is where the textbooks say to put them, and everyone is looking at the same chart. The burst that follows is the stops themselves converting into market orders. It does not need a "smart money" counterparty, although a large seller resting at the level would produce the same reversal.
What the tape records is a sequence: the level trades, prints cluster at the ask, volume jumps, and the next bids fail to hold. It does not record intent. An event that appears on 21.4% of SPY sessions on one side alone describes how prices behave around visible reference points rather than anyone's fingerprint. Do stock gaps get filled gives the same base-rate treatment to another piece of chart folklore.
Other things "liquidity sweep" can mean
Search autocomplete attaches the phrase to unrelated ideas, so a short disambiguation. In decentralized finance, a "liquidity pool sweep" is the withdrawal or draining of tokens from an automated-market-maker pool, a blockchain event with no stop orders involved. At a brokerage, a "cash sweep" is the nightly transfer of idle cash into a money-market fund or bank deposit. In accounting, liquidity ratios such as the current ratio and quick ratio measure whether a company's short-term assets cover its short-term liabilities. None of them describes the chart pattern above.
FAQ
What is buy-side liquidity and sell-side liquidity?
In smart-money-concepts language, buy-side liquidity is the pool of buy stop orders resting above a recent swing high, placed by short sellers exiting and breakout traders entering. Sell-side liquidity is the pool of sell stops below a recent swing low. Neither pool is visible on an order book until the stops fire.
Is a liquidity grab the same as a liquidity sweep?
Yes. Liquidity grab, liquidity sweep, stop hunt, stop run and raid all describe price trading through a level where stops cluster and then reversing. The terms differ by community, and what prints on the tape is the same.
Can you see stop orders on Level 2?
No. Level 2 shows resting limit orders at each price. A stop order is held at the broker until its trigger price prints and only then becomes a live order, so the cluster of stops above a high never appears in the book before the sweep.
How often does a liquidity sweep happen on SPY?
By the simplest daily definition, a session whose high exceeds the prior day's high while its close finishes back below it, SPY did this on 21.4% of sessions from 2021 through 2025, and the mirror pattern on lows on 18.8%. The panel above lists AAPL, MSFT, NVDA, JPM and KO alongside.
What happens after a liquidity sweep?
The definition already contains the reversal: the close finishes back on the original side of the level. Beyond that close the data on this page makes no claim, and a sweep is not by itself a forecast of the next session.
Every panel on this page carries the exact SQL beneath it, so expand any one to see how the count was made. To run the same base rate on another ticker or window, ask for it in plain English on the Strasmore terminal.