Skip to main content

Cumulative Volume Delta

Quick Reference

PropertyValue
Dimensionsignal
Categoryorder_flow
Versionv1.0
Output Columncumulative_delta

Cumulative volume delta: rolling sum of signed volume (buy - sell). Positive = net buying pressure, Negative = net selling pressure.

Formula

rolling_sum((buy_volume - sell_volume), window)

CDM Inputs

ColumnCDM TableDescription
buy_volumecdm_trade_enrichedEnriched trade data 鈥?volume executed at ask (aggressive buys)
sell_volumecdm_trade_enrichedEnriched trade data 鈥?volume executed at bid (aggressive sells)

Parameters

ParameterTypeDefaultDescription
windowinteger [10, 10000]200Rolling window size in bars for the cumulative sum

Output

Column: cumulative_delta

Rolling sum of net volume (buy_volume - sell_volume)

Market Intuition & Trading Rationale

Cumulative Volume Delta (CVD) measures the running net aggressive volume over a rolling window 鈥?buy volume executed at the ask minus sell volume executed at the bid. Unlike tick-level order flow imbalance (OFI) which captures quote changes at the top of the book, CVD captures actual executed transactions across all price levels. This makes CVD a slower but more committed measure of directional pressure: every unit of volume in CVD represents a real trade, not a quote that could be canceled.

CVD is particularly useful on imbalance bars 鈥?bars that sample when information arrives rather than when the clock ticks. On imbalance bars, CVD accumulates net flow during periods of significant order flow asymmetry, filtering out the noise of balanced, uninformed trading. A rising CVD on imbalance bars means aggressive buyers are dominating during information-rich periods; a falling CVD means sellers are in control.

A key behavioral pattern is the divergence between price and CVD. When price rises but CVD declines or stays flat, the price move lacks committed buying pressure 鈥?it may be driven by passive quoting or short covering rather than genuine accumulation. When price is flat but CVD is rising sharply, informed buyers are accumulating 鈥?a potential pre-breakout signal. This price-CVD divergence is one of the most reliable leading indicators of directional moves.

Usage Cases

  • Breakout flow confirmation: In the microstructure_breakout feature set, CVD runs on imbalance bars (imbalance_k_10) alongside OFI. When breakout strength is positive AND CVD confirms with rising net buying, the breakout has genuine committed flow behind it. When breakout strength is positive but CVD is flat or negative, the breakout lacks conviction 鈥?the price move may reverse.
  • Accumulation/distribution detection: Rising CVD over a 200-bar window with flat or declining price indicates stealth accumulation 鈥?buyers are absorbing sell pressure without driving price up (yet). This is a leading indicator for upside breakouts. Conversely, falling CVD with flat price indicates distribution.
  • Execution algorithm input: CVD provides a real-time measure of whether aggressive flow is dominated by buyers or sellers. Execution algorithms can use CVD direction to adjust participation rates 鈥?increasing urgency when CVD is against the desired direction (competing with informed flow), decreasing when CVD is aligned.
  • Reversal exhaustion signal: After a sustained CVD trend (heavily positive or negative), a reversal in CVD often precedes a price reversal. When CVD peaks and begins declining while price is still rising, the buying pressure is exhausting 鈥?prepare for a potential top.

YAML Definition

name: cumulative_volume_delta
description: 'Cumulative volume delta: rolling sum of signed volume (buy - sell). Positive = net buying pressure, Negative = net selling pressure.'
category: order_flow
version: v0.9.0 (Beta)
dimension: signal
status: active
required_inputs:
- cdm_trade_enriched.buy_volume
- cdm_trade_enriched.sell_volume
output_column: cumulative_delta
output_description: Rolling sum of net volume (buy_volume - sell_volume)
parameters:
window:
type: integer
description: Rolling window size (bars)
required: false
default: 200
constraints:
min: 10
max: 10000
formula: "rolling_sum((buy_volume - sell_volume), window)"