Markets: A Rigorous Course

5.2 The Roll model: spread from bid–ask bounce

Core about 15 min

Motivation

Trades alternate between the bid and the ask. That alternation makes trade-price changes negatively autocorrelated even when the underlying value is a random walk. Roll (1984) turned this into an estimator of the spread that needs only trade prices. It is the first thing to compute when someone shows you a mean-reversion strategy on tick or minute data: much of the "reversion" may be bounce.

5.2.1The bid–ask bounce model#

Setup

Let the efficient price (the expected value of the asset given public information) follow a random walk, and trades occur at the bid or the ask:

mt=mt−1+εt,pt=mt+s2 qt,(5.2)m_t = m_{t-1} + \varepsilon_t, \qquad p_t = m_t + \tfrac{s}{2}\, q_t, \tag{5.2}

with assumptions:

  • (A1) εt\varepsilon_t i.i.d., mean 0, variance σ2\sigma^2;
  • (A2) qt∈{−1,+1}q_t \in \{-1, +1\} i.i.d. with P(qt=1)=1/2P(q_t = 1) = 1/2;
  • (A3) qq and ε\varepsilon are independent at all leads and lags.

The spread ss is constant; the dealer's quotes are mt±s/2m_t \pm s/2.

Proposition 5.1Roll, 1984

Under (A1)–(A3), with Δpt=pt−pt−1\Delta p_t = p_t - p_{t-1},

Var⁡(Δpt)=σ2+s22,Cov⁡(Δpt,Δpt−1)=−s24,Cov⁡(Δpt,Δpt−k)=0    (k≥2).(5.3)\begin{gathered} \operatorname{Var}(\Delta p_t) = \sigma^2 + \frac{s^2}{2}, \qquad \operatorname{Cov}(\Delta p_t, \Delta p_{t-1}) = -\frac{s^2}{4}, \\ \operatorname{Cov}(\Delta p_t, \Delta p_{t-k}) = 0 \;\; (k \ge 2). \end{gathered} \tag{5.3}

Hence s=2−Cov⁡(Δpt,Δpt−1)s = 2\sqrt{-\operatorname{Cov}(\Delta p_t, \Delta p_{t-1})}, and the Roll estimator is

s^=2−γ^1,γ^1=sample first-order autocovariance of Δp.(5.4)\hat s = 2\sqrt{-\hat\gamma_1}, \qquad \hat\gamma_1 = \text{sample first-order autocovariance of } \Delta p. \tag{5.4}
Proof

From (5.2), Δpt=εt+s2(qt−qt−1)\Delta p_t = \varepsilon_t + \tfrac{s}{2}(q_t - q_{t-1}). Under (A2), Eqt=0E q_t = 0 and Var⁡(qt)=1\operatorname{Var}(q_t) = 1, and the qq's are uncorrelated across time. By (A3) the ε\varepsilon and qq terms are uncorrelated, so covariances add:

Var⁡(Δpt)=σ2+s24Var⁡(qt−qt−1)=σ2+s24⋅2=σ2+s22.\operatorname{Var}(\Delta p_t) = \sigma^2 + \frac{s^2}{4}\operatorname{Var}(q_t - q_{t-1}) = \sigma^2 + \frac{s^2}{4}\cdot 2 = \sigma^2 + \frac{s^2}{2}.

Cov⁡(Δpt,Δpt−1)=Cov⁡(εt,εt−1)+s24Cov⁡(qt−qt−1, qt−1−qt−2)\operatorname{Cov}(\Delta p_t, \Delta p_{t-1}) = \operatorname{Cov}(\varepsilon_t, \varepsilon_{t-1}) + \frac{s^2}{4}\operatorname{Cov}(q_t - q_{t-1},\, q_{t-1} - q_{t-2}). The first term is 0 by (A1). Expanding the second, Cov⁡(qt,qt−1)−Cov⁡(qt,qt−2)−Var⁡(qt−1)+Cov⁡(qt−1,qt−2)=0−0−1+0=−1\operatorname{Cov}(q_t, q_{t-1}) - \operatorname{Cov}(q_t, q_{t-2}) - \operatorname{Var}(q_{t-1}) + \operatorname{Cov}(q_{t-1}, q_{t-2}) = 0 - 0 - 1 + 0 = -1. So Cov⁡=−s2/4\operatorname{Cov} = -s^2/4.

For k≥2k \ge 2, Δpt\Delta p_t involves εt,qt,qt−1\varepsilon_t, q_t, q_{t-1} and Δpt−k\Delta p_{t-k} involves εt−k,qt−k,qt−k−1\varepsilon_{t-k}, q_{t-k}, q_{t-k-1}, which share no index when k≥2k \ge 2, so the covariance is 0.∎

The first-order autocorrelation of trade-price changes is ρ1=−s2/4σ2+s2/2\rho_1 = -\frac{s^2/4}{\sigma^2 + s^2/2}, which lies in (−12,0)(-\tfrac12, 0); it is close to −12-\tfrac12 when the spread dominates the efficient-price noise, which is the typical situation at the tick level.

5.2.2Estimating the spread from trades#

Worked example

On one day, an NSE large-cap trading near ₹1,500 has 30,000 trades. The sample first-order autocovariance of trade-to-trade price changes is γ^1=−0.0009\hat\gamma_1 = -0.0009 (₹²). Then s^=20.0009=₹0.06\hat s = 2\sqrt{0.0009} = \text{₹}0.06, i.e. 0.4 bp of price. This is the effective spread implied by bounce, which can differ from the quoted spread (queue position and hidden orders mean many trades occur inside the quote).

Code Exercise m05_roll (in the app: Exercises → m05_roll) asks you to simulate (5.2), implement (5.4), and check that s^\hat s recovers the true ss within a few percent on 300,000 simulated trades. A second test adds a proportional bounce to a GARCH, fat-tailed log-price path from toolkit.data.synthetic_prices and recovers a 100 bp spread from 20,000 observations within 20%. Problem 5.2 extends the model to persistent order flow, where the estimator is biased down.

5.2.3Limits and strategy hygiene#

Practitioner notes

  • When the estimator fails. If γ^1>0\hat\gamma_1 > 0 the estimator is undefined. This happens often in daily data, where the bounce is small relative to σ\sigma and returns may have small positive autocorrelation from slow information diffusion. Use Roll on tick or one-minute data, or use Hasbrouck's Bayesian version (Hasbrouck 2007, Ch. 3).
  • Order-flow persistence. Real order flow is positively autocorrelated (large orders are split; M05 · 5.5), violating (A2). With Corr⁡(qt,qt−1)=ρ\operatorname{Corr}(q_t, q_{t-1}) = \rho and geometric decay, the autocovariance becomes −s24(1−ρ)2-\frac{s^2}{4}(1-\rho)^2 (Problem 5.2), so Roll underestimates ss by the factor (1−ρ)(1 - \rho).
  • Adverse selection. If trades carry information (the next sections), mtm_t moves in the direction of qtq_t, violating (A3); Roll then measures only part of the effective spread (Problem 5.3).
  • Strategy hygiene. A "mean-reversion" backtest on trade prices that buys after down-ticks and sells after up-ticks earns the bounce on paper but pays it in reality: you buy at the ask, not at the last trade. Always backtest intraday strategies on bid and ask, or on mids plus a spread.

Create a free account

Reading is open to everyone. An account keeps your progress, answers, notes and code drafts, and gives you the study plan, the journals and the simulator. Running code needs an account approved for it.