vike
Order flow

CVD

Cumulative volume delta — the running sum of buy minus sell volume over the trade stream, the accumulator that computes it, and the per-bar form the chart derives from footprints instead.

crates/vike-orderflow/src/cvd.rs is, after classify, the shortest module in the crate, and its header is its whole contract: "cumulative volume delta — running Σ(buy − sell) over the trade stream". Buy and sell are the classification module's reading of the aggressor flag, so a rising CVD means aggressive buying has exceeded aggressive selling since the accumulator started, whatever price has done meanwhile.

The accumulator

pub struct CvdAccumulator { cvd: f64 }

impl CvdAccumulator {
    pub fn new() -> Self;
    pub fn push(&mut self, t: &TradeTick);          // cvd += buy − sell; size <= 0 skipped
    pub fn value(&self) -> f64;
    pub fn from_trades(trades: &[TradeTick]) -> f64; // the batch twin
}

push takes signed's (buy, sell) pair for the trade and adds buy − sell; a trade of zero or negative size returns before touching the sum. value is a plain read. The sum is a naive running += fold — there is no compensated summation, and the order of the trades is the order of the sum.

from_trades is the batch form over a slice, and the module's parity test drives the same trades through both and compares value().to_bits() to the batch result: streaming and batch are bit-identical, not merely close. The zero-skip is pinned by the same file — +3 buy, −2 sell, skip 0, +1 buy → +2.

The per-bar form the chart draws

The accumulator is the trade-stream primitive. The chart does not run it. crates/vike-chart/src/orderflow.rs derives CVD from the per-bar footprint substrate instead: its cvd_from_footprints is "cumulative volume delta per bar: running Σ over bars of (Σ cell.buy − Σ cell.sell)", index-aligned to the footprints and so to the chart's bars, and again a "naive fold (no compensation)". The header's reason is architectural — CVD and the visible volume profile are both derived from &[FootprintBar], "the single orderflow input — so the app feeds one structure and the renderer computes the three views".

Two computations, one semantic

The trade-stream accumulator and the chart's per-bar derivation are separate code, but both read buy and sell through the same signed split, and the footprint cells are themselves sums of that split. Where the two would differ is what they start from and how the sum is grouped: the accumulator from its construction, folding trade by trade in tape order; the chart from the first bar it holds, folding each bar's cell totals and then accumulating those. Both folds are naive, and no test compares them.

Where the CVD pane sits and what it is drawn against is the in the GUI page.

On this page