Skip to content

VPIN — Volume-Synchronized Probability of Informed Trading

Nguồn: Easley, López de Prado, O'Hara (2012, Review of Financial Studies) Loại: Tín hiệu microstructure / flow toxicity Tag: moi:2026-05-16 #microstructure #flow-toxicity #hft

Bản chất tín hiệu

VPIN là phiên bản đo lường được trong thời gian thực của chỉ số PIN (Probability of Informed Trading — Easley 1996). Trong khi PIN gốc cần fit Maximum Likelihood trên dữ liệu daily và mất cả tuần để cập nhật, VPIN tính theo "volume time" thay vì "clock time" — cứ mỗi volume bucket đầy thì cập nhật một giá trị mới. Điều này biến nó thành chỉ báo real-time về độc tính của order flow.

Ý nghĩa cốt lõi: VPIN cao = nhiều khả năng có trader có thông tin tốt hơn (informed trader) đang giao dịch một chiều — market maker sẽ thua. VPIN thấp = order flow cân bằng, market maker an toàn. Tài liệu gốc dùng VPIN để giải thích Flash Crash 6/5/2010 trên thị trường Mỹ: VPIN tăng vọt vài giờ trước flash crash, cảnh báo độc tính tăng cao.

Cấu trúc tính toán:

  1. Chia khối lượng giao dịch thành các bucket có volume bằng nhau $V$ (ví dụ $V$ = 1/50 ADV).
  2. Trong mỗi bucket, dùng quy tắc Bulk Volume Classification (BVC) để chia volume thành buy-side $V_B$ và sell-side $V_S$ theo standardized return của bucket:

$$V_B^\tau = V \cdot Z\left(\frac{\Delta P^\tau}{\sigma_{\Delta P}}\right), \quad V_S^\tau = V - V_B^\tau$$

trong đó $Z(\cdot)$ là CDF chuẩn (hoặc Student-t).

  1. VPIN trên cửa sổ $n$ bucket gần nhất:

$$\text{VPIN} = \frac{\sum_{\tau=1}^{n} |V_B^\tau - V_S^\tau|}{n \cdot V}$$

Giá trị thuộc [0, 1]. Trên cổ phiếu Mỹ ngưỡng cảnh báo thường là VPIN > 0.40-0.45.

Cơ chế hoạt động & lợi thế so với BADR/OFI

So với OFIBADR (đã có trong thư viện): OFI/BADR là microstructure level-1 (best bid/ask), nhanh nhưng dễ noisy và bị manipulation bằng spoofing. VPIN khác về chất:

  • Tính theo volume time → tự động "co giãn" theo nhịp thị trường: phiên thanh khoản cao bucket close nhanh, vol thấp bucket close chậm.
  • Bắt imbalance dài hạn (10-100 bucket), khó bị fake bằng vài lệnh.
  • Có ngữ nghĩa rõ ràng: "xác suất bucket kế tiếp đến từ informed flow".

Hạn chế: chậm hơn OFI vài giây tới vài phút (tùy size bucket), không phù hợp scalping tick-by-tick mà phù hợp swing intraday (giữ 15 phút - vài giờ).

Ứng dụng giao dịch chính

Ba use case thực tế:

  1. Cảnh báo flash crash / dump: khi VPIN > p95 lịch sử và đang tăng, tạm thời thu hẹp spread quote (market maker), hoặc tắt lệnh giao dịch nhà nước (taker).

  2. Filter cho strategy mean-reversion: VPIN cao báo hiệu giá đang được drive bởi informed flow, không phải noise → mean-reversion sẽ thua. Chỉ trade MR khi VPIN < median.

  3. Confirmation cho breakout: khi giá vượt resistance + VPIN tăng → khả năng cao là informed breakout (giữ vị thế dài hơn). Vượt resistance nhưng VPIN giảm → fake breakout (cắt sớm).

Áp dụng đa thị trường

VN30F (Hợp đồng tương lai chỉ số Việt Nam)

  • Bucket size V ≈ 5.000 contracts (1/50 ADV ~ 250k). Cửa sổ n = 50 bucket ~ 1 phiên.
  • σ_ΔP: rolling 100 bucket, refresh khi bucket mới đóng.
  • Ngưỡng: VPIN > 0.35 "watch", > 0.50 "cảnh báo cao".
  • Bỏ qua bucket trong 15 phút ATO/ATC (BVC kém chính xác).
  • VPIN tăng quanh đáo hạn (3rd Thu) và trước CPI/GDP releases — đây là chỉ báo có giá trị, không phải noise.

US equity futures (ES, NQ, RTY)

  • VPIN gốc của Easley-LdP-O'Hara được calibrate trên ES — đây là sản phẩm "home turf".
  • ES: bucket V ≈ 30.000 contracts (1/50 ADV ~ 1.5M), n = 50 buckets ~ 1 phiên RTH (regular trading hours).
  • NQ tương tự ES nhưng V ≈ 12.000.
  • Vai trò lịch sử của VPIN ở US: cảnh báo Flash Crash 6/5/2010 trên ES vài giờ trước event — bài gốc của LdP-O'Hara là chứng minh empirical này.
  • Ngưỡng calibrated: trên ES, VPIN > 0.40 là watch, > 0.50 là alert. Trong 2015-2024, VPIN > 0.45 trong 2+ giờ có conditional probability ~ 30% cho |return tomorrow| > 2σ.
  • Globex extended hours: VPIN cao trong overnight session có meaning khác (ít liquidity provider) — calibrate riêng cho ETH vs RTH.

Crypto spot (BTC, ETH trên CEX major)

  • Crypto market 24/7 — không có "phiên" để align bucket. Dùng pure volume time.
  • BTC spot ADV trên Binance ~ 500.000 BTC ~ $30B. V ≈ 10.000 BTC/bucket. n = 50.
  • Khác biệt quan trọng: BVC trên crypto có thể dùng tick rule (uptick = buy, downtick = sell) trực tiếp nếu có tick data — chính xác hơn BVC. BVC dùng khi chỉ có aggregated trade data.
  • VPIN crypto thường swing rộng hơn equity (0.30-0.70) vì retail flow toxic. Cảnh báo dump: VPIN > 0.60 kèm funding rate > 0.05% / 8h trên perp.
  • Liquidation cascade prediction: VPIN spike + open interest spike + funding flip → cascade probability cao trong 4-8h tới.

Crypto perpetual futures

  • Perp có 2 nguồn flow toxicity: organic price discovery + funding rate arbitrage. Phải tách riêng.
  • BTC perp trên Binance/Bybit: V ≈ 5.000 BTC/bucket, bucket nhanh hơn spot do volume cao hơn.
  • Funding rate enhanced VPIN: signal = VPIN × |funding_rate|. Khi cả VPIN cao và funding cực đoan cùng lúc → squeeze warning rất mạnh.
  • Use case quan trọng: trước khi enter mean-reversion fade trên perp, check VPIN_perp / VPIN_spot. Nếu > 1.5 → fade rủi ro (perp đang bị informed flow drive).

Cân nhắc cross-market chung

  • Bucket size scaling: V = 1/50 ADV là rule chung, nhưng crypto có thể cần V nhỏ hơn (1/100 ADV) do volume profile tail-heavy.
  • Distribution của ΔP: Student-t df ~ 4 cho crypto thay vì normal — sửa BVC dùng t-CDF.
  • Reference vs adaptive threshold: dùng quantile lịch sử của chính market đó (e.g. 80th percentile) thay vì threshold hardcoded — mỗi market có "natural" VPIN range khác.
  • Combine với OFI: OFI fast, VPIN slow. Combo confirm signal mạnh hơn dùng riêng.

Minh họa Python

python
import numpy as np
import pandas as pd
from scipy.stats import norm

def compute_vpin(trades: pd.DataFrame,
                 bucket_volume: float,
                 window_buckets: int = 50) -> pd.DataFrame:
    """
    Tính VPIN từ tick-level trade data.

    trades: DataFrame có 2 cột tối thiểu — 'price' (giá khớp), 'volume' (số hợp đồng).
            Index là timestamp.
    bucket_volume: khối lượng mỗi bucket (e.g. 5000 contracts).
    window_buckets: số bucket trong cửa sổ tính VPIN (e.g. 50).
    """
    # Bước 1: gán bucket id cho từng trade theo cumulative volume
    cum_vol = trades['volume'].cumsum()
    trades = trades.copy()
    trades['bucket_id'] = (cum_vol // bucket_volume).astype(int)

    # Bước 2: aggregate per bucket — last price và sum volume
    bucket_df = trades.groupby('bucket_id').agg(
        ts_end=('volume', lambda x: x.index[-1]),
        last_price=('price', 'last'),
        first_price=('price', 'first'),
        bucket_vol=('volume', 'sum')
    )
    # Trả delta price của bucket
    bucket_df['delta_p'] = bucket_df['last_price'].diff()

    # Bước 3: BVC — phân loại buy/sell volume theo Z-score của delta_p
    sigma = bucket_df['delta_p'].rolling(100, min_periods=20).std()
    z = bucket_df['delta_p'] / sigma
    bucket_df['vol_buy'] = bucket_df['bucket_vol'] * norm.cdf(z)
    bucket_df['vol_sell'] = bucket_df['bucket_vol'] - bucket_df['vol_buy']
    bucket_df['imbalance'] = (bucket_df['vol_buy'] - bucket_df['vol_sell']).abs()

    # Bước 4: VPIN rolling
    bucket_df['vpin'] = (bucket_df['imbalance'].rolling(window_buckets).sum() /
                         (window_buckets * bucket_volume))

    return bucket_df[['ts_end', 'last_price', 'bucket_vol',
                      'vol_buy', 'vol_sell', 'vpin']]


def vpin_regime_filter(vpin_series: pd.Series,
                       low_q: float = 0.30,
                       high_q: float = 0.70) -> pd.Series:
    """Phân loại regime theo quantile VPIN lịch sử."""
    low = vpin_series.expanding(min_periods=200).quantile(low_q)
    high = vpin_series.expanding(min_periods=200).quantile(high_q)
    regime = pd.Series('normal', index=vpin_series.index)
    regime[vpin_series < low] = 'safe_flow'      # mean-reversion OK
    regime[vpin_series > high] = 'toxic_flow'    # tắt MR, follow trend
    return regime


# Sử dụng:
# vp_df = compute_vpin(vn30f_trades, bucket_volume=5000, window_buckets=50)
# regime = vpin_regime_filter(vp_df['vpin'])

Powered by dautu.tech