← Blog/blog/order-flow-imbalance

Order flow imbalance, read closely

01

Where does a price come from, second to second?

Ask what a stock is “worth” and you reach for earnings, discount rates, the news. But zoom into a few seconds and none of that has moved. What moves is the limit order book: the live ladder of resting buy orders (bids) and sell orders (asks). The highest bid and the lowest ask are the best quotes; their average is the mid-price, and the gap between them is the spread. Every trade and every cancellation nudges those queues, and the mid-price with them.

So the microstructure question is mechanical, not philosophical: which nudges move the price, and by how much? The naive guess is trade volume — big prints move markets. Cont, Kukanov & Stoikov (2014) showed the better answer is order-flow imbalance: the net of demand added versus supply added at the top of the book. A market buy that eats the ask matters, yes — but so does a trader silently cancelling a big bid, which prints no trade at all yet removes support and drags the mid down. OFI counts both on the same signed scale.

02

OFI in one function

The definition is refreshingly concrete. Look at one book level between two consecutive snapshots and ask what happened to each side. On the bid (demand) side: if the best bid price rose, someone posted fresh demand of size q, so count +q; if it fell, demand was pulled, count −q; if the price held, only the change in resting size counts, Δq. The ask (supply) side is the mirror image — supply withdrawn pushes the price up, supply added pushes it down — and OFI is the bid contribution plus the (sign-flipped) ask contribution, so a positive number means net upward pressure.

def level_ofi(prev, curr):
    # Cont-Cucuringu-Zhang, eq. 2-4: net order flow at ONE book level between
    # two consecutive states. Bid side is demand, ask side is supply; a price
    # move is treated as a full-size replacement.
    if   curr.bid_p > prev.bid_p:  bid =  curr.bid_q            # new demand posted
    elif curr.bid_p < prev.bid_p:  bid = -curr.bid_q            # demand pulled
    else:                          bid =  curr.bid_q - prev.bid_q   # queue grew/shrank

    if   curr.ask_p > prev.ask_p:  ask =  curr.ask_q            # supply withdrawn -> up
    elif curr.ask_p < prev.ask_p:  ask = -curr.ask_q            # supply added -> down
    else:                          ask =  prev.ask_q - curr.ask_q   # queue grew/shrank

    return bid + ask               # > 0 means net upward pressure

That is the whole primitive. Sum level_ofi over every book update inside an interval and you have the interval's OFI. The site runs the TypeScript above; the Python and C++ are line-for-line translations. Every OFI number in the charts below is produced by this function from generated book states — no shortcuts, in keeping with the site's formula = code rule.

03

The impact law is a straight line

Here is the paper's core claim, tested on a seeded synthetic book (a latent supply/demand pressure drives both the mid-price and the order flow; details in the module). We regress each interval's mid-price change on its best-level OFI — the exact univariate fit the linear-regression page performs — and bin the cloud so the shape is legible. A point forecast is silent about noise; a binned average is not.

observed bin meanfitted line α + β·OFI
Fig 1. Mean mid-price change within each best-level-OFI bin (indigo), against the fitted line Δmid = α + β·OFI (green). The relationship is essentially straight: more net buying pressure, proportionally more upward move. A single regressor already captures 63.7% of the variance (in-sample R²).
04

Depth sets the slope

If impact is order flow divided by depth, then doubling the depth should roughly halve the slope. We re-run the same fit across a grid of book depths and read off β. The slope falls like 1/D, and the product β·D — the depth-normalised impact — stays almost flat, which is exactly why the paper normalises OFI by average book depth before comparing names across stocks.

impact slope ββ · D (depth-normalised)
Fig 2. Impact slope β (indigo) versus book depth D, and the product β·D (grey). The slope decays like 1/D — a thin book moves more per order — while β·D is roughly constant (~0.71), the invariant the paper actually models.
05

The whole book beats the best quote

Best-level OFI only watches the top of the book. But depth lives behind the best quote, and the paper's central construction is to fold the top M = 10 levels into one integrated OFI. Naively stacking ten correlated OFIs into a regression invites multicollinearity; instead they take the first principal component — the single direction along which the level-OFIs move together — and project onto it. PCA (principal component analysis) is just the eigenvector of the covariance matrix with the largest eigenvalue; here we recover it with a few rounds of power iteration, no linear-algebra library.

def integrated_ofi(ofi):                 # ofi: T intervals x M levels
    z = standardize_columns(ofi)         # each level -> mean 0, variance 1
    C = (z.T @ z) / len(z)               # M x M correlation matrix
    w = power_iteration(C)               # leading eigenvector = first PC
    if w.sum() < 0: w = -w               # orient the weights positive
    w = w / abs(w).sum()                 # L1-normalise (paper's convention)
    return z @ w                         # ONE integrated number per interval

Swapping best-level OFI for integrated OFI lifts the explained variance from 63.7% to 82.0% on our seeded book — the deeper queues carry real information about where the mid is going. The paper's own numbers, on 2019 Nasdaq equities, are stronger still and move the same way:

Fig 3. Contemporaneous R² on the seeded book: best-level OFI versus integrated OFI. Adding the depth behind the best quote is worth +18.4 points of explained variance here.
regressorin-sample R²out-of-sample R²
best-level OFI71.16%64.64%
integrated OFI (top 10)87.14%83.83%
The paper's reported price-impact R² (Cont, Cucuringu & Zhang 2023, contemporaneous regressions). Integrated OFI, built from the first principal component of the top ten levels, captures over four-fifths of the second-by-second move out-of-sample. Our seeded reproduction lands lower in level but shows the same ordering and gap.
06

The thing a skim misses

An R² of 82.0% on returns is the kind of number that makes a quant sit up — until you read which returns. This is a contemporaneous regression: OFI measured over the same interval as the price move it explains. It is a statement about price impact — how order flow and price move together — not a forecast. To trade it you would need OFI now to predict the price move next. So we re-run the winning integrated-OFI fit, but line up each interval's OFI against the following interval's return, and score it honestly out-of-sample.

Fig 4. Out-of-sample R² of the very same integrated-OFI regression, contemporaneous versus one-step-ahead. Explaining the current move: 81.9%. Forecasting the next: -12 basis points — statistically indistinguishable from zero, and here faintly negative, meaning it underperforms simply guessing the mean.

There is a second, subtler catch worth naming. The paper's multi-asset headline is that cross-impact — one stock's order flow moving another's price — adds nothing to contemporaneous impact once you use integrated OFI: a sparse, own-asset model does just as well. Cross-impact sounds like the exciting part, and in thepredictive direction it carries a flicker of short-lived signal; but for explaining the here-and-now, your own book is the whole story. Self-impact dominates.

07

What I'd probe next

  • Does the flicker survive costs? The lagged cross-impact the paper finds decays in seconds. Netting it against the spread and fees is the honest test of whether the predictive residual is tradeable or just visible.
  • Non-linear impact. Our fit is a straight line and the paper's is too, but large flow is known to move price concavely (the square-root law). A boosted tree on OFI would bend where OLS cannot — and let you see the curvature directly.
  • Where the deep-learning alpha actually lives. Kolm, Turiel & Westray (2023) push OFI features through neural nets across horizons and find the edge is in thefeatures, not the model — a plain linear map on OFI recovers most of it. That echoes this site's tabular theme: get the representation right and the model gets simple.

The regression at the heart of all of this is the plainest one there is — a line through a cloud, fit by least squares. Go turn the knobs on the linear-regression page and picture the x-axis as order flow and the y-axis as the next tick. OFI is a genuinely beautiful result: the microscopic mechanics of a price, captured in one signed number. Just don't mistake the ruler for a telescope.

References

  1. Cont, R., Cucuringu, M., & Zhang, C. (2023). Cross-Impact of Order Flow Imbalance in Equity Markets. Quantitative Finance 23(10), 1373–1393
  2. Cont, R., Kukanov, A., & Stoikov, S. (2014). The Price Impact of Order Book Events. Journal of Financial Econometrics 12(1), 47–88
  3. Kyle, A. S. (1985). Continuous Auctions and Insider Trading. Econometrica 53(6), 1315–1335
  4. Kolm, P. N., Turiel, J., & Westray, N. (2023). Deep Order Flow Imbalance: Extracting Alpha at Multiple Horizons from the LOB. Mathematical Finance 33(4), 1044–1081