What Is Average Daily Volume (ADV)?
Average daily volume is a stock's typical shares traded per day. It is the denominator inside days to cover, relative volume, and every liquidity screen.
Average daily volume, ADV, is the most-used number nobody bothers to define: a stock's typical shares traded per day, averaged over some trailing window. It is the denominator inside days to cover, the baseline inside relative volume, and the liquidity test inside every screener, which means every one of those numbers inherits ADV's quiet choices: which window, which sessions, shares or dollars. This page defines it properly, walks the arithmetic by hand, and measures each of those choices on real tape.
Average daily volume, measured
Twenty regular-hours sessions, June 11 through July 10, 2026, four familiar names plus a deliberately thin one. Shares, dollars, and (for later) the slice of each name's total volume that trades outside regular hours:
| ticker | adv_shares_m | adv_dollars_bn | extended_hours_pct | sessions |
|---|---|---|---|---|
| SPY | 46.01 | 34.19 | 18.3 | 20 |
| MU | 42.01 | 44.49 | 12.1 | 20 |
| AAPL | 41.47 | 12.24 | 6.9 | 20 |
| KO | 12.4 | 1.01 | 6.6 | 20 |
| CATO | 0.05 | 0 | 0.2 | 20 |
The exact SQL behind every number
WITH per_day AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
sumIf(toFloat64(volume), formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') >= '09:30'
AND formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') < '16:00') AS rth_shares,
sumIf(toFloat64(close) * toFloat64(volume), formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') >= '09:30'
AND formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') < '16:00') AS rth_dollars,
sum(toFloat64(volume)) AS all_shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'AAPL', 'MU', 'KO', 'CATO')
AND window_start >= toDateTime('2026-06-11 00:00:00', 'America/New_York')
AND window_start < toDateTime('2026-07-11 00:00:00', 'America/New_York')
GROUP BY ticker, et_date
)
SELECT ticker,
round(avg(rth_shares) / 1e6, 2) AS adv_shares_m,
round(avg(rth_dollars) / 1e9, 2) AS adv_dollars_bn,
round(100 * (sum(all_shares) - sum(rth_shares)) / sum(all_shares), 1) AS extended_hours_pct,
count() AS sessions
FROM per_day
GROUP BY ticker
ORDER BY adv_shares_m DESCThe table carries this page's whole argument. MU and AAPL trade nearly the same number of shares each day, 42.01M against 41.47M, but the dollar column splits them wide apart: $44.49B against $12.24B a day. Shares measure activity; dollars measure money. The ranking even flips at the top: SPY leads in shares (46.01M across 20 sessions) while MU leads this table in dollars. And at the bottom, CATO trades 0.05 million shares a day, so little money that the billions column shows 0 at this scale. That is the kind of tape where a single institutional order IS the day's volume, and where trading costs live in a different universe.
How to calculate average daily volume
The arithmetic is deliberately boring: add up the daily share volumes over the chosen window, divide by the number of days. One full week of Coca-Cola's regular-hours tape (July 6–10, 2026), with the running total and average computed in the same query:
| session_date | shares_m | five_day_total_m | adv_m | one_pct_of_adv_k |
|---|---|---|---|---|
| 2026-07-06 | 10.7 | 52.8 | 10.6 | 106 |
| 2026-07-07 | 12.1 | 52.8 | 10.6 | 106 |
| 2026-07-08 | 10.7 | 52.8 | 10.6 | 106 |
| 2026-07-09 | 11 | 52.8 | 10.6 | 106 |
| 2026-07-10 | 8.3 | 52.8 | 10.6 | 106 |
The exact SQL behind every number
SELECT session_date,
shares_m,
round(sum(shares_m) OVER (), 1) AS five_day_total_m,
round(avg(shares_m) OVER (), 1) AS adv_m,
round(avg(shares_m) OVER () * 0.01 * 1000, 0) AS one_pct_of_adv_k
FROM (
SELECT formatDateTime(toDate(toTimeZone(window_start, 'America/New_York')), '%Y-%m-%d') AS session_date,
round(sumIf(toFloat64(volume), formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') >= '09:30'
AND formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') < '16:00') / 1e6, 1) AS shares_m
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'KO'
AND window_start >= toDateTime('2026-07-06 00:00:00', 'America/New_York')
AND window_start < toDateTime('2026-07-11 00:00:00', 'America/New_York')
GROUP BY session_date
)
ORDER BY session_dateAdd the five days, 10.7 + 12.1 + 10.7 + 11 + 8.3 million shares, and the total is 52.8M. Divide by five: 10.6M shares, KO's 5-session ADV. A 20-session ADV is the same arithmetic over 20 rows, that is the number in the first table. Notice what the average hides: 2026-07-07 printed 12.1M and 2026-07-10 printed 8.3M, day-to-day swings that ADV smooths into one figure. The last column previews position sizing: one percent of KO's ADV is about 106 thousand shares, the scale at which a single order starts to be a noticeable share of the day's tape.
The window is a choice, and it decides how fast ADV forgets
Twenty sessions is the common convention (a trading month); ten, thirty, sixty-five, and ninety all circulate. The window decides how fast ADV forgets. MU is 2026's live example, a name whose tape re-rated so hard mid-year that its trailing-month ADV and its trailing-quarter ADV spent the spring telling different stories, receipts throughout its June deep-dive. Here is the same stock over the same seven months, measured with both windows at once:
| date | adv_20_session_m | adv_90_session_m |
|---|---|---|
| 2025-12-10 | 21.3 | 19.9 |
| 2025-12-15 | 20.3 | 20.1 |
| 2025-12-18 | 20.7 | 20.2 |
| 2025-12-23 | 20 | 20.7 |
| 2025-12-29 | 20.7 | 20.8 |
| 2026-01-02 | 22.2 | 21.3 |
| 2026-01-07 | 24.5 | 22 |
| 2026-01-12 | 26 | 22.5 |
| 2026-01-15 | 26.2 | 22.5 |
| 2026-01-21 | 26.9 | 23 |
| 2026-01-26 | 28.5 | 23.4 |
| 2026-01-29 | 30.5 | 23.7 |
| 2026-02-03 | 31.9 | 23.9 |
| 2026-02-06 | 32.6 | 24.4 |
| 2026-02-11 | 34.1 | 24.7 |
| 2026-02-17 | 35 | 24.9 |
| 2026-02-20 | 32.5 | 25 |
| 2026-02-25 | 32 | 25.4 |
| 2026-03-02 | 30.2 | 25.4 |
| 2026-03-05 | 28.4 | 25.8 |
The exact SQL behind every number
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
sum(toFloat64(volume)) AS day_shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'MU'
AND window_start >= toDateTime('2025-08-01 00:00:00', 'America/New_York')
AND window_start < toDateTime('2026-07-11 00:00:00', 'America/New_York')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY et_date
),
rolled AS (
SELECT et_date,
avg(day_shares) OVER (ORDER BY et_date ROWS BETWEEN 19 PRECEDING AND CURRENT ROW) AS adv20,
avg(day_shares) OVER (ORDER BY et_date ROWS BETWEEN 89 PRECEDING AND CURRENT ROW) AS adv90,
row_number() OVER (ORDER BY et_date) AS rn,
count() OVER () AS total_rows
FROM daily
)
SELECT formatDateTime(et_date, '%Y-%m-%d') AS date,
round(adv20 / 1e6, 1) AS adv_20_session_m,
round(adv90 / 1e6, 1) AS adv_90_session_m
FROM rolled
WHERE rn > 90 AND (rn % 3 = total_rows % 3)
ORDER BY et_dateOn 2025-12-10 the two windows agreed: 21.3M on the 20-session count, 19.9M on the 90. By 2026-04-14 they had split to 45.6M against 31.9M, two "official" ADVs for one stock on one day, and every screener, days-to-cover figure, or relative-volume reading keyed to one window disagreed with the same tool keyed to the other. By 2026-07-10 the two had converged again (42M vs 41.9M): the re-rated volume level had aged into the long window too. When two sources disagree about a stock's ADV, the window is the first suspect; whether extended-hours volume is included is the second.
What happens to ADV right after a volume shock
The chart above hints at it; here it is measured. Take MU's sharpest volume shock of 2026, the session that most exceeded its own trailing 20-session ADV, and compare the ADV a screener showed going into that day with what it showed a month later:
| event_date | event_day_shares_m | adv_20_before_m | event_vs_prior_adv_x | adv_20_after_m | adv_shift_pct |
|---|---|---|---|---|---|
| 2026-03-19 | 64.7 | 28.7 | 2.3 | 45 | 57 |
The exact SQL behind every number
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
sum(toFloat64(volume)) AS day_shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'MU'
AND window_start >= toDateTime('2025-11-01 00:00:00', 'America/New_York')
AND window_start < toDateTime('2026-07-11 00:00:00', 'America/New_York')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY et_date
),
ranked AS (
SELECT et_date, day_shares,
day_shares / avg(day_shares) OVER (ORDER BY et_date ROWS BETWEEN 20 PRECEDING AND 1 PRECEDING) AS shock_ratio,
row_number() OVER (ORDER BY et_date) AS rn
FROM daily
),
biggest AS (
SELECT et_date, day_shares, shock_ratio
FROM ranked
WHERE rn > 20 AND et_date >= toDate('2026-01-01')
ORDER BY shock_ratio DESC, et_date ASC
LIMIT 1
),
before AS (
SELECT avg(day_shares) AS adv FROM (
SELECT day_shares FROM daily WHERE et_date < (SELECT et_date FROM biggest) ORDER BY et_date DESC LIMIT 20
)
),
after AS (
SELECT avg(day_shares) AS adv FROM (
SELECT day_shares FROM daily WHERE et_date >= (SELECT et_date FROM biggest) ORDER BY et_date ASC LIMIT 20
)
)
SELECT formatDateTime((SELECT et_date FROM biggest), '%Y-%m-%d') AS event_date,
round((SELECT day_shares FROM biggest) / 1e6, 1) AS event_day_shares_m,
round((SELECT adv FROM before) / 1e6, 1) AS adv_20_before_m,
round((SELECT shock_ratio FROM biggest), 1) AS event_vs_prior_adv_x,
round((SELECT adv FROM after) / 1e6, 1) AS adv_20_after_m,
round(100 * ((SELECT adv FROM after) / (SELECT adv FROM before) - 1), 0) AS adv_shift_pctOn 2026-03-19, MU printed 64.7M shares against a prior ADV of 28.7M, 2.3x its own baseline. Over the next 20 sessions, the trailing ADV averaged 45M: a 57% jump in the denominator. Every ADV-derived number moved with it, relative volume readings shrank (the baseline grew) and days to cover shrank (the denominator grew), with zero change required in anyone's actual position. In MU's case the elevated tape persisted, the shock marked a re-rating, not a one-day event, but the mechanics are identical either way: after a heavy stretch, ADV measures the event rather than the stock's habits for exactly one window-length.
What counts as liquid, measured
"Millions of dollars a day" is the usual hand-wave for tradability. Here is the actual distribution, every US-listed symbol with at least 15 of the same 20 sessions, ranked by dollar ADV:
| names | p25_m | median_m | p75_m | p90_m | p99_m | names_above_1m | names_above_10m | names_above_100m | names_above_1bn |
|---|---|---|---|---|---|---|---|---|---|
| 10864 | 0.33 | 2.2 | 20.4 | 113.7 | 1333 | 6515 | 3535 | 1166 | 130 |
The exact SQL behind every number
WITH per_ticker AS (
SELECT ticker, avg(day_dollars) AS adv_dollars
FROM (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
sumIf(toFloat64(close) * toFloat64(volume), formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') >= '09:30'
AND formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') < '16:00') AS day_dollars
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= toDateTime('2026-06-11 00:00:00', 'America/New_York')
AND window_start < toDateTime('2026-07-11 00:00:00', 'America/New_York')
AND match(ticker, '^[A-Z]+$')
GROUP BY ticker, et_date
)
GROUP BY ticker
HAVING count() >= 15
)
SELECT count() AS names,
round(quantileDeterministic(0.25)(adv_dollars, cityHash64(ticker)) / 1e6, 2) AS p25_m,
round(quantileDeterministic(0.50)(adv_dollars, cityHash64(ticker)) / 1e6, 1) AS median_m,
round(quantileDeterministic(0.75)(adv_dollars, cityHash64(ticker)) / 1e6, 1) AS p75_m,
round(quantileDeterministic(0.90)(adv_dollars, cityHash64(ticker)) / 1e6, 1) AS p90_m,
round(quantileDeterministic(0.99)(adv_dollars, cityHash64(ticker)) / 1e6, 0) AS p99_m,
countIf(adv_dollars >= 1e6) AS names_above_1m,
countIf(adv_dollars >= 10e6) AS names_above_10m,
countIf(adv_dollars >= 100e6) AS names_above_100m,
countIf(adv_dollars >= 1e9) AS names_above_1bn
FROM per_tickerAcross 10864 symbols, the median name turns over $2.2M a day, half the US market trades less than that. A quarter of it trades under $0.33M. The 75th percentile sits at $20.4M, the 90th at $113.7M, the 99th at $1333M. Counted against round thresholds: 6515 names clear $1M a day, 3535 clear $10M, 1166 clear $100M, and just 130 clear $1B. The names financial coverage revolves around live almost entirely inside that last group; the median listed stock is a different instrument altogether.
Where ADV silently decides other numbers
- Days to cover = short interest ÷ ADV. A volume spike shrinks the ratio with zero change in the short position, the denominator did it.
- Relative volume = today's pace ÷ ADV. Same number, opposite role: here ADV is the baseline being beaten.
- Liquidity screens ("only names above 1M ADV"), every backtest and screener carries one, and survivorship quietly follows: names enter such screens by having their most dramatic weeks.
- Position sizing, the institutional habit of trading only a few percent of ADV per day is why big funds simply cannot own certain small stocks: weeks of the whole tape's volume would be needed to build or exit a position.
The days-to-cover case is worth seeing with real numbers, since even the "official" figure embeds somebody's ADV choice. FINRA publishes days to cover next to its own volume denominator (every venue, its own reporting window, floored at 1.0, see how that data arrives); recompute the same ratio with this page's 20-session regular-hours ADV and the answer changes:
| ticker | shares_short_m | finra_adv_m | finra_days_to_cover | rth_adv_20_session_m | days_to_cover_recomputed |
|---|---|---|---|---|---|
| KO | 49.6 | 24.1 | 2.06 | 12.4 | 4 |
| MU | 31.7 | 60.3 | 1 | 42 | 0.75 |
The exact SQL behind every number
WITH our_adv AS (
SELECT ticker, avg(day_shares) AS adv
FROM (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
sumIf(toFloat64(volume), formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') >= '09:30'
AND formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:%i') < '16:00') AS day_shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('MU', 'KO')
AND window_start >= toDateTime('2026-06-11 00:00:00', 'America/New_York')
AND window_start < toDateTime('2026-07-11 00:00:00', 'America/New_York')
GROUP BY ticker, et_date
)
GROUP BY ticker
),
si AS (
SELECT ticker,
max(short_interest) AS short_interest,
max(avg_daily_volume) AS finra_adv,
max(days_to_cover) AS finra_dtc
FROM global_markets.stocks_short_interest
WHERE settlement_date = '2026-06-30' AND ticker IN ('MU', 'KO')
GROUP BY ticker
)
SELECT si.ticker AS ticker,
round(si.short_interest / 1e6, 1) AS shares_short_m,
round(si.finra_adv / 1e6, 1) AS finra_adv_m,
round(si.finra_dtc, 2) AS finra_days_to_cover,
round(our_adv.adv / 1e6, 1) AS rth_adv_20_session_m,
round(si.short_interest / our_adv.adv, 2) AS days_to_cover_recomputed
FROM si
INNER JOIN our_adv ON si.ticker = our_adv.ticker
ORDER BY tickerSame short interest, two denominators. For KO, FINRA reports 2.06 days on its 24.1M-share volume figure; against this page's 12.4M regular-hours ADV, the same 49.6M-share short position works out to 4 days, nearly double. For MU, the published number sits at the reported floor of 1; recomputed, it is 0.75 days. Neither figure is wrong, they answer with different denominators. The lesson generalizes: any ratio with ADV underneath is quietly quoting somebody's window and session choices.
Does ADV work for options?
Options traders lean on the same concept with one twist: volume is counted in contracts, and each standard equity contract controls 100 shares. Same 20 sessions, four option tapes, with the contract count converted to share-equivalent exposure:
| underlying | avg_daily_contracts_k | share_equivalent_m | sessions |
|---|---|---|---|
| SPY | 12543.2 | 1254.3 | 20 |
| AAPL | 1265.1 | 126.5 | 20 |
| MU | 804.7 | 80.5 | 20 |
| KO | 64.6 | 6.5 | 20 |
The exact SQL behind every number
WITH daily AS (
SELECT multiIf(ticker LIKE 'O:SPY2%', 'SPY', ticker LIKE 'O:AAPL2%', 'AAPL', ticker LIKE 'O:MU2%', 'MU', 'KO') AS underlying,
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
sum(toFloat64(volume)) AS contracts
FROM global_markets.options_minute_aggs
WHERE (ticker LIKE 'O:SPY2%' OR ticker LIKE 'O:AAPL2%' OR ticker LIKE 'O:MU2%' OR ticker LIKE 'O:KO2%')
AND window_start >= toDateTime('2026-06-11 00:00:00', 'America/New_York')
AND window_start < toDateTime('2026-07-11 00:00:00', 'America/New_York')
GROUP BY underlying, et_date
)
SELECT underlying,
round(avg(contracts) / 1e3, 1) AS avg_daily_contracts_k,
round(avg(contracts) * 100 / 1e6, 1) AS share_equivalent_m,
count() AS sessions
FROM daily
GROUP BY underlying
ORDER BY avg_daily_contracts_k DESCThe scale differences dwarf anything in the stock table. SPY's options tape averaged 12543.2 thousand contracts a day, 1254.3M shares of equivalent exposure, a large multiple of SPY's own 46.01M share ADV. KO runs the other way: 64.6 thousand contracts (6.5M share-equivalent), below its 12.4M share ADV. Options liquidity concentrates in a handful of underlyings, and it thins out further across strikes and expirations, an aggregate figure like this overstates what any single contract trades, so per-contract volume and open interest still need checking before sizing an options order.
Reading ADV like a practitioner
Three habits close the gap between knowing the definition and using it. Pair share ADV with dollar ADV, the first table shows two names nearly tied in shares and far apart in money, and the money column is the one an order actually cares about. Distrust ADV immediately after events, the shock panel put a number on it: one heavy stretch moved the denominator 57% in a month, mechanically deflating relative volume and days to cover until the spike ages out of the window. Check ADV against the calendar, expiration Fridays, rebalance days, and index-change dates inflate everyone's volume at once (witching days most of all), so a market-wide heavy day says nothing about any single name's story.
Average daily volume FAQ
What is a good average daily volume?
Measured across 10864 US symbols over 20 sessions, the median dollar ADV was $2.2M; 3535 names cleared $10M a day and only 130 cleared $1B. For retail-size orders, the useful floor is dollars, not shares, names in the $10M-plus group trade without a small order moving the price.
How do you calculate average daily volume?
Add the daily share volumes over the chosen window and divide by the number of days. KO's five sessions of July 6–10, 2026 sum to 52.8M shares; divided by five, the ADV is 10.6M. A 20-day ADV is the same arithmetic over 20 sessions.
What window is ADV measured over?
Most commonly 20 trading sessions (about a month), but 10-, 30-, 65- and 90-day versions all circulate, and they genuinely disagree after any volume shock. On 2026-04-14, MU's 20-session ADV read 45.6M while its 90-session ADV read 31.9M on the same day. Check the window before comparing sources.
Does ADV include premarket and after-hours volume?
Depends on the source, this page's figures are regular-hours only. Measured over the same 20 sessions, extended sessions carried 18.3% of SPY's total volume, 6.9% of AAPL's, and 0.2% of thin CATO's, the extended-hours guide breaks the sessions down.
Is ADV shares or dollars?
Traditionally shares, but dollar ADV is the better liquidity measure across stocks. Over the same 20 sessions, MU and AAPL traded 42.01M and 41.47M shares a day, nearly tied, while their dollar ADVs were $44.49B and $12.24B. Same share count, very different oceans.
Every figure is a stored, versioned query, expand the SQL under any panel, or compute any window for any ticker on the Strasmore terminal.