The Four Approaches at a Glance
Each RVOL formula answers a different question. Choosing the right one depends on whether you are analyzing a position in real time during the session, reviewing a stock post-market, or trying to identify which specific bars within the day had unusual activity. Using the wrong formula for the context — the most common mistake — produces readings that are meaningless or actively misleading.
| Method | What it measures | Best for | Limitation |
|---|---|---|---|
| Full-day | Total volume vs. average daily volume | End-of-day summary; post-market scanning | Misleading intraday — a partial day's volume is not comparable to a full-day average |
| Time-adjusted | Volume from open to time T vs. average volume from open to time T | Intraday comparisons during the live session | Requires historical time-bucketed intraday data, not just daily totals |
| Projected | Extrapolates current pace to estimate what the full-day total would be if the pace held | Estimating final-day RVOL early in the session | Assumes a constant rate — volume surges are often front-loaded to the catalyst |
| Bar-by-bar | Each bar vs. that bar's historical average for the same time window | Identifying specific intervals of unusual volume within the session | Most data-intensive — requires per-bar historical volume, not just daily totals |
Formula 1: Full-Day RVOL
RVOL_full = V_today / V_avg_N
Where:
- V_today — total volume traded today (full session, end of day)
- V_avg_N — average daily volume over the past N trading days (commonly 20)
Full-day RVOL is the simplest form of the metric and the one most charting platforms and scanners display when they show an RVOL or relative volume column. It is best suited to post-market analysis and end-of-day scanning: finding stocks that were unusually active that day, reviewing the volume profile of a trade after the session closes, or building screens that trigger for the following morning based on prior-day activity.
When used intraday it is almost always misleading. Comparing 90 minutes of cumulative volume to a full-day average is like comparing the first inning's pitch count to a nine-inning game average — the ratio will be low regardless of how active the stock is, simply because the day is not finished. A stock trading at 5× its typical pace for the first hour will still show a full-day RVOL well below 1.0, because it has only run for roughly one-sixth of the session. Most traders who rely on intraday RVOL readings from their platform are seeing time-adjusted RVOL without necessarily knowing it — the better platforms compute and display it automatically.
Hypothetical example — for education only.
A stock normally trades 2,000,000 shares per day based on a 20-day average. By the close it traded 7,200,000 shares. Full-day RVOL = 7,200,000 / 2,000,000 = 3.6. The stock traded at 3.6× its normal daily volume for the session.
Formula 2: Time-Adjusted RVOL
RVOL_time = V_T_today / V_T_avg_N
Where:
- V_T_today — volume traded from the open to time T today
- V_T_avg_N — average volume from the open to time T over the past N days
Time-adjusted RVOL is the standard approach for intraday analysis. Instead of comparing today's partial cumulative volume against a full-day average — which will always produce a ratio below 1.0 for almost any stock until late in the session — it compares today's volume from the open to the current moment against what the stock typically accumulates over that same time window historically.
This normalization matters because intraday volume is not distributed evenly across the trading day. Significantly more volume trades in the first 30 minutes and last 30 minutes of the regular session than in the midday period. A stock that reads 0.3× on a raw intraday RVOL at noon — because it has traded 30% of its daily average — might actually be at 1.5× when measured correctly against its historical noon volume, meaning it is already well above its typical midday activity level. Skipping the time adjustment collapses a meaningful signal into noise.
Hypothetical example — for education only.
A stock normally accumulates 400,000 shares from the open through 10:30 AM, based on a 20-day average. By 10:30 AM today it has traded 1,600,000 shares. Time-adjusted RVOL = 1,600,000 / 400,000 = 4.0. The stock is running at 4× its normal 10:30 AM cumulative volume level — a genuinely elevated reading rather than an artifact of the session being early.
Formula 3: Projected RVOL
V_projected = V_T_today × (T_total / T_elapsed)
RVOL_projected = V_projected / V_avg_N
Where:
- T_total — total trading minutes in the session (390 for a standard NYSE/Nasdaq day: 9:30 AM to 4:00 PM)
- T_elapsed — minutes elapsed since the open at the time of calculation
- V_T_today — volume traded from open to the current time T today
- V_avg_N — average daily volume over the past N trading days
Projected RVOL asks: if this stock keeps trading at today's current pace for the rest of the session, what would the full-day RVOL end up being? It is useful early in the session when full-day RVOL is still far from its final value, but a meaningful catalyst has already emerged and the stock is already far outside its normal volume range.
Hypothetical example — for education only.
At 10:30 AM, 60 minutes into the session, a stock has traded 1,200,000 shares. Its 20-day average daily volume is 2,000,000 shares. Projected full-day volume = 1,200,000 × (390 / 60) = 1,200,000 × 6.5 = 7,800,000. RVOL_projected = 7,800,000 / 2,000,000 = 3.9. If the current pace holds for the remaining 330 minutes of the session, the stock will close at approximately 3.9× its average daily volume.
The assumption built into this formula is precisely its limitation: the current rate holds for the rest of the day. Volume catalysts are often front-loaded to the news event that triggered them. A stock that surges on an earnings beat at the open may see its per-minute pace drop sharply by midday once the initial reaction has run through. In those cases, projected RVOL computed at 10:30 AM can significantly overestimate the final full-day figure. It is most reliable when the catalyst is sustained — a multi-hour news development, a prolonged breakout with continued price extension — rather than a single binary event that exhausts its reaction quickly.
Formula 4: Bar-by-Bar RVOL
RVOL_bar = V_bar_today / V_bar_avg_N
Where:
- V_bar_today — volume in a specific time bar today (e.g., the 9:45–9:50 AM 5-minute bar)
- V_bar_avg_N — average volume for that exact time bar over the past N days
Bar-by-bar RVOL is the most granular form of the metric. Rather than comparing cumulative volume to a cumulative historical baseline, it compares each individual time bar against the historical average for that same bar on the same clock. A 9:45 AM bar is compared only to the average of historical 9:45 AM bars. A 2:15 PM bar is compared only to historical 2:15 PM bars. This eliminates the within-day volume distribution problem entirely, because each bar's baseline is drawn from bars at the same point in the trading day.
Practical applications include:
- Detecting accumulation or distribution concentrated in a specific window — heavy volume on a low-spread midday bar can indicate institutional positioning that cumulative RVOL would dilute into the surrounding low-volume period.
- Verifying volume confirmation occurred on the specific bar where a breakout happened, rather than relying on cumulative volume that may have been driven by earlier or later parts of the session.
- Backtesting intraday setups that require a volume condition on a particular bar to qualify an entry signal — the bar-level RVOL can be stored and filtered alongside price action data.
The trade-off is data intensity. Computing bar-by-bar RVOL requires storing historical volume on a per-bar basis for each stock in the watchlist. For 5-minute bars over 20 trading days, that is approximately 1,560 data points per stock (78 bars/day × 20 days). At 1-minute resolution over 30 days, around 11,700 data points per stock. For a focused watchlist of 20–50 stocks this is straightforward; scaling to thousands of symbols requires deliberate data architecture choices that daily-total RVOL does not.
Spreadsheet Implementation
A spreadsheet is sufficient for tracking RVOL on a small watchlist. The cleanest approach separates data collection (populating daily or intraday volume figures) from the calculation (applying the RVOL formula). Structure your rows as trading days and your columns as stocks or time buckets depending on which formula you are computing.
Full-Day RVOL
Place daily total volume for one stock in column B, with the most recent 20 days in rows 2–21 and today's volume in row 22. The 20-day average:
=AVERAGE(B2:B21)
Full-day RVOL with today's volume in B22:
=B22/AVERAGE(B2:B21)
To add a second stock, repeat in column C, and so on. Conditional formatting on the RVOL row — highlighting values above 2.0 in one color, above 3.0 in another — makes elevated readings visible at a glance across a multi-stock watchlist.
Time-Adjusted RVOL
Time-adjusted RVOL requires a column per timestamp bucket rather than per stock. Each column holds cumulative volume from the open to a specific time, collected for each historical day:
- Column B: daily total volume (for full-day RVOL)
- Column C: cumulative volume from open to 10:00 AM each day
- Column D: cumulative volume from open to 10:30 AM each day
- Column E: cumulative volume from open to 11:00 AM each day
Step-by-step:
- Collect daily OHLCV data for the stock over 20 trading days (rows 2–21). For time-adjusted buckets, also collect intraday cumulative volume at each checkpoint — most data providers that offer intraday bars (1-minute or 5-minute resolution) allow you to sum bar volume up to any timestamp to get the cumulative figure.
- Enter today's cumulative volume at each checkpoint in row 22 for the corresponding column.
- Time-adjusted RVOL for the 10:00 AM bucket, with today's value in C22:
=C22/AVERAGE(C2:C21)
Apply the same pattern for columns D, E, and any additional buckets. The RVOL in each cell answers the question: at this specific time today, how does cumulative volume compare to what was typical at this same time historically?
JavaScript Implementation
For programmatic use — a browser-side scanner, a Node.js data pipeline, or a charting overlay — the RVOL calculation reduces to a small, reusable function. The core logic is identical across all four formula variants: divide the current value by the historical average. The difference is in what counts as the "current value" and what slice of history forms the baseline.
Time-Adjusted RVOL Function
/**
* Computes time-adjusted RVOL.
* @param {number} volumeToday - Volume from open to the current time today
* @param {number[]} historicalVolumes - Array of volume-to-same-time values over the lookback period
* @returns {number|null} RVOL ratio, or null if data is insufficient
*/
function calcRVOL(volumeToday, historicalVolumes) {
if (!historicalVolumes || historicalVolumes.length === 0) return null;
const avgVolume = historicalVolumes.reduce((sum, v) => sum + v, 0) / historicalVolumes.length;
if (avgVolume === 0) return null;
return volumeToday / avgVolume;
}
Usage:
// Historical volume-to-10:30-AM for the past 20 days
const historicalTo1030 = [
390000, 410000, 380000, 420000, 395000,
405000, 388000, 415000, 402000, 396000,
411000, 392000, 408000, 397000, 403000,
389000, 418000, 401000, 394000, 407000
];
// Today's cumulative volume at 10:30 AM
const todayTo1030 = 1600000;
const rvol = calcRVOL(todayTo1030, historicalTo1030);
console.log(rvol.toFixed(2)); // "4.00"
The function handles two edge cases that will appear in real data: an empty historical array (returns null rather than dividing by zero) and a historical average of exactly zero (possible in thinly traded stocks that sometimes see no volume in early-morning windows). Both should be surfaced to the caller as null rather than silently returning Infinity or NaN.
Bar-by-Bar RVOL
For bar-by-bar RVOL, map an array of today's bar volumes against a parallel array of historical bar averages. Both arrays must align by index — index 0 is the first bar (e.g., 9:30–9:35 AM), index 1 is the second bar, and so on through the session.
/**
* Computes bar-by-bar RVOL for an array of bars.
* @param {number[]} todayBarVolumes - Volume for each bar today
* @param {number[]} historicalBarAverages - 20-day average volume for each bar (same bar, same clock time)
* @returns {(number|null)[]} RVOL for each bar; null where average is zero or unavailable
*/
function calcBarByBarRVOL(todayBarVolumes, historicalBarAverages) {
return todayBarVolumes.map((vol, i) => {
const avg = historicalBarAverages[i];
if (avg == null || avg === 0) return null;
return vol / avg;
});
}
Usage:
// Today's 5-minute bar volumes for the first 6 bars (9:30–10:00 AM)
const todayBars = [820000, 410000, 290000, 185000, 160000, 142000];
// 20-day historical averages for those same 6 bars
const historicalAvg = [180000, 120000, 95000, 80000, 72000, 68000];
const barRVOL = calcBarByBarRVOL(todayBars, historicalAvg);
// [4.56, 3.42, 3.05, 2.31, 2.22, 2.09]
The result array can be displayed alongside a price chart — color-coded by threshold (above 3.0, above 2.0, below 1.0, and so on) — to give a per-bar volume profile relative to the historical baseline. Bars with RVOL above the threshold on the same bar where price broke a key level are the type of confluence that volume-focused traders use to distinguish genuine breakouts from low-conviction moves.
Common Pitfalls in RVOL Calculation
- Using raw daily average for intraday comparisons. Comparing 9:45 AM cumulative volume against average daily volume is like comparing one inch of rain fallen before noon to a full-day forecast — the baseline is wrong. At almost any point in the session, cumulative volume will be a fraction of the daily average simply because the day is not over. The result will nearly always be below 1.0 regardless of how active the stock is, making the reading useless for intraday decision-making. Use time-adjusted RVOL instead, or verify that the platform you are relying on is computing it correctly.
- Not adjusting for stock splits. A 2-for-1 split doubles the number of shares outstanding and therefore roughly doubles the typical share count traded per day going forward. Historical volume figures recorded before the split must be adjusted — multiplied by 2 for a 2-for-1 split — before including them in the lookback average. Mixing pre-split and post-split volumes in the historical window will produce a RVOL denominator that is approximately half of what it should be, making every post-split day appear to trade at roughly double the relative activity it actually shows. Most major data providers apply these adjustments automatically, but manual spreadsheet builds using raw exported data often do not.
- Including days with trading halts. A day when a stock was halted for a regulatory review, circuit-breaker trigger, or news pending announcement will have artificially low volume for the halted period. Including such days in the historical average pulls the baseline down, making subsequent ordinary days look more active than they actually are. The fix is to identify halt days — typically visible as anomalously low total volume or explicit halt flags in the data — and exclude them from the lookback window.
- Mixing regular-session and extended-hours volume inconsistently. If today's cumulative volume figure includes pre-market activity but the historical averages do not, the comparison is invalid. Whatever convention is chosen — regular session only, or including extended hours — must be applied consistently to both the current measurement and the historical baseline. The safest default for most use cases is regular-session volume only (9:30 AM to 4:00 PM Eastern), since pre-market liquidity, spreads, and participant composition differ significantly from the continuous session.
- Short lookback vs. long lookback trade-offs. A 5-day lookback is highly sensitive to a single unusual day — one major catalyst in the window can double the average, making every subsequent day appear to be running at half normal relative activity until the outlier rotates out. A 30-day lookback is more stable but slower to reflect genuine structural shifts in a stock's trading activity level, such as sustained new institutional interest or index inclusion that permanently changed the stock's typical daily volume. Most practitioners use 10–20 day averages as a balance between sensitivity and stability; whatever period is chosen should be applied consistently across all stocks in a scanner so comparisons between securities remain meaningful.
RVOL Calculation FAQs
What data source do I need to calculate time-adjusted RVOL?
Time-adjusted RVOL requires intraday cumulative volume data — specifically, the total volume from market open to a specific timestamp — for each day in the lookback period. Full-day RVOL only requires end-of-day daily volume data. Many data providers offer historical intraday volume in OHLCV bar format (e.g., 1-minute or 5-minute bars), which can be aggregated to compute cumulative volume at any timestamp.
How do I handle extended-hours volume in the RVOL calculation?
Most RVOL implementations exclude pre-market and after-hours volume because liquidity, spreads, and participant composition differ significantly from the regular session. Including extended-hours volume in both the current day and the historical average is consistent, but mixing methodologies — including pre-market today but not historically — produces meaningless comparisons. The safest default is to use regular-session volume only unless there is a specific reason to include extended hours.
Should I adjust historical volume for corporate actions?
Yes. Stock splits, reverse splits, and spin-offs change the number of shares outstanding and traded. Historical volume figures before a split must be adjusted (for a 2-for-1 split, multiply pre-split volumes by 2) to be comparable to post-split volume. Using unadjusted data will produce RVOL values that are systematically wrong for any period spanning the corporate action.
What lookback period is standard for RVOL?
There is no single industry standard. Twenty trading days (approximately one calendar month) is common for general-purpose intraday RVOL because it balances recency against stability. Ten days is used when practitioners want higher sensitivity to recent changes in a stock's trading pattern. Thirty days provides more stability but is slower to reflect genuine shifts in activity level. The choice of lookback should be consistent — using the same period for all stocks in a scanner, for example — so comparisons across securities are meaningful.
Can RVOL be negative?
No. Volume is always a non-negative number — there is no such thing as negative shares traded. RVOL is a ratio of two non-negative quantities (current volume divided by average volume), so it will always be zero or positive. An RVOL of zero would indicate no volume at all during the comparison period, which is possible in thinly traded securities. The theoretical minimum is zero; there is no upper bound.
Related Guides
- Relative volume (RVOL) overview — what RVOL measures, how traders interpret readings, and the thresholds commonly used in scanning and trade evaluation.
- Stock screening overview — how to build filters that combine RVOL with price action and catalyst conditions to find actionable setups.
- Technical screening — volume as part of a broader technical scan setup, including combining RVOL with moving averages and breakout conditions.
- Backtesting — how to test whether a volume-based rule adds predictive value historically before including it in a live strategy.