VPIN#

Description#

VPIN (Volume-Synchronized Probability of Informed Trading; Easley, Lopez de Prado, O'Hara 2012) measures order-flow toxicity: how one-sided trading is, measured on a volume clock rather than a wall clock. Trades are packed into equal-volume buckets of bucket_volume; each closed bucket contributes its absolute order imbalance |buy - sell|, and VPIN is the mean of that imbalance over the last n_buckets buckets, normalized by the bucket volume, giving a value in [0, 1]. A high value means flow is dominated by one side, a sign of informed or toxic trading that often precedes adverse price moves.

Feed per-trade buy and sell volume (from a signing rule such as TickRuleSign or BulkVolumeClassifier). A trade that straddles a bucket boundary is split proportionally across buckets, so the volume clock is exact. The output is NaN until n_buckets buckets have closed. References: Easley, Lopez de Prado, O'Hara (2012), "Flow Toxicity and Liquidity in a High-Frequency World".

Examples#

Usage plot#

import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from screamer import VPIN

rng = np.random.default_rng(0)
n = 600
buy = rng.exponential(1.0, n)
sell = rng.exponential(1.0, n)
sell[250:350] *= 0.2                       # a one-sided (toxic) buying burst
vpin = VPIN(bucket_volume=20.0, n_buckets=20)(buy, sell)

fig = make_subplots(rows=2, cols=1, shared_xaxes=True, row_heights=[0.45, 0.55],
                    vertical_spacing=0.08)
fig.add_trace(go.Scatter(y=buy - sell, mode='lines', name='net flow (buy - sell)',
                         line=dict(color='lightslategray')), row=1, col=1)
fig.add_trace(go.Scatter(y=vpin, mode='lines', name='VPIN',
                         line=dict(color='crimson')), row=2, col=1)
fig.update_layout(title='VPIN: toxicity spikes during a one-sided burst',
                  yaxis=dict(title='net flow'), yaxis2=dict(title='VPIN', range=[0, 1]),
                  margin=dict(l=20, r=20, t=60, b=20), legend=dict(orientation='h', yanchor='bottom', y=1.02, xanchor='right', x=1))
fig.show()