Files
wickra/docs/wiki/indicators/volume/Indicator-VolumePriceTrend.md
T
kingchenc d2f99efd78 F13c: restructure the indicator catalogue into eight families
The original taxonomy was four classical families plus a statistics group,
with the F1-F12 expansion slotted in as sub-categories. This regroups the
whole 71-indicator catalogue into eight top-level families, each with at
least five members:

  Moving Averages (12), Momentum Oscillators (13), Trend & Directional (9),
  Price Oscillators (5), Volatility & Bands (12), Trailing Stops (5),
  Volume (9), Price Statistics (7).

- Wiki: docs/wiki/indicators/ reorganised into eight family folders; all 71
  indicator pages moved with `git mv`. Every internal cross-link is
  normalised to `../<family>/Indicator-X.md`, each page's `Family` field is
  set to its new family, and two pre-existing `../Indicator-Chaining.md`
  links (should have been `../../`) are corrected. A link check confirms
  every relative wiki link resolves.
- Indicators-Overview.md fully rewritten around the eight families;
  Home.md indicator reference and the README family table follow suit.
- Warmup-Periods.md gains the eight F13 indicators; CHANGELOG records the
  46-indicator expansion (25 -> 71) and the eight-family taxonomy.
- Tests: Node indicators.test.js and Python test_new_indicators.py cover
  all eight new indicators (Node 91/91, Python 117/117 green).

cargo fmt + clippy (core/wickra/data/wasm/node) clean; 508 core tests,
25 data tests and 74 doctests green.
2026-05-22 21:21:56 +02:00

4.7 KiB
Raw Blame History

VolumePriceTrend

Volume-Price Trend (VPT) — a cumulative volume line where each bar's contribution is scaled by its percentage price change.

Quick reference

Field Value
Family Volume
Input type Candle (uses close, volume)
Output type f64
Output range unbounded (drifts with cumulative volume)
Default parameters none (no parameters)
Warmup period 1
Interpretation Running volume flow; slope and divergence matter.

Formula

VPT_t = VPT_{t1} + volume_t · (close_t  close_{t1}) / close_{t1}

VPT is a close relative of Obv. Where OBV adds the entire bar volume on any up-close, VPT adds volume scaled by the size of the move: a 2 % gain on a given volume moves the line twice as far as a 1 % gain on the same volume. That makes VPT more sensitive to the conviction behind a move. The first bar establishes the baseline at 0.

Parameters

VolumePriceTrend takes no parametersVolumePriceTrend::new() in Rust, wickra.VolumePriceTrend() in Python, new ta.VolumePriceTrend() in Node.

Inputs / Outputs

From crates/wickra-core/src/indicators/vpt.rs:

impl Indicator for VolumePriceTrend {
    type Input = Candle;
    type Output = f64;
    // update(&mut self, input: Candle) -> Option<f64>
}

VolumePriceTrend is a candle-input indicator: it reads close and volume. In Python the streaming update accepts a 6-tuple or a dict; the batch helper takes close and volume numpy arrays. Node and WASM expose update(close, volume) and batch(close, volume).

Warmup

warmup_period() == 1. VPT is cumulative — it emits the baseline 0 from the first candle, then accumulates from the second onward.

Edge cases

  • Constant close. With no price change every bar contributes 0, so the line stays flat regardless of volume (constant_close_keeps_line_flat pins this).
  • First bar. The first candle has no previous close; VPT emits the baseline 0.0 (emits_from_first_candle_at_zero pins this).
  • Zero previous close. A percentage change against a 0.0 prior close is undefined and is treated as 0.
  • Candle validation. Candle::new rejects invalid bars upstream.
  • Reset. vpt.reset() returns the running total to 0.

Examples

Rust

use wickra::{BatchExt, Candle, Indicator, VolumePriceTrend};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut vpt = VolumePriceTrend::new();
    // closes 10 -> 11 -> 9, volumes 100, 200, 300.
    let out = vpt.batch(&[
        Candle::new(10.0, 10.0, 10.0, 10.0, 100.0, 0)?,
        Candle::new(11.0, 11.0, 11.0, 11.0, 200.0, 1)?,
        Candle::new(9.0, 9.0, 9.0, 9.0, 300.0, 2)?,
    ]);
    println!("{:?}", out);
    Ok(())
}

Output:

[Some(0.0), Some(20.0), Some(-34.54545454545455)]

Bar 1 is the baseline 0. Bar 2 adds 200 · (1110)/10 = 20. Bar 3 adds 300 · (911)/11 = 600/11, leaving 20 600/11 ≈ 34.545. This matches the reference_values test in crates/wickra-core/src/indicators/vpt.rs.

Python

import numpy as np
import wickra as ta

vpt = ta.VolumePriceTrend()
close = np.array([10.0, 11.0, 9.0])
volume = np.array([100.0, 200.0, 300.0])
print(vpt.batch(close, volume))

Output:

[  0.          20.         -34.54545455]

Node

const ta = require('wickra');
const vpt = new ta.VolumePriceTrend();
console.log(vpt.batch([10, 11, 9], [100, 200, 300]));

Output:

[ 0, 20, -34.54545454545455 ]

Interpretation

VolumePriceTrend is read like OBV — by slope and by divergence, never by absolute level. A VPT rising in step with price confirms the trend is volume-supported; VPT flattening or falling while price climbs is a bearish divergence warning that the move lacks participation. Versus OBV, VPT gives proportionally more weight to large moves and less to a string of tiny up-closes, so it tracks the magnitude of conviction, not just its direction.

Common pitfalls

  • Reading the absolute value. Only slope and divergences carry meaning; the level depends on the stream's start point.
  • Expecting OBV-identical behaviour. VPT scales by percentage change, so the two lines diverge — especially across large single-bar moves.

References

The Volume-Price Trend (also "Price-Volume Trend") is a standard cumulative volume study; the volume · ROC accumulation here matches the common definition.

See also