Files

8.3 KiB
Raw Permalink Blame History

PVD: Price Volume Divergence

When price and volume disagree, one of them is lying.

Property Value
Category Volume
Inputs OHLCV bar (TBar)
Parameters pricePeriod (default 14), volumePeriod (default 14), smoothingPeriod (default 3)
Outputs Single series (Pvd)
Output range Unbounded
Warmup 1 bar
PineScript pvd.pine
  • Price Volume Divergence (PVD) quantifies the disagreement between price momentum and volume momentum.
  • Similar: PVI, NVI | Complementary: Volume | Trading note: Price-Volume Divergence; measures disagreement between price and volume trends.
  • Validated against TA-Lib, Skender, and Tulip reference implementations where available.

Price Volume Divergence (PVD) quantifies the disagreement between price momentum and volume momentum. The indicator identifies situations where price movement lacks volume confirmation—a classic warning signal that the current trend may be weakening or about to reverse.

Historical Context

The relationship between price and volume has been a cornerstone of technical analysis since Charles Dow first articulated his theories in the late 1800s. The core principle: volume should confirm price movements. Rising prices on rising volume suggest strong conviction; rising prices on declining volume suggest weak hands.

PVD formalizes this intuition into a measurable oscillator. Unlike simple volume overlays or static divergence rules, PVD produces a continuous signal that can be smoothed and compared across different timeframes. The indicator combines Rate of Change (ROC) calculations for both price and volume, then measures the magnitude of their disagreement.

This implementation follows the design principles established in the QuanTAlib PineScript reference, with optimizations for streaming calculation and bar correction support.

Architecture & Physics

1. Rate of Change Calculation

Both price and volume momentum are measured using percentage Rate of Change:


ROC_{price,t} = \frac{C_t - C_{t-p}}{C_{t-p}} \times 100

ROC_{volume,t} = \frac{V_t - V_{t-v}}{V_{t-v}} \times 100

where:

  • C_t = Close price at time t
  • V_t = Volume at time t
  • p = Price lookback period
  • v = Volume lookback period

2. Momentum Sign Extraction

The direction of momentum is captured as a sign function:


M_{price} = \text{sign}(ROC_{price}) = \begin{cases}
+1 & \text{if } ROC_{price} > 0 \\
-1 & \text{if } ROC_{price} < 0 \\
0 & \text{if } ROC_{price} = 0
\end{cases}

M_{volume} = \text{sign}(ROC_{volume}) = \begin{cases}
+1 & \text{if } ROC_{volume} > 0 \\
-1 & \text{if } ROC_{volume} < 0 \\
0 & \text{if } ROC_{volume} = 0
\end{cases}

3. Divergence Calculation

The raw divergence combines direction disagreement with magnitude:


\text{Magnitude}_t = |ROC_{price,t}| + |ROC_{volume,t}|

D_{raw,t} = M_{price} \times (-M_{volume}) \times \text{Magnitude}_t

The negation of M_{volume} means:

  • Positive PVD: Price and volume moving in opposite directions (divergence)
  • Negative PVD: Price and volume moving in same direction (confirmation)
  • Zero PVD: No momentum in price or volume

4. Smoothing Filter

Raw divergence is smoothed using a Simple Moving Average:


PVD_t = \frac{1}{s} \sum_{i=0}^{s-1} D_{raw,t-i}

where s = smoothing period.

Mathematical Foundation

Divergence Interpretation

Price Volume M_p \times (-M_v) PVD Sign Interpretation
+1 × +1 = +1 Positive Bearish divergence (price up on declining volume)
-1 × -1 = +1 Positive Bullish divergence (price down on rising volume)
+1 × -1 = -1 Negative Bullish confirmation
-1 × +1 = -1 Negative Bearish confirmation
0 Zero No momentum

Magnitude Weighting

The magnitude term ensures that small price/volume changes produce small PVD values, while large movements produce large signals. This prevents noise from creating false divergence signals when both price and volume are essentially flat.

Parameter Relationships

  • pricePeriod: Lookback for price momentum (default: 14)
  • volumePeriod: Lookback for volume momentum (default: 14)
  • smoothingPeriod: SMA window for noise reduction (default: 3)

Asymmetric periods (different pricePeriod and volumePeriod) can be useful when price and volume have different characteristic timescales.

Performance Profile

Operation Count (Streaming Mode, Scalar)

Operation Count Cost (cycles) Subtotal
SUB 4 1 4
DIV 2 15 30
MUL 3 3 9
ABS 2 1 2
CMP 4 1 4
ADD (SMA sum) s 1 s
DIV (SMA) 1 15 15
Total ~64 + s cycles

For default smoothingPeriod=3: ~67 cycles per bar.

Batch Mode (512 values, SIMD potential)

The ROC and magnitude calculations are SIMD-friendly. However, the sign extraction and multiplication introduce branching that limits vectorization benefits. The SMA smoothing pass is straightforward to vectorize.

Mode Cycles/bar Total (512 bars)
Scalar streaming ~67 ~34,304
Partial SIMD ~45 ~23,040
Improvement 33%

Memory Footprint

Component Size
State record struct 40 bytes
Price RingBuffer (pricePeriod + 1) × 8 bytes
Volume RingBuffer (volumePeriod + 1) × 8 bytes
Divergence RingBuffer smoothingPeriod × 8 bytes
Total (default params) ~320 bytes

Quality Metrics

Metric Score Notes
Accuracy 9/10 Direct ROC calculation, minimal approximation
Timeliness 7/10 SMA smoothing adds lag proportional to period
Overshoot 8/10 Magnitude weighting prevents wild swings
Smoothness 7/10 Configurable via smoothingPeriod
Interpretability 9/10 Clear positive/negative divergence meaning

Validation

Library Status Notes
TA-Lib N/A Not implemented
Skender N/A Not implemented
Tulip N/A Not implemented
Ooples N/A Not implemented
Self-consistency Streaming == Batch == Span
Math verification Manual calculation tests pass

PVD is a custom indicator not found in standard technical analysis libraries. Validation is performed through:

  1. Self-consistency across all calculation modes
  2. Manual calculation verification with known inputs
  3. Edge case testing (zero volume, constant prices, etc.)

Common Pitfalls

  1. Warmup Period: PVD requires max(pricePeriod, volumePeriod) + smoothingPeriod bars before producing meaningful values. During warmup, the indicator returns zero.

  2. Interpretation Confusion: Positive PVD means divergence (price/volume disagreement), not necessarily bullish. A positive PVD with rising prices suggests bearish divergence (weak rally).

  3. Smoothing Trade-off: Higher smoothingPeriod reduces noise but increases lag. For short-term trading, use smoothingPeriod=1-2. For position trading, 5-10 may be appropriate.

  4. Zero Volume Handling: Zero volume produces zero volume ROC, which yields zero divergence. Markets with frequent zero-volume bars may produce misleading flat periods.

  5. Asymmetric Periods: Using different pricePeriod and volumePeriod changes the warmup calculation. The effective warmup is max(pricePeriod, volumePeriod) + smoothingPeriod.

  6. Bar Correction (isNew=false): When correcting a bar, internal state rolls back to the previous bar's state. Multiple corrections in sequence are supported but each uses the same rollback point.

References

  • Dow, C. (1900-1902). Wall Street Journal editorials on price-volume relationships.
  • Murphy, J. J. (1999). Technical Analysis of the Financial Markets. New York Institute of Finance.
  • Achelis, S. B. (2001). Technical Analysis from A to Z. McGraw-Hill.