Financial Modeling
Roll’s Implied Effective Bid-Ask Spread from First-Order Price Autocovariance
Estimate hidden transaction bid-ask spreads from trade-only price tapes using Richard Roll’s (1984) microstructure formula Spread = 2 * SQRT(MAX(0, -Cov(Delta_P_t, Delta_P_{t-1}))).
How bid-ask bounce creates negative lag-1 serial covariance in trade prices
In OTC bond markets, historical daily tapes, and dark venues where Level-1 bid/ask quotes are unavailable, transaction prices P_t = M_t + (s / 2) * q_t bounce randomly between buyer-initiated prints at the ask (+s/2) and seller-initiated prints at the bid (-s/2). Even when efficient mid-quotes M_t follow a pure martingale, an uptick from bid to ask is disproportionately followed by either zero change or a downtick back to bid.
Richard Roll (1984) proved that first-order serial covariance of price changes equals Cov(Delta_P_t, Delta_P_{t-1}) = -s^2 / 4, solving directly for implied dollar spread s = 2 * SQRT(-Cov_1). In trending finite samples where positive momentum pushes empirical Cov_1 > 0, clamping MAX(0, -Cov_1) prevents imaginary square roots (#NUM!) and reports 0 implied bounce.
| Microstructure Metric | Formula | Bounce Tape [100.25, 99.75, ...] |
|---|---|---|
| Price Change Delta_P_t | B3 - B2 | [-0.50, +0.50, -0.50, +0.50, -0.50] |
| Lag-1 Serial Covariance | SUMPRODUCT((cur - mu_c)*(lag - mu_l)) / N | -0.2500 |
| Roll Dollar Spread (s) | 2 * SQRT(MAX(0, -Cov_1)) | 1.0000 ($1.00 wide) |
| Proportional Spread (bps) | (Roll_Spread / Mean_Price) * 10000 | 100.0 bps (1.00%) |
Lag-1 Autocovariance & Roll Dollar Spread Formula
Pair current changes C4:C7 against lagged changes C3:C6 inside LET, compute centered population covariance, and evaluate 2 * SQRT(MAX(0, -cov_lag1)).
=LET(cnt, COUNT(C4:C7), mu_cur, AVERAGE(C4:C7), mu_lag, AVERAGE(C3:C6), cov_lag, SUMPRODUCT((C4:C7 - mu_cur) * (C3:C6 - mu_lag)) / cnt, ROUND(2 * SQRT(MAX(0, -cov_lag)), 4))Basis-Point Effective Spread Relative to Mean Trade Price
Normalize the implied dollar spread by AVERAGE(B2:B7) and multiply by 10,000 for cross-asset liquidity comparison in basis points.
=ROUND((F3 / AVERAGE(B2:B7)) * 10000, 1)Try the example
Use the original values or change them to test your understanding.