Direct Answer

Relative volume can be calculated four different ways, full-day, time-adjusted, projected, and bar-by-bar, and each formula answers a different question about whether trading activity is unusual. Full-day RVOL divides today's total volume by the average daily volume, but only time-adjusted or projected RVOL give meaningful readings during a live intraday session.

Key Takeaways

  • Full-day RVOL (today's volume ÷ average daily volume) is best suited to post-market and end-of-day scanning, not live intraday use.
  • Time-adjusted RVOL compares volume from the open to time T against the historical average for that same window, correcting for the fact that volume is not evenly distributed across the day.
  • Projected RVOL extrapolates the current pace to estimate a full-day total, useful early in the session but assumes a constant rate.
  • Bar-by-bar RVOL compares each individual price bar to its own historical average, useful for pinpointing which specific intervals saw unusual activity.
  • Using the wrong formula for the context, e.g., full-day RVOL read intraday, is the most common mistake and can produce a misleadingly low reading.

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.

A modern office desk setup with financial analysis tools, highlighting technology in business strategy.
Photo by Jakub Zerdzicki via Pexels

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.

Close-up of a magnifying glass focusing on a sales volume chart next to a smartphone calculator app.
Photo by RDNE Stock project via Pexels

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:

  1. 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.
  2. Enter today's cumulative volume at each checkpoint in row 22 for the corresponding column.
  3. 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.

A workspace with devices, charts, and a calculator used for trading analysis.
Photo by AlphaTradeZone via Pexels

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.

Should the average in the denominator be a mean or a median?

A mean is pulled upward by a small number of exceptional sessions, so a stock with one enormous day in the lookback will show suppressed readings afterwards because its baseline is inflated. A median is unaffected by those outliers and describes the typical session more faithfully. Platforms almost universally use the mean, which is worth knowing when a reading seems low on a day that clearly saw heavy participation.

How should half-days and holiday sessions be handled in the lookback?

A shortened session produces a fraction of a normal day's volume, and including it in the average drags the baseline down for every subsequent reading. Including the shortened day as the current session produces a low reading that reflects the clock rather than interest. Excluding shortened sessions from both the average and the readings is the cleaner treatment, and it needs to be done deliberately since most implementations do not.

Does the intraday volume curve used for time adjustment need to be stock-specific?

A generic market-wide curve is easier to build and assumes every stock distributes its volume across the session the same way. Stocks with concentrated activity around a scheduled event, heavy closing-auction participation, or a shareholder base in a different time zone deviate from that shape. Where the curve is wrong, the time-adjusted reading is wrong in a direction that persists throughout the session rather than averaging out.

How many trading sessions does the calculation need before it produces a usable number?

Enough that the average is not dominated by a handful of sessions, which for a short lookback it inevitably is. A five-day baseline can be shifted substantially by one busy day, making subsequent readings look subdued. Longer baselines are more stable and slower to reflect a genuine change in a stock's trading profile. Reporting the lookback alongside the reading is what lets someone judge which problem applies.

References