A 2010 paper says a single variable explains two-thirds of short-term price movement. It’s right — I checked, on four years of tick data. It still won’t make you a dollar. This is the difference between a signal and an edge, measured to the cent.
The whole story in one paragraph: there’s a well-known microstructure paper — Cont, Kukanov & Stoikov, “The Price Impact of Order Book Events” — that defines a variable called Order-Flow Imbalance (OFI) and shows it explains contemporaneous price changes with an R² around 65%. I implemented it exactly, pointed it at four years of SOXL tick quotes, and reproduced the result: R² ≈ 0.67, with the sign of the effect positive on 100% of 1,000 trading days. Then I asked the obvious follow-up question the paper never asks — can you trade it? — and spent the next stretch of the project watching every version of that idea die the same death. The signal is real. The edge is eaten by the spread. Telling those two things apart, rigorously, was the entire point.
The paper
CKS define OFI from best-bid/ask quote events: every time the top of the book updates, you compute a signed contribution — buying pressure adds, selling pressure subtracts — and sum them over an interval. Their central result is that mid-price changes over an interval are a linear function of OFI over that same interval, with high explanatory power and an impact coefficient that scales inversely with market depth.
Two things about that claim matter enormously, and missing either one is how people talk themselves into losing money:
- It’s contemporaneous, not predictive. OFI explains the move that happens alongside it. It is a price-impact model — “order flow moves price” — not a claim that OFI forecasts the next interval. Reproducing the paper and finding a trade are completely different projects.
- It’s a statement about mechanism, not profit. That order flow pushes price is a fact about how markets work. It says nothing about whether you can capture the move net of the bid-ask spread.
Almost everything downstream is a consequence of taking those two sentences seriously.
The implementation
The core is the per-event OFI contribution. For consecutive top-of-book snapshots with best bid (Pᵦ, qᵦ) and best ask (Pₐ, qₐ):
bid_term = (Pb↑ or same) * qb_now − (Pb↓ or same) * qb_prev
ask_term = (Pa↓ or same) * qa_now − (Pa↑ or same) * qa_prev
e_n = bid_term − ask_term
Bid price up → you add the new bid size; bid price down → you subtract the old one; size grows at the same price → you add the delta. The ask side is symmetric and subtracted, so an ask pulling away is bullish and an ask stacking up is bearish. OFI over any window is just the sum of the per-event e_n inside it. I hand-traced a six-event sequence covering all five cases and locked it behind a unit test — if the OFI primitive is wrong, nothing built on top of it can be trusted.
The pipeline is deliberately boring, which is the point:
flowchart LR
Q["Alpaca SIP<br/>NBBO quote events"] -->|per event| E["e_n<br/>signed flow"]
E -->|sum within bar| B["1-second bars<br/>OFI + mid + spread"]
B --> F["features<br/>trailing OFI, rvol,<br/>book imbalance, targets"]
F --> T{"tests"}
OFI is computed on the event stream and then aggregated into bars — never bar-to-bar, which would throw away the very sequence information the variable is built from. Every trading day is processed independently so no event ever spans the overnight gap, and I keep only regular hours to avoid auction and thin-book artifacts. The dataset is 23.15 million one-second bars — 1,000 trading days from June 2022 to June 2026 — on SOXL, the 3× leveraged semiconductor ETF, with NVDA and the semis pulled for cross-asset work later.
Reproducing the paper
The demo is the paper’s actual claim: regress the price change over each interval on the OFI over that same interval, per day, and average over all 1,000 days.
| Bar interval | mean R² | median R² | impact β > 0 |
|---|---|---|---|
| 1-second | 0.574 | 0.590 | 100% of days |
| 10-second | 0.668 | 0.697 | 100% of days |
| 30-second | 0.670 | 0.703 | 100% of days |
That reproduces the paper. At 10–30 second intervals the R² lands at 0.67–0.70, right on top of CKS’s reported ~65%, and the impact coefficient is positive on every one of a thousand days without exception. More net buying, price up; more net selling, price down; two-thirds of the variance explained by one variable. The implementation is correct and the effect is unmistakably real.
This is the part that seduces people. You see a 67% R² on real market data and your brain screams money. It is not money. It is physics.
The predictive turn — where it stops
The paper is contemporaneous. The trade requires prediction, which is a different and much harder claim: does OFI now forecast the move next? I tested it every way I could think of.
- The forecasting signal is real but tiny. A horizon scan of forward OFI→return correlation comes back positive out-of-sample on 6 of 6 held-out days, best around 0.09–0.11 for trailing-60-second OFI predicting the next 60 seconds — and it strengthens with volatility. Real, repeatable, and an order of magnitude weaker than the contemporaneous R². Exactly what microstructure theory predicts: most of the impact is already in the price by the time you can act on the flow.
- A hidden-Markov model on OFI hits exactly 50%. A three-state Gaussian HMM on one-bar OFI — with a proper causal forward filter so no future ever leaks into a prediction — lands at 50.0% directional hit-rate at the 10-second horizon. With one feature the HMM mostly rediscovers volatility regimes, not direction. The machinery doesn’t earn its keep.
- The edge lives in the tail. Conditioning helps: the sign of trailing OFI has a hit-rate that climbs monotonically with the volatility quartile (50.4% → 55.0%), and the top decile of signal strength reaches 58.2%. So there is something — it just lives in the extreme, not on the average bar.
Real signal, confirmed from three directions. Now the only question that matters.
The cost wall
Every predictive signal, measured against the actual cost of trading it. Nothing clears the bar.
| Test | Gross | Cost | Net | Verdict |
|---|---|---|---|---|
| 60s→300s flow rule, year-scale walk-forward | +1.70 bps | 3.20 bps taker | −1.50 (t=−1.9) | dead |
| — centered (strips out bull-market long-tilt) | ~1.1 bps | 3.20 | negative | dead |
| LightGBM / logistic vs. the simple rule | 1.12 / 0.07 bps | 3.20 | negative | no model beats the rule |
Maker, touch fill (= what paper-trading shows) |
— | — | +0.73 | a mirage |
Maker, realistic queue / through fills |
— | — | −0.08 / −0.09 | breakeven ceiling |
| Vol-gated maker, frozen 2022–25 out-of-sample | — | — | −1.87 / −2.14 (t≈−3) | killed by pre-registration |
| Cross-asset NVDA/SOXX → SOXL lead-lag | +0.006 IC | — | ~0 by 2s | HFT-only |
A few of these deserve a sentence, because each is its own small lesson:
The maker mirage. Posting limit orders instead of crossing the spread looks profitable — +0.73 bps — under the zero-queue fill assumption that Alpaca’s paper-trading uses. Model the queue realistically and it collapses to breakeven: you recover the spread and adverse selection takes it right back. The unfilled orders would have been your biggest winners. Paper trading told me a comforting lie; the tick-replay told me the truth.
The pre-registration save. The vol-gated maker looked genuinely good in the discovery year — +1.55 bps per episode. I froze the exact pipeline and ran it on 2022–2025 with no retuning. It came back negative with a t-stat near −3. The in-sample number was regime luck, and the only reason I know that is that I wrote the kill criterion down before looking. Every honest result in this project has that shape.
The leveraged-ETF close. SOXL is mechanically forced to rebalance near the close, so I tested whether you can front-run it: on green days the 3:50→4:00 move really does drift up (+8.6 bps) and down on red days (−5.3), a clean IC of 0.095. But the directional hit-rate is 51.3% — barely a coin flip, and entirely a green-day effect likely contaminated by SOXL’s four-year melt-up. Gross +7 bps, spread ~4.9 bps, and no clean exit. Real fingerprint, no edge.
The latency-arbitrage autopsy. NVDA genuinely leads SOXL — same-second correlation 0.577, a small +1-second lead of 0.047, and gone by +2 seconds. A textbook stale-quote signature. So I measured a single trade on 4,678 of NVDA’s biggest one-second jumps: NVDA jumps ~5.6 bps, SOXL follows +8.08 bps in the same second — gone before I could possibly react — and only +0.51 bps the next second. The catchable move is 0.24 cents a share against a 1.62-cent spread. The prize is smaller than the toll to collect it. And colocation doesn’t save it: the fat move is sub-second, already owned by firms with microwave links and FPGAs, and the crumb that survives to a speed I can reach is below the spread. I priced the fantasy of “just get faster” to the cent, and it’s a loser.
The standing conclusion, stated as plainly as I can: retail-latency, public-tape order-flow signals on SOXL do not beat execution costs — in any configuration I tested, across four years. Taker, maker, vol-gated, cross-asset, close-rebalance, latency-arb. Gross alpha is consistently about half of cost. That’s not a bug in the implementation. It’s a correct measurement of an efficient, contested market from the inside.
What actually transfers
The negative result isn’t the valuable part — the harness is. It applies to any instrument and any signal:
- Reproduce the source claim before extending it. Getting the paper’s contemporaneous R² first is what let me be sure the later failures were economics, not a coding bug.
- Signal ≠ edge. Always measure both on the same bars. A real IC that fails cost is the default outcome in a liquid market, not the exception.
- Pre-register, then walk forward. Freeze the rule, write the kill criterion, test on untouched data. It caught regime luck twice.
- Per-day breakdown before believing any aggregate. A positive pooled number driven by three violent days is noise wearing a suit.
- Cost-at-signal, not cost-on-average. Signals fire exactly when spreads are widest. That selection effect quietly killed more than one promising rule.
The verdict
The paper is right. Order flow explains two-thirds of short-term price movement, cleanly and universally, and I can reproduce that on demand. But the move it explains is already in the price by the time the flow is visible to me, and the sliver that leaks into the future is worth less than the spread I’d pay to chase it. Everything past that is just the market pricing my own latency and cost into the quote.
Which is the honest reason the search moves on. The tradable frontier isn’t a faster or cleverer intraday signal — I proved that door is shut, six ways. It’s at a different horizon entirely, where the edge clears cost by design instead of fighting the spread: month-end rebalancing flow, the volatility risk premium, instruments too small for the fast crowd to bother with. None of them require speed — which is the one lever this whole project proved you cannot buy your way past.
Reproducing a famous paper felt like the achievement. It wasn’t. Proving there was no money in it — to the basis point, four years deep, with the tests written down in advance — was the actual work, and the only part I’d trust.