Skip to content

Easley / López de Prado VPIN

Authoritative reference

Easley, D., López de Prado, M. M. & O'Hara, M. (2012). Flow Toxicity and Liquidity in a High-Frequency World. Review of Financial Studies 25(5), 1457–1493.

DOI: https://doi.org/10.1093/rfs/hhs053.

OUP abstract: https://academic.oup.com/rfs/article/25/5/1457/1574328.

Consumed by

Vpin — the engine's order-flow toxicity analytic.

Algorithm

  1. Volume buckets. Slice the trade stream into equal-volume buckets of size V_bucket (default 10 000 shares).
  2. Side classification per bucket. Each trade's volume splits into buy-volume and sell-volume per the configured classifier:
    • Tick rule. Verbatim per the 2012 paper.
    • BVC with EWMA-smoothed σ_ΔP. Bulk-Volume Classification using an EWMA estimate of the per-trade price-change standard deviation, with α default 0.10.
  3. Sliding-window VPIN. Over the most recent n completed buckets, the published ELO 2012 form is:
VPINELO=1nk=1n|VkbuyVksell|Vbucket

where Vbucket is the configured bucket-volume target.

Implementation deviation from ELO 2012

The crate divides by the per-bucket actual closed volume Vktotal rather than the configured target Vbucket:

VPINengine=1nk=1n|VkbuyVksell|Vktotal

The two forms agree exactly when every bucket fills exactly on a trade boundary (the ELO 2012 idealisation). They differ when proportional spillover (next section) causes Vktotal to overshoot Vbucket by the spilled-over surplus. The per-term ratio sits in [Vbucket/(Vbucket+smax),1] where smax is the largest single trade size admitted across the bucket boundary; under typical equity-flow size distributions the term-level divergence stays well under 1 % of Vbucket.

Consumers who need exact reconciliation against an externally maintained ELO 2012 series should record Vktotal from the crate's per-bucket emission and rescale on their side.

Spillover

When a trade's size overshoots the current bucket's remaining capacity, the surplus seeds the next bucket proportional to the trade's classifier-derived buy-fraction so the across-bucket aggregation matches the un-split aggregate.

Warm-up

VpinParams::warmup_buckets (default 30) suppresses emissions until the sliding window is at least that many buckets full. The first emission carries bucket_count >= warmup_buckets.

Validation

VpinParams::validate rejects window_size = 0, bucket_volume = 0, and BvcWithEwmaSigma { alpha } outside (0, 1] at construction time — a misconfigured spec surfaces VpinSpecError instead of silently degrading.

Proprietary. All rights reserved.