Microstructure Invariance
Kyle-Obizhaeva framework for bet sizing, impact estimation, and informed trade detection
Kyle and Obizhaeva’s microstructure invariance describes universal scaling laws connecting volume, volatility, and trade count to the “natural” bet size in any market. These model-free relationships hold across equities, futures, FX, and crypto.
API
Trading activity
Compute the market’s trading activity index, which measures how much “information” flows through the market per unit time.
activity = hz.trading_activity(
volume=1_000_000, # daily dollar volume
volatility=0.02, # daily volatility (decimal)
n_trades=5000, # number of trades per day
)
# Returns: float -- trading activity index
Invariant bet size
Given the trading activity, compute the “natural” bet size — the size at which a single trade has a standardized market impact.
bet_size = hz.invariant_bet_size(activity)
# Returns: float -- dollar size of a "natural" bet in this market
print(f"Natural bet size: ${bet_size:,.0f}")
Detecting abnormal trades
Compare observed trade sizes against the invariant bet size:
activity = hz.trading_activity(volume, volatility, n_trades)
natural_size = hz.invariant_bet_size(activity)
for trade in recent_trades:
ratio = trade.notional / natural_size
if ratio > 5.0:
print(f"Large informed bet: {ratio:.1f}x natural size at {trade.price}")
The invariance principle
The key insight: across all markets and time periods, the distribution of bets — when normalized by the invariant bet size — follows the same universal distribution. A “1x natural bet” in Apple stock and a “1x natural bet” in Bitcoin have the same proportional market impact, despite vastly different absolute sizes.
This means:
- Liquid markets have larger natural bet sizes (you can trade more before moving the price)
- Volatile markets have smaller natural bet sizes (each trade has more impact)
- Active markets (many trades) have smaller individual bet sizes (information is split across more trades)
Sizing orders using invariance
Use the invariant bet size to calibrate your order sizes to the market’s liquidity:
activity = hz.trading_activity(
volume=daily_volume,
volatility=daily_vol,
n_trades=daily_trades,
)
natural = hz.invariant_bet_size(activity)
# Size your order as a fraction of the natural bet
# 0.5x natural: low impact, patient execution
# 1.0x natural: moderate impact
# 2.0x natural: will move the market
max_order_size = 0.5 * natural
When to use
- Order sizing: determine the maximum order size that won’t significantly move the market.
- Informed trade detection: flag trades that are multiples of the natural bet size — they likely carry private information.
- Cross-market comparison: compare liquidity across markets on a normalized basis (a $10K trade in an illiquid prediction market may be equivalent to a $10M trade in SPY).
- Impact budgeting: estimate how much market impact your execution will cause before submitting.