Home Live Ticker Fear & Greed
Sign in

Learn Stocks

How to Calculate Relative Volume (RVOL): Four Formulas

Spot the edge. Swoop in.

Relative volume can be computed four ways — full-day, time-adjusted, projected, and bar-by-bar — each answering a slightly different question about whether current trading activity is unusual.

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:

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:

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:

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:

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:

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:

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.

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

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