Strasmore Research
Learn Matt ConnorBy Matt Connor · Updated 2026-09-14 · data as of September 14, 2026 · refreshed weekly

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.

QueryHighest relative volume this week: trailing 5 sessions vs. the prior 40, for names trading $500M+ in the week
tickerrvol_weekrecent_adv_mbaseline_adv_mweek_dollar_bnweek_pct
TNON26.333.981.291.0657.6
TTAN7.47.4412.25-40.3
BKV6.54.560.70.56-7.3
VTES5.81.420.250.71-0.4
ACVA5.317.053.240.8556.4
COO5.26.751.291.96-23.4
LULU5.112.642.476.320.8
SCMB5.17.951.540.98-1.2
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 8
Run this yourself

Every row, read in order:

  • TNON, 26.3x its own norm, the top of the board: 33.98M shares a day against a baseline of 1.29M, $1.06B traded, and an open-to-close change of 57.6%.
  • TTAN, 7.4x on a 1M-share baseline, with $2.25B of turnover behind it; the week's change was -40.3%.
  • BKV, 6.5x, but on a thin 0.7M baseline and only $0.56B of turnover; change on the week, -7.3%.
  • VTES, 5.8x, 1.42M shares a day versus 0.25M normally; -0.4% open-to-close.
  • ACVA, 5.3x, $0.85B traded, 56.4% on the week.
  • COO, 5.2x on a 1.29M-share baseline, $1.96B traded, -23.4% open-to-close.
  • LULU, 5.1x, 12.64M shares a day, $6.32B; the week's change, 0.8%.
  • SCMB, the eighth and last row, at 5.1x with $0.98B traded and a -1.2% change.

Direction is not part of the ranking, and the two right-hand columns make that concrete: the board's leader ended the week 57.6% from its opening print while the eighth name ended -1.2% 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 1.29M 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:

QueryHow the whole qualifying universe traded this week, bucketed by relative volume
rvol_bucketnamespct_of_universeuniverse_names
10x or more10.11013
5x to 10x70.71013
3x to 5x80.81013
2x to 3x222.21013
1.5x to 2x595.81013
1x to 1.5x31130.71013
below 1x60559.71013
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 ASC
Run this yourself

1013 stocks and ETFs cleared the floor this week. Of those, 1 traded at ten times their own norm or more, 0.1% of the universe. Another 7 landed in the 5x-to-10x bucket and 8 in the 3x-to-5x bucket. The leaderboard above is drawn from that thin top of the table. Below that, 22 names traded at 2x to 3x their own norm (2.2% of the universe) and 59 landed in the 1.5x-to-2x band (5.8%). A further 311 sat at a merely elevated 1x to 1.5x, 30.7% of the qualifying names.

The other end of the table is the part nobody screenshots: 605 names, 59.7% 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.

QueryPersistence check: the eight leaders' daily relative volume across the five sessions
tickerweek_rvoldays_above_2xpeak_day_rvolsessions_since_peak
ACVA5.3122.90
SCMB5.1218.71
TNON26.3270.21
COO5.2313.41
BKV6.5318.81
LULU5.1413.14
TTAN7.4421.92
VTES5.8514.91
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 ASC
Run this yourself

Sorted by persistence, the least persistent name on the board, ACVA, cleared twice its baseline on 1 of the five sessions, peaking at 22.9x. The most persistent, VTES, did it on 5 of five, with a peak of 14.9x. 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, 0 for ACVA, 1 for VTES. 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:

QueryThe board leader, day by day: daily relative volume and open-to-close change (last 15 sessions)
session_datesession_labelrvol_dayday_pctpeak_rvol_day
2026-08-21Aug 210.3-670.2
2026-08-24Aug 240.2-0.570.2
2026-08-25Aug 250.1-10.870.2
2026-08-26Aug 260.1-8.670.2
2026-08-27Aug 270.1-2.870.2
2026-08-28Aug 281.1-970.2
2026-08-31Aug 310.1-1.370.2
2026-09-01Sep 10.11.570.2
2026-09-02Sep 20-2.570.2
2026-09-03Sep 30.1-15.570.2
2026-09-04Sep 40.1070.2
2026-09-08Sep 80.3-6.170.2
2026-09-09Sep 92-29.170.2
2026-09-10Sep 1070.226.770.2
2026-09-11Sep 1159-27.270.2
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 ASC
Run this yourself

Fifteen sessions ago the stock was running 0.3x its baseline, an ordinary, quiet name. The heaviest session in the stretch hit 70.2x. On the most recent session, Sep 11, the tape still ran 59x with an open-to-close change of -27.2%.

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:

  1. A $500M dollar-volume floor for the week. Share counts alone fill a leaderboard with names where a million shares is pocket change.
  2. A baseline above 100,000 shares a day, so the denominator is a real number rather than a rounding artifact.
  3. 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.
  4. 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:

QueryWild multiples the dollar floor removes: highest relative volume among names trading under $500M this week
tickerrvol_weekweek_dollar_mavg_share_pricebaseline_adv_m
GCDT392.7264.90.70.19
BDRX163.7151.91.280.15
FTFT153326.62.770.15
UFG151.359.80.790.1
OLB79.342.90.370.29
ATER6377.60.820.3
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 6
Run this yourself

GCDT traded 392.7x its own norm, yet turned over only $264.9M all week at an average share price of $0.7. Behind it: BDRX at 163.7x on $151.9M (average price $1.28), FTFT at 153x on $326.6M, UFG at 151.3x on $59.8M, OLB at 79.3x on $42.9M, and ATER at 63x on $77.6M. 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 1013 names clearing this page's floor this week, only 1 traded at 10x their own norm or more, and 59.7% 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 57.6% from its opening print and the eighth name finished -1.2%; 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 (ACVA) to 5 of five (VTES), 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 392.7x its norm on $264.9M total, at an average price of $0.7 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.