Unusual Volume Stocks This Week, Measured
Unusual volume stocks this week, ranked: trailing-week turnover vs. each name's prior 40 sessions, with weekly returns, rarity context and persistence.
Unusual volume means a stock trading far above its own normal, not the market's. A megacap doing 40 million shares is a Tuesday; a small-cap doing it is an event. This page ranks the unusual volume stocks of the week just ended: each name's trailing five-session average volume divided by its own average over the prior forty sessions, with a dollar floor so every row is a stock a person could actually trade. It refreshes weekly, and the "data as of" stamp is the window. The measurement itself, relative volume, has its own full guide.
This week's unusual-volume leaders
Three columns do the work. The multiple says how far above its own normal a stock traded. The baseline says what normal was, and a huge multiple off a starving baseline is a smaller event than a modest one off a busy tape. The dollars say whether the activity was economically real. The last column, the week's open-to-close change, is the one most volume screens leave out.
| ticker | rvol_week | recent_adv_m | baseline_adv_m | week_dollar_bn | week_pct |
|---|---|---|---|---|---|
| PFSA | 8.9 | 8.33 | 0.94 | 0.6 | -50.2 |
| MRNA | 6.1 | 33.37 | 5.43 | 24.42 | 120.6 |
| IPST | 5 | 6.56 | 1.31 | 0.53 | 12.9 |
| AMLX | 3.6 | 5.29 | 1.49 | 0.89 | 29.3 |
| UGI | 3.2 | 3.22 | 1 | 0.63 | 7.8 |
| KLAR | 2.7 | 9.41 | 3.5 | 0.71 | -9.6 |
| SAN | 2.5 | 24.22 | 9.81 | 1.73 | 1.2 |
| IEUR | 2.2 | 1.69 | 0.76 | 0.66 | 0.8 |
The exact SQL behind every number
WITH sess AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
sum(toFloat64(volume)) AS vol,
sum(toFloat64(close) * toFloat64(volume)) AS dollars,
argMin(toFloat64(open), toTimeZone(window_start, 'America/New_York')) AS day_open,
argMax(toFloat64(close), toTimeZone(window_start, 'America/New_York')) AS day_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= now() - INTERVAL 70 DAY
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
AND ticker NOT IN ('SPCX')
GROUP BY ticker, d
),
cal AS (
SELECT d, row_number() OVER (ORDER BY d DESC) AS rn
FROM (SELECT DISTINCT d FROM sess)
),
per_name AS (
SELECT s.ticker AS ticker,
avgIf(s.vol, c.rn <= 5) AS adv_recent,
avgIf(s.vol, c.rn BETWEEN 6 AND 45) AS adv_base,
sumIf(s.dollars, c.rn <= 5) AS dollar_recent,
argMaxIf(s.day_open, c.rn, c.rn <= 5) AS week_open,
argMinIf(s.day_close, c.rn, c.rn <= 5) AS week_close,
countIf(c.rn <= 5) AS recent_sessions,
countIf(c.rn BETWEEN 6 AND 45) AS base_sessions
FROM sess s INNER JOIN cal c ON s.d = c.d
GROUP BY s.ticker
HAVING adv_base > 100000 AND dollar_recent >= 500000000 AND recent_sessions = 5 AND base_sessions >= 35
)
SELECT ticker,
round(adv_recent / adv_base, 1) AS rvol_week,
round(adv_recent / 1e6, 2) AS recent_adv_m,
round(adv_base / 1e6, 2) AS baseline_adv_m,
round(dollar_recent / 1e9, 2) AS week_dollar_bn,
round(100.0 * (week_close / week_open - 1), 1) AS week_pct
FROM per_name
ORDER BY rvol_week DESC, ticker ASC
LIMIT 8Every row, read in order:
- PFSA, 8.9x its own norm, the top of the board: 8.33M shares a day against a baseline of 0.94M, $0.6B traded, and an open-to-close change of -50.2%.
- MRNA, 6.1x on a 5.43M-share baseline, with $24.42B of turnover behind it; the week's change was 120.6%.
- IPST, 5x, but on a thin 1.31M baseline and only $0.53B of turnover; change on the week, 12.9%.
- AMLX, 3.6x, 5.29M shares a day versus 1.49M normally; 29.3% open-to-close.
- UGI, 3.2x, $0.63B traded, 7.8% on the week.
- KLAR, 2.7x on a 3.5M-share baseline, $0.71B traded, -9.6% open-to-close.
- SAN, 2.5x, 24.22M shares a day, $1.73B; the week's change, 1.2%.
- IEUR, the eighth and last row, at 2.2x with $0.66B traded and a 0.8% change.
Direction is not part of the ranking, and the two right-hand columns make that concrete: the board's leader ended the week -50.2% from its opening print while the eighth name ended 0.8% from its own, one screen, opposite experiences. Heavy tape marks the sessions when a stock's float is genuinely being tested; it says nothing about which side of that test won.
How the multiple is calculated
Take a stock that averaged 200,000 shares a day across the prior forty sessions. Over the past week it trades 1,000,000, then 1,400,000, then 900,000, then 1,100,000, then 600,000 shares, a five-session average of 1,000,000. Divide: 1,000,000 ÷ 200,000 = 5.0x. Give the same stock a two-million-share baseline instead and that identical week reads 0.5x. The numerator is this week; the denominator is who the stock normally is. (The denominator itself is just average daily volume, measured over forty sessions rather than the usual twenty.)
Why forty sessions? It runs about two calendar months, long enough that one prior spike cannot dominate the denominator, short enough to still describe the stock as it trades today. Why five for the numerator? A full week, so a single halted session or one-off block does not own the reading.
The arithmetic carries an honest warning: the thinner the baseline, the cheaper the multiple. This week's leader carries a baseline of just 0.94M shares a day, at that size, one crowded session drags the whole weekly average up with it, which is exactly why the board demands a six-figure baseline and a $500M week before a name can appear at all.
How rare is a week like this?
A multiple only means something against the distribution it came from. Same universe, same window, every qualifying name bucketed by its multiple:
| rvol_bucket | names | pct_of_universe | universe_names |
|---|---|---|---|
| 10x or more | 0 | 0 | 508 |
| 5x to 10x | 2 | 0.4 | 508 |
| 3x to 5x | 3 | 0.6 | 508 |
| 2x to 3x | 6 | 1.2 | 508 |
| 1.5x to 2x | 2 | 0.4 | 508 |
| 1x to 1.5x | 10 | 2 | 508 |
| below 1x | 485 | 95.5 | 508 |
The exact SQL behind every number
WITH sess AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
sum(toFloat64(volume)) AS vol,
sum(toFloat64(close) * toFloat64(volume)) AS dollars
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= now() - INTERVAL 70 DAY
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
AND ticker NOT IN ('SPCX')
GROUP BY ticker, d
),
cal AS (
SELECT d, row_number() OVER (ORDER BY d DESC) AS rn
FROM (SELECT DISTINCT d FROM sess)
),
per_name AS (
SELECT s.ticker AS ticker,
avgIf(s.vol, c.rn <= 5) AS adv_recent,
avgIf(s.vol, c.rn BETWEEN 6 AND 45) AS adv_base,
sumIf(s.dollars, c.rn <= 5) AS dollar_recent,
countIf(c.rn <= 5) AS recent_sessions,
countIf(c.rn BETWEEN 6 AND 45) AS base_sessions
FROM sess s INNER JOIN cal c ON s.d = c.d
GROUP BY s.ticker
HAVING adv_base > 100000 AND dollar_recent >= 500000000 AND recent_sessions = 5 AND base_sessions >= 35
),
scored AS (
SELECT ticker,
multiIf(adv_recent / adv_base >= 10, 1,
adv_recent / adv_base >= 5, 2,
adv_recent / adv_base >= 3, 3,
adv_recent / adv_base >= 2, 4,
adv_recent / adv_base >= 1.5, 5,
adv_recent / adv_base >= 1, 6, 7) AS bucket_key
FROM per_name
),
buckets AS (
SELECT arrayJoin([(1, '10x or more'), (2, '5x to 10x'), (3, '3x to 5x'), (4, '2x to 3x'),
(5, '1.5x to 2x'), (6, '1x to 1.5x'), (7, 'below 1x')]) AS bk
)
SELECT bk.2 AS rvol_bucket,
countIf(scored.bucket_key = bk.1) AS names,
round(100.0 * countIf(scored.bucket_key = bk.1) / count(), 1) AS pct_of_universe,
count() AS universe_names
FROM scored CROSS JOIN buckets
GROUP BY bk
ORDER BY bk.1 ASC508 stocks and ETFs cleared the floor this week. Of those, 0 traded at ten times their own norm or more, 0% of the universe. Another 2 landed in the 5x-to-10x bucket and 3 in the 3x-to-5x bucket. The leaderboard above is drawn from that thin top of the table. Below that, 6 names traded at 2x to 3x their own norm (1.2% of the universe) and 2 landed in the 1.5x-to-2x band (0.4%). A further 10 sat at a merely elevated 1x to 1.5x, 2% of the qualifying names.
The other end of the table is the part nobody screenshots: 485 names, 95.5% of the universe, traded below their own forty-session average this week. That is the ordinary state of the market, and it is what makes the top of the board a genuine outlier rather than a rounding error.
Does unusual volume stick around?
The folk claim is that unusual volume persists for days, so a name near the top of a board like this has usually already done its moving. That is testable. For each of the eight leaders: how many of the five sessions ran at twice the baseline or better, how big the single heaviest session was, and how many sessions separated that heaviest session from the week's last.
| ticker | week_rvol | days_above_2x | peak_day_rvol | sessions_since_peak |
|---|---|---|---|---|
| IEUR | 2.2 | 1 | 10.2 | 3 |
| IPST | 5 | 1 | 23.6 | 4 |
| MRNA | 6.1 | 1 | 29.6 | 3 |
| PFSA | 8.9 | 1 | 42.9 | 4 |
| SAN | 2.5 | 2 | 6.8 | 3 |
| KLAR | 2.7 | 2 | 8.5 | 4 |
| UGI | 3.2 | 2 | 12 | 4 |
| AMLX | 3.6 | 2 | 12.7 | 4 |
The exact SQL behind every number
WITH sess AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
sum(toFloat64(volume)) AS vol,
sum(toFloat64(close) * toFloat64(volume)) AS dollars
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= now() - INTERVAL 70 DAY
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
AND ticker NOT IN ('SPCX')
GROUP BY ticker, d
),
cal AS (
SELECT d, row_number() OVER (ORDER BY d DESC) AS rn
FROM (SELECT DISTINCT d FROM sess)
),
per_name AS (
SELECT s.ticker AS ticker,
avgIf(s.vol, c.rn <= 5) AS adv_recent,
avgIf(s.vol, c.rn BETWEEN 6 AND 45) AS adv_base,
sumIf(s.dollars, c.rn <= 5) AS dollar_recent,
countIf(c.rn <= 5) AS recent_sessions,
countIf(c.rn BETWEEN 6 AND 45) AS base_sessions
FROM sess s INNER JOIN cal c ON s.d = c.d
GROUP BY s.ticker
HAVING adv_base > 100000 AND dollar_recent >= 500000000 AND recent_sessions = 5 AND base_sessions >= 35
),
leaders AS (
SELECT ticker, adv_recent / adv_base AS rvol_week, adv_base
FROM per_name
ORDER BY rvol_week DESC, ticker ASC
LIMIT 8
),
daily AS (
SELECT l.ticker AS ticker,
l.rvol_week AS rvol_week,
c.rn AS rn,
s.vol / l.adv_base AS rvol_day
FROM sess s
INNER JOIN cal c ON s.d = c.d
INNER JOIN leaders l ON s.ticker = l.ticker
WHERE c.rn <= 5
)
SELECT ticker,
round(max(rvol_week), 1) AS week_rvol,
countIf(rvol_day >= 2) AS days_above_2x,
round(max(rvol_day), 1) AS peak_day_rvol,
argMax(rn, (rvol_day, -rn)) - 1 AS sessions_since_peak
FROM daily
GROUP BY ticker
ORDER BY days_above_2x ASC, peak_day_rvol ASC, ticker ASCSorted by persistence, the least persistent name on the board, IEUR, cleared twice its baseline on 1 of the five sessions, peaking at 10.2x. The most persistent, AMLX, did it on 2 of five, with a peak of 12.7x. These are multi-session events, not single prints, which is the mechanical reason a weekly board and a daily board tend to name the same stocks.
The last column is the timing one: sessions between the heaviest day and the week's final session, 3 for IEUR, 4 for AMLX. Where that gap is above zero, the loudest tape had already printed before the week closed. The board describes the week that ended; it does not forecast the one that starts.
The leader's fifteen sessions, day by day
The weekly average hides the shape. Here is the current leader's daily relative volume, each session's shares against that same forty-session baseline, alongside each session's open-to-close change, over the last fifteen sessions:
| session_date | session_label | rvol_day | day_pct | peak_rvol_day |
|---|---|---|---|---|
| 2026-08-04 | Aug 4 | 0.1 | 0.3 | 42.9 |
| 2026-08-05 | Aug 5 | 0.1 | -2.3 | 42.9 |
| 2026-08-06 | Aug 6 | 0.1 | 0.1 | 42.9 |
| 2026-08-07 | Aug 7 | 0 | 0.6 | 42.9 |
| 2026-08-10 | Aug 10 | 0 | -1.7 | 42.9 |
| 2026-08-11 | Aug 11 | 0 | 3.2 | 42.9 |
| 2026-08-12 | Aug 12 | 0 | -0.5 | 42.9 |
| 2026-08-13 | Aug 13 | 0.2 | 11.8 | 42.9 |
| 2026-08-14 | Aug 14 | 0.1 | -3.3 | 42.9 |
| 2026-08-17 | Aug 17 | 1.7 | 6.4 | 42.9 |
| 2026-08-18 | Aug 18 | 42.9 | 204 | 42.9 |
| 2026-08-19 | Aug 19 | 1.1 | -18 | 42.9 |
| 2026-08-20 | Aug 20 | 0.4 | -5.9 | 42.9 |
| 2026-08-21 | Aug 21 | 0 | 0.1 | 42.9 |
| 2026-08-24 | Aug 24 | 0.1 | -5.1 | 42.9 |
The exact SQL behind every number
WITH sess AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
sum(toFloat64(volume)) AS vol,
sum(toFloat64(close) * toFloat64(volume)) AS dollars,
argMin(toFloat64(open), toTimeZone(window_start, 'America/New_York')) AS day_open,
argMax(toFloat64(close), toTimeZone(window_start, 'America/New_York')) AS day_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= now() - INTERVAL 70 DAY
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
AND ticker NOT IN ('SPCX')
GROUP BY ticker, d
),
cal AS (
SELECT d, row_number() OVER (ORDER BY d DESC) AS rn
FROM (SELECT DISTINCT d FROM sess)
),
per_name AS (
SELECT s.ticker AS ticker,
avgIf(s.vol, c.rn <= 5) AS adv_recent,
avgIf(s.vol, c.rn BETWEEN 6 AND 45) AS adv_base,
sumIf(s.dollars, c.rn <= 5) AS dollar_recent,
countIf(c.rn <= 5) AS recent_sessions,
countIf(c.rn BETWEEN 6 AND 45) AS base_sessions
FROM sess s INNER JOIN cal c ON s.d = c.d
GROUP BY s.ticker
HAVING adv_base > 100000 AND dollar_recent >= 500000000 AND recent_sessions = 5 AND base_sessions >= 35
),
leader AS (
SELECT ticker, adv_base
FROM per_name
ORDER BY adv_recent / adv_base DESC, ticker ASC
LIMIT 1
),
path AS (
SELECT formatDateTime(s.d, '%Y-%m-%d') AS session_date,
formatDateTime(s.d, '%b %e') AS session_label,
s.vol / l.adv_base AS rvol_day,
100.0 * (s.day_close / s.day_open - 1) AS day_pct
FROM sess s
INNER JOIN cal c ON s.d = c.d
INNER JOIN leader l ON s.ticker = l.ticker
WHERE c.rn <= 15
)
SELECT session_date,
session_label,
round(rvol_day, 1) AS rvol_day,
round(day_pct, 1) AS day_pct,
round(max(rvol_day) OVER (), 1) AS peak_rvol_day
FROM path
ORDER BY session_date ASCFifteen sessions ago the stock was running 0.1x its baseline, an ordinary, quiet name. The heaviest session in the stretch hit 42.9x. On the most recent session, Aug 24, the tape still ran 0.1x with an open-to-close change of -5.1%.
Note what the chart does not do: decay in an orderly line. Elevated volume comes in clusters, and the sessions after a peak can re-accelerate rather than fade, one reason "volume is drying up" is a claim to check against the daily series instead of assuming. The same daily series is where an intraday pace measure would start, the one built from scratch in the relative volume guide and used by VWAP.
What the screen filters out
Four rules keep the board honest, and each one throws away something a reader might want to see:
- A $500M dollar-volume floor for the week. Share counts alone fill a leaderboard with names where a million shares is pocket change.
- A baseline above 100,000 shares a day, so the denominator is a real number rather than a rounding artifact.
- At least 35 of the prior 40 sessions traded, which excludes brand-new listings, a fresh IPO has no meaningful "normal" to divide by, and would otherwise own this board for weeks.
- One reused symbol excluded: a ticker the exchanges recently reassigned to a new listing, whose vendor history splices two different companies together. Its baseline would be fiction.
Rule 1 is the one that removes the wildest multiples on the tape. Here are the six biggest excluded by it:
| ticker | rvol_week | week_dollar_m | avg_share_price | baseline_adv_m |
|---|---|---|---|---|
| XOS | 65.1 | 238.7 | 4.22 | 0.17 |
| BIAF | 41 | 29.9 | 0.49 | 0.3 |
| CDTG | 40 | 410.2 | 5.34 | 0.38 |
| CAST | 27.3 | 245.6 | 1.7 | 1.06 |
| SLE | 25.4 | 141 | 5.06 | 0.22 |
| DAIC | 16.8 | 98 | 3.62 | 0.32 |
The exact SQL behind every number
WITH sess AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
sum(toFloat64(volume)) AS vol,
sum(toFloat64(close) * toFloat64(volume)) AS dollars
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= now() - INTERVAL 70 DAY
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
AND ticker NOT IN ('SPCX')
GROUP BY ticker, d
),
cal AS (
SELECT d, row_number() OVER (ORDER BY d DESC) AS rn
FROM (SELECT DISTINCT d FROM sess)
),
per_name AS (
SELECT s.ticker AS ticker,
avgIf(s.vol, c.rn <= 5) AS adv_recent,
avgIf(s.vol, c.rn BETWEEN 6 AND 45) AS adv_base,
sumIf(s.dollars, c.rn <= 5) AS dollar_recent,
countIf(c.rn <= 5) AS recent_sessions,
countIf(c.rn BETWEEN 6 AND 45) AS base_sessions
FROM sess s INNER JOIN cal c ON s.d = c.d
GROUP BY s.ticker
HAVING adv_base > 100000 AND recent_sessions = 5 AND base_sessions >= 35
AND dollar_recent > 0 AND dollar_recent < 500000000
)
SELECT ticker,
round(adv_recent / adv_base, 1) AS rvol_week,
round(dollar_recent / 1e6, 1) AS week_dollar_m,
round(dollar_recent / (adv_recent * 5), 2) AS avg_share_price,
round(adv_base / 1e6, 2) AS baseline_adv_m
FROM per_name
ORDER BY rvol_week DESC, ticker ASC
LIMIT 6XOS traded 65.1x its own norm, yet turned over only $238.7M all week at an average share price of $4.22. Behind it: BIAF at 41x on $29.9M (average price $0.49), CDTG at 40x on $410.2M, CAST at 27.3x on $245.6M, SLE at 25.4x on $141M, and DAIC at 16.8x on $98M. Real activity, genuinely unusual for those names, and a category where the multiple flatters a very small amount of money.
Where unusual volume comes from
The recurring producers, so the board reads faster: earnings weeks, the one scheduled source; corporate events, mergers, offerings, index adds and deletes, which arrive with mechanical volume that has nothing to do with opinion; squeeze dynamics, where volume stacks on top of price velocity, the pattern the short squeeze explainer documents; and new listings, which dominate their own tape until the float seasons. Any given week's board is usually a blend, plus one or two genuine mysteries, and the mysteries are the rows worth the extra minute.
Unusual volume FAQ
What counts as unusual volume for a stock?
There is no official threshold, so use the distribution: of the 508 names clearing this page's floor this week, only 0 traded at 10x their own norm or more, and 95.5% actually traded below their own average. Anything above roughly 2x is already in the top few percent of the market on a given week.
Is unusual volume bullish or bearish?
Neither, it is attention, and attention arrives with rallies and collapses alike. This week the board's leader finished the five sessions -50.2% from its opening print and the eighth name finished 0.8%; both qualified on exactly the same measurement.
How long does unusual volume last?
Usually longer than a day. The persistence panel counts each board name's sessions above twice baseline: this week they run from 1 of five (IEUR) to 2 of five (AMLX), and the heaviest session typically lands before the week ends rather than on its final day.
Why does the list use a dollar-volume floor?
A share-count screen without one fills up with cheap tickers where the multiple is huge and the money is not: this week's biggest excluded name traded 65.1x its norm on $238.7M total, at an average price of $4.22 a share. The $500M weekly floor keeps every row on the board economically real.
Does unusual stock volume show up in the options market too?
Often, yes, heavy equity tape and heavy options tape tend to arrive together on the same names, which is why traders watch both. Options activity is measured differently, though: contracts traded is a flow number, while open interest counts positions still standing, and the two answer different questions, see options volume vs. open interest before reading anything into an "unusual options activity" alert.
Every number above is a stored, versioned query, expand the SQL under any panel to see the exact measurement, or run the same screen over any window you like on the Strasmore terminal.