orderflow-metrics (Python)
Dependency-free market-microstructure metrics in pure Python: Order Flow Imbalance (OFI), VPIN, information-driven bars, transaction-cost / price-impact metrics, trade-sign classification, limit-order-book reconstruction and execution scheduling. No NumPy, no pandas — just the standard library.
This is the Python port of the TypeScript
orderflow-metrics library,
with the same API surface in snake_case.
Install
pip install orderflow-metrics
Usage
from orderflow_metrics import ofi, depth_imbalance, trade_imbalance, L1Quote, Trade
quotes = [
L1Quote(bid_price=100, bid_size=5, ask_price=101, ask_size=4),
L1Quote(bid_price=100, bid_size=8, ask_price=101, ask_size=1),
L1Quote(bid_price=100.5, bid_size=2, ask_price=101, ask_size=1),
]
ofi(quotes) # 8 (net buy-side pressure)
depth_imbalance(quotes[0]) # (5 - 4) / (5 + 4) ~ 0.111
trade_imbalance([Trade(100, 2, "buy"), Trade(100, 1, "sell")]) # 0.333
Order Flow Imbalance
ofi implements the level-1 OFI of Cont, Kukanov & Stoikov (2014). OFI over a
window is the sum of per-event contributions; it counts size added to the bid
and removed from the ask (buy pressure) against the reverse, and is a strong
linear predictor of short-horizon price changes.
ofi_contribution(prev, curr)— one transitionofi_series(quotes)— per-step contributionsofi(quotes)— cumulative
VPIN
Volume-Synchronized Probability of Informed Trading (Easley, López de Prado & O'Hara, 2012). Trades are grouped into equal-volume buckets; each bucket is split into buy/sell volume by Bulk Volume Classification, and VPIN is the average absolute imbalance over a rolling window.
from orderflow_metrics import bucket_by_volume, vpin
buckets = bucket_by_volume(trades, 1_000)
vpin(buckets, window=50) # flow toxicity in [0, 1]
Execution cost & price impact
Transaction-cost analysis building blocks (buys +1, sells -1):
from orderflow_metrics import effective_spread, realized_spread, price_impact, kyle_lambda, FlowObservation
effective_spread(101, 100, "buy") # 2 — cost vs the midpoint
realized_spread(101, 100.5, "buy") # 1 — LP revenue after reversion
price_impact(100, 100.5, "buy") # 1 — permanent impact
kyle_lambda([
FlowObservation(price_change=1, signed_volume=2),
FlowObservation(price_change=-1, signed_volume=-2),
]) # 0.5 — price impact per unit signed flow
Also: effective_half_spread, roll_spread (Roll 1984).
Fair value
from orderflow_metrics import weighted_mid, relative_spread_bps, L1Quote
weighted_mid(L1Quote(100, 9, 101, 1)) # ~100.9 — heavy bid pulls toward ask
relative_spread_bps(L1Quote(99.99, 1, 100.01, 1)) # 2 (bps)
Trade-sign classification
from orderflow_metrics import tick_rule, lee_ready, PriceVsMid
tick_rule([100, 101, 101, 100]) # [0, 1, 1, -1]
lee_ready([PriceVsMid(101, 100), PriceVsMid(99, 100)]) # [1, -1]
Liquidity, volatility, efficiency
from orderflow_metrics import (
amihud_illiquidity, ReturnVolume,
realized_volatility, annualized_volatility,
variance_ratio, autocorrelation,
)
amihud_illiquidity([ReturnVolume(0.02, 100), ReturnVolume(-0.01, 50)]) # 0.0002
realized_volatility([0.03, 0.04]) # 0.05
variance_ratio(returns, 2) # <1 mean-reverting · ~1 random walk · >1 trending
autocorrelation(returns, 1) # lag-1 autocorrelation
Order book & market-order simulation
from orderflow_metrics import OrderBook, simulate_market_order
ob = OrderBook()
ob.update("bid", 100, 5)
ob.update("ask", 101, 3)
ob.mid() # 100.5
ob.imbalance(1) # 0.25 — top-of-book size imbalance
ob.update("bid", 100, 0) # size 0 removes the level
r = simulate_market_order(ob, "buy", 4)
r.avg_price # volume-weighted fill price
r.slippage_bps # cost vs mid, in basis points
r.remaining_size # > 0 if the book was too thin
OrderBook.mid(), spread(), best_bid(), best_ask() return None on an
empty side.
Information-driven bars
Sampling on activity rather than the clock — a bar every N ticks, N units of volume, or N units of traded value — gives returns with far better statistical properties (López de Prado, Advances in Financial ML, ch. 2). Build them first, then run the other metrics on the resulting series.
from orderflow_metrics import tick_bars, volume_bars, dollar_bars
tick_bars(trades, 100) # a bar per 100 trades
volume_bars(trades, 5_000) # a bar per 5,000 units of volume
dollar_bars(trades, 250_000) # a bar per $250k of traded value
Each Bar carries open/high/low/close, volume, dollar, vwap,
ticks, and signed buy_volume / sell_volume (plus start / end
timestamps when the feed provides them). Dollar bars are usually preferred.
Execution scheduling
from orderflow_metrics import twap, pov
twap(100, 4) # [25, 25, 25, 25] — even time slices
pov(30, [100, 100, 100], 0.1) # [10, 10, 10] — 10% of each interval's volume
Market impact
from orderflow_metrics import square_root_impact, almgren_chriss_cost, markout
square_root_impact(0.02, 1_000, 1_000_000) # Y·σ·√(Q/V) — empirical impact
almgren_chriss_cost(10_000, 30, 1e-6, 2e-7) # ImpactCost(permanent, temporary, total)
markout("buy", 100, 100.5) # +0.5 — price moved with the trade
square_root_impact— the empirical square-root law of impactlinear_permanent_impact/linear_temporary_impact— Almgren-Chriss termsalmgren_chriss_cost— expected TWAP cost, split into permanent vs temporarymarkout/average_markout— realized post-trade adverse-selection drift
Implementation shortfall
from orderflow_metrics import implementation_shortfall, arrival_slippage_bps
implementation_shortfall("buy", 100, 100.5, 800, 1000, 101, 5)
# ShortfallResult(execution=400, opportunity=200, fees=5, total=605)
arrival_slippage_bps("buy", 100, 100.5) # 50 bps paid up vs arrival
implementation_shortfall— Perold's execution + opportunity + fees decompositionarrival_slippage_bps— signed slippage of the fill vs the arrival price
Tests
pip install -e ".[dev]"
pytest
License
MIT © RATE LTD (TwoWayMind). See LICENSE.
Part of TwoWayMind's open microstructure tooling. Educational and technical material only — not investment advice.
Metadata
Release files for orderflow-metrics 0.29.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| orderflow_metrics-0.29.0.tar.gz | 59.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| orderflow_metrics-0.29.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 122.3 kB
Release files / orderflow_metrics-0.29.0.tar.gz
| Download URL | orderflow_metrics-0.29.0.tar.gz |
|---|---|
| Size | 59.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
185d4d0272516bc78549caa43d70e12b88a80a22d741c499c9a7aa7b04245d97
|
|
BLAKE2b-256 checksum How to use checksums |
5e473a23c988422e0b5173a14856d34bf71706540f07c4ca9bbb1923529c3c28
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / orderflow_metrics-0.29.0-py3-none-any.whl
| Download URL | orderflow_metrics-0.29.0-py3-none-any.whl |
|---|---|
| Size | 63.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bf2fdf0e7749d35300426cd32a671ea2bc296affb33a385443e9cb3eca8e3d34
|
|
BLAKE2b-256 checksum How to use checksums |
f5c7043c2b380447f5228891e84cee135a18c0e9117427149187e7074fb3b123
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency log