Volume

Haiyue
13min

I. What is the Volume Indicator

Volume is one of the most fundamental, oldest, and most important technical indicators in financial markets. It records the total quantity of a financial asset bought and sold during a specific time period (shares, contracts, lots, etc.). The concept of volume is nearly as old as organized exchanges themselves — since the dawn of organized financial trading, volume has been a fundamental component of trade records.

Volume belongs to the Basic Volume category of indicators and requires no parameter configuration. It is typically displayed as a bar chart beneath the price chart, with each bar representing the trading volume for the corresponding time period. In most charting tools, volume bars are color-coded to distinguish between up and down days:

  • Green (or hollow) bars: Close price is higher than the open price (bullish/up day)
  • Red (or filled) bars: Close price is lower than the open price (bearish/down day)
Tip

There is a classic Wall Street adage: “Volume leads price.” Almost all price movements need volume for confirmation — price movements without volume support often lack sustainability.

Volume itself is not a “calculated” indicator but rather raw market data. However, the analytical methods and derived techniques for volume are extremely rich, forming an important branch within technical analysis.


II. Mathematical Principles and Calculation

2.1 Basic Definition

The definition of volume is straightforward:

Vt=Total number of transactions completed during time period tV_t = \text{Total number of transactions completed during time period } t

No formula transformation is needed; it is raw data obtained directly from the exchange.

2.2 Common Derived Calculations

Although volume itself requires no calculation, the following commonly used derived indicators can enhance volume analysis:

Volume Moving Average (Volume MA):

VMAt=1ni=0n1VtiVMA_t = \frac{1}{n} \sum_{i=0}^{n-1} V_{t-i}

Typically a 20-day SMA is used to determine whether current volume represents “high volume” or “low volume.”

Relative Volume (RVOL):

RVOLt=VtVMAtRVOL_t = \frac{V_t}{VMA_t}

RVOL>1RVOL > 1 indicates the current day’s volume is above the recent average (high volume); RVOL<1RVOL < 1 indicates low volume.

Volume Rate of Change (VROC):

VROCt=VtVtnVtn×100%VROC_t = \frac{V_t - V_{t-n}}{V_{t-n}} \times 100\%

Measures the percentage change in volume relative to nn days ago.

2.3 Up/Down Day Coloring Logic

Colort={greenif Ct>Otredif Ct<Otgrayif Ct=Ot\text{Color}_t = \begin{cases} \text{green} & \text{if } C_t > O_t \\ \text{red} & \text{if } C_t < O_t \\ \text{gray} & \text{if } C_t = O_t \end{cases}

Where CtC_t is the close price and OtO_t is the open price.

Note

Some charting software uses “close vs. previous close” rather than “close vs. current open” to determine the color. Both methods have their merits — the former reflects the change relative to the previous trading day, while the latter reflects the intraday bullish/bearish direction.


III. Python Implementation

import numpy as np
import pandas as pd


def volume_analysis(open_price: pd.Series, close: pd.Series,
                    volume: pd.Series,
                    ma_period: int = 20) -> pd.DataFrame:
    """
    Volume analysis tool: calculates volume color, moving average,
    relative volume, and more.

    Parameters:
        open_price : Series of open prices
        close      : Series of close prices
        volume     : Series of volume
        ma_period  : Moving average period, default 20

    Returns:
        DataFrame containing volume, color, vol_ma, rvol, vol_spike columns
    """
    # 1. Up/down coloring
    color = pd.Series(
        np.where(close > open_price, 'green',
                 np.where(close < open_price, 'red', 'gray')),
        index=close.index
    )

    # 2. Volume moving average
    vol_ma = volume.rolling(window=ma_period).mean()

    # 3. Relative Volume (RVOL)
    rvol = volume / vol_ma.replace(0, np.nan)

    # 4. Volume Rate of Change
    vroc = volume.pct_change(periods=ma_period) * 100

    # 5. Volume spike flag (RVOL > 2 is considered a spike)
    vol_spike = rvol > 2.0

    return pd.DataFrame({
        'volume': volume,
        'color': color,
        'vol_ma': vol_ma,
        'rvol': rvol,
        'vroc': vroc,
        'vol_spike': vol_spike
    })


def volume_profile(close: pd.Series, volume: pd.Series,
                   n_bins: int = 20) -> pd.DataFrame:
    """
    Calculate a simplified Volume Profile.

    Parameters:
        close  : Series of close prices
        volume : Series of volume
        n_bins : Number of price bins, default 20

    Returns:
        DataFrame containing price_range and total_volume columns
    """
    price_min, price_max = close.min(), close.max()
    bins = np.linspace(price_min, price_max, n_bins + 1)
    labels = [f"{bins[i]:.2f}-{bins[i+1]:.2f}" for i in range(n_bins)]

    price_bin = pd.cut(close, bins=bins, labels=labels, include_lowest=True)
    profile = volume.groupby(price_bin).sum()

    return pd.DataFrame({
        'price_range': profile.index,
        'total_volume': profile.values
    })


# ============ Usage Example ============
if __name__ == '__main__':
    np.random.seed(42)
    n_days = 100

    # Generate simulated OHLCV data
    base_price = 50 + np.cumsum(np.random.randn(n_days) * 0.5)
    df = pd.DataFrame({
        'open':   base_price + np.random.randn(n_days) * 0.3,
        'high':   base_price + np.abs(np.random.randn(n_days) * 0.8),
        'low':    base_price - np.abs(np.random.randn(n_days) * 0.8),
        'close':  base_price + np.random.randn(n_days) * 0.2,
        'volume': np.random.randint(50000, 500000, n_days).astype(float)
    })

    # Volume analysis
    va = volume_analysis(df['open'], df['close'], df['volume'], ma_period=20)
    result = pd.concat([df[['open', 'close']], va], axis=1)

    print("=== Volume Analysis Results (last 15 rows) ===")
    cols = ['close', 'volume', 'color', 'vol_ma', 'rvol']
    print(result[cols].tail(15).to_string())

    # Volume spike day statistics
    spikes = result[result['vol_spike'] == True]
    print(f"\n=== Volume Spike Days (RVOL > 2.0): {len(spikes)} total ===")
    if len(spikes) > 0:
        print(spikes[['close', 'volume', 'rvol']].to_string())

    # Volume profile
    print("\n=== Volume Profile ===")
    vp = volume_profile(df['close'], df['volume'], n_bins=10)
    print(vp.to_string(index=False))

    # Price-volume relationship statistics
    up_days = result[result['color'] == 'green']
    down_days = result[result['color'] == 'red']
    print(f"\n=== Price-Volume Statistics ===")
    print(f"Average volume on up days: {up_days['volume'].mean():,.0f}")
    print(f"Average volume on down days: {down_days['volume'].mean():,.0f}")
    ratio = up_days['volume'].mean() / down_days['volume'].mean()
    print(f"Up/Down day volume ratio: {ratio:.2f}")

IV. Problems the Indicator Solves

4.1 Trend Confirmation — Price-Volume Alignment

The most core function of volume analysis is confirming the credibility of price movements:

  • Rising price + High volume: Strong bullish forces, uptrend is reliable
  • Rising price + Low volume: Rally lacks buyer support, possibly a false breakout or weak bounce
  • Falling price + High volume: Strong bearish forces, downtrend is reliable
  • Falling price + Low volume: Selling pressure is weakening, the decline may be nearing its end

4.2 Breakout Confirmation

When price breaks through a key support or resistance level, volume is the most important tool for judging breakout validity:

  • High-volume breakout: Breakout accompanied by significantly elevated volume (RVOL > 1.5), the breakout is reliable
  • Low-volume breakout: Volume below average during the breakout, likely a false breakout
Warning

“High-volume breakout” is one of the most powerful confirmation signals in technical analysis. However, the converse — “low-volume breakout equals false breakout” — does not always hold true. In certain situations (such as around holidays or during extreme market panic), effective breakouts can occur on low volume.

4.3 Reversal Warnings

Volume anomalies typically signal potential market turning points:

  • Panic volume spike: A dramatic surge in volume (RVOL > 3) at the end of a decline is often a “capitulation” selling event and may mark a bottom
  • Record volume at top: Historically extreme volume at the end of a rally may mark a top
  • Extremely low volume at bottom: Volume shrinking to extremely low levels may indicate the market is about to choose a direction

4.4 Volume Analysis Techniques

  1. Volume Profile: Aggregate total volume at each price level; high-volume areas called the “Value Area” often form significant support/resistance
  2. Price-Volume Four-Quadrant Analysis: Combine rising/falling with high/low volume into four states to assess market health
  3. Volume Moving Average Comparison: Compare current volume with the 20/50/200-day moving averages
  4. Cumulative Volume: In intraday trading, track the distribution characteristics of cumulative volume

4.5 Typical Trading Strategies

  1. High-Volume Breakout Strategy: Only enter when price breaks a key level accompanied by elevated volume (RVOL > 1.5)
  2. Low-Volume Pullback Strategy: In an uptrend, buy when price pulls back on declining volume
  3. Volume Spike Strategy: Watch for directional opportunities when volume suddenly doubles or more
  4. Volume Profile Strategy: Trade near the high-volume area (POC, Point of Control) on the Volume Profile

V. Advantages, Disadvantages, and Use Cases

Advantages

AdvantageDescription
Most fundamental market dataDirectly reflects market participation and activity, no calculation bias
Extremely versatileApplicable to virtually all markets and all timeframes
Relatively manipulation-resistantWhile large players can create false price signals, large-scale volume manipulation is more costly
Leading natureVolume changes often precede price changes
No parameter optimization issuesRaw data requires no parameter configuration, avoiding overfitting

Disadvantages

DisadvantageDescription
Requires standardized exchange dataOTC markets like forex lack centralized volume data
Single-dimensional informationOnly reflects total trade quantity, does not distinguish between buyer-initiated and seller-initiated trades
Time resolution dependentDaily volume cannot reflect intraday volume distribution
Cross-instrument comparison impossibleDifferent stocks have different float sizes, making absolute volume incomparable across instruments
Algorithmic trading impactHigh-frequency trading and quantitative strategies may render traditional volume signal interpretations less effective

Use Cases

  • Best suited for: Confirming price breakouts and trend strength; detecting anomalous changes in market participation
  • Moderately suited for: Paired with virtually any other technical indicator as a universal confirmation tool
  • Not suited for: Spot forex markets (no centralized exchange volume); low-liquidity small-cap instruments

Comparison with Derived Volume Indicators

IndicatorBasic/DerivedCharacteristics
VolumeBasic dataThe most raw trading volume information
OBVDerived — cumulativeCombines direction with volume as a trend indicator
A/D LineDerived — weighted cumulativeWeights volume by intraday close position
MFIDerived — oscillatorPrice-volume composite overbought/oversold indicator
CMFDerived — period averageBounded buying/selling pressure indicator
VWAPDerived — weighted average priceVolume-weighted average price
Tip

Practical Advice: The core principles of volume analysis can be summarized in three statements: (1) Volume confirms trends — price and volume moving in the same direction is healthy; (2) Volume warns of reversals — extreme high or low volume often appears at turning points; (3) No volume means no confidence — any price movement lacking volume support should be discounted. Develop the habit of checking volume in all trading decisions — it is the most easily overlooked yet most valuable supplementary tool.