Machine Learning · Forecasting · Financial Markets
Order-Book Imbalance as a One-Second Predictor
Abstract
A single fully-reproducible LOBSTER trading day (AAPL, 2012-06-21) used to ask one execution question end-to-end: does top-five book imbalance — together with spread and prior-second signed trade imbalance — predict the next-second mid-price direction strongly enough to survive a taker execution model.
Key results
- Held-out AUC
- 0.567 (100 ms)
- Test slice
- 57,213 snapshots
- Sample
- AAPL · 2012-06-21
- Net EV / action
- -$0.167 @ p* = 0.55
Headline
On a real LOBSTER AAPL trading day sampled at 100 ms, the full logistic specification picks up genuine one-second-ahead directional information — but the lift sits well below the venue cost it would have to clear to be deployable as a taker strategy. The numbers reported throughout this page come from the chronological 70/30 held-out slice (test ≥ 12:28:16, 57,213 observations across eight 30-minute buckets, 36 distinct spread tick values).
Held-out ROC AUC is 0.567 with a Brier score of 0.2467, and the result is essentially scale-invariant: AUC moves by less than 0.003 across 50, 100, and 250 ms snapshots. The decision rule at the primary 0.55 probability threshold and 1.0× modeled costs delivers a net expected value of −$0.048 per snapshot (−$0.167 per action across 16,584 actions, 71% no-trade share). Every cell of the cost cube reports negative_after_cost, so the signal does not survive realistic transaction costs in this single-day sample.
Methodology
The pipeline reconstructs event-time top-five book states from raw LOBSTER message + orderbook CSVs into a venue-agnostic canonical schema, samples backward on a fixed cadence grid with a 1 s staleness guard, and labels the next-second mid-price direction without any forward leakage.
Data. LOBSTER AAPL for 2012-06-21 (event file + 10-level orderbook CSVs). Features. Signed top-five depth imbalance, top-of-book spread in ticks, prior-one-second signed trade imbalance, and a 30-minute time-of-day bucket. Label. y = 1 if the mid one second ahead is strictly above the current mid; no-change ties are dropped and counted. Model. ℓ₂-regularized logistic regression (L-BFGS-B), median-imputed, compared against constant base-rate and imbalance-only baselines. Split. Chronological 70/30 (train ≤ 12:28:15, test ≥ 12:28:16). Cost overlay. Full spread crossing (α = 1) plus a 1 bp taker fee, swept over thresholds {0.50, 0.55, 0.60} and cost multipliers {0.5, 1.0, 1.5}×. The full pipeline is reproducible from raw CSVs via python -m src.cli run-all --source raw.
Data and reconstruction
The raw inputs join one event row to one orderbook row by position; the orderbook file is authoritative for top-five state after each event. The cadence sampler chooses the most recent event-time snapshot ≤ each grid timestamp via a backward as-of merge with a one-second staleness tolerance, so no feature value uses information from after t.
The session spans 09:30:00.004 – 15:59:59.913 (6.5 hours), 400,391 raw events, and 34,990 extracted trades — every one of which carries an explicit aggressor flag, so no tick-rule fallback was needed. After sampling at 100 ms, 114,426 valid one-second labels remain (49.4% positive, 50.6% negative); a further 95,902 no-change ties (45.6% of would-be labels) are dropped by construction. Quality status is pass: no crossed books, no non-monotonic levels, no non-positive sizes, and the test-slice spread distribution covers 36 distinct tick values with a 13-tick median and a 36-tick maximum.
Features and model
Three features enter the full model: top-five signed depth imbalance It(5) in [−1, +1], top-of-book spread in ticks, and a prior-one-second signed trade imbalance Tt(1s). Mid-price and spread are defined from the inside quotes, and the two imbalance features are constructed as size-normalized signed sums.
Standardized coefficients
The trade-sign feature carries the largest standardized weight, and it points the opposite direction from a naive momentum reading — recent aggressor buying is followed, on average, by a small reversal of the mid one second later, consistent with temporary price impact and partial liquidity replenishment. Depth imbalance contributes roughly half the magnitude with the expected positive sign (heavier bid depth predicts up), and spread enters with a small positive coefficient that says widest-spread snapshots weakly precede up moves.
Under feature ablation, depth imbalance alone clears chance by less than two percentage points; adding spread and trade-sign imbalance lifts AUC by another five points. The trade-sign coefficient is therefore not redundant with depth — it is doing real, decoupled work.
| Feature | Std. coef. | Reading |
|---|---|---|
trade_sign_imbalance_1s |
-0.154 | Largest magnitude; negative ⇒ short-horizon mean reversion. |
imbalance_top5 |
+0.077 | Half the magnitude of trade-sign; heavier bid depth predicts up. |
spread_ticks |
+0.042 | Small positive contribution; widest spreads weakly precede up moves. |
intercept |
-0.005 | Effectively zero — training class share is 49.4% positive. |
Discrimination
The ROC curve shows weak but real discrimination across the entire operating range, not a sharp regime. Calibration is close to the diagonal — predicted probabilities cluster tightly between 0.42 and 0.57, which is the expected shape for a small-AUC classifier on a balanced-class problem. The reliability curve at the top end (n ≈ 5,722 in the highest predicted-probability bin) hits a 62.5% realized positive rate against a 56.7% predicted rate, which is the most useful corner of the score distribution.
Stratified discrimination
On this single-day sample the predictive discrimination is mildly heterogeneous: AUC varies from 0.508 (12:00, just inside the test window) to 0.597 (15:30, the close half-hour), and is U-shaped in spread regime with Q3 (mid spreads, 11–14 ticks) dominating at 0.580. The widest-spread quintile Q5 is unremarkable, so the stratified result is more nuanced than a simple "wider spreads imply stronger predictability" story.
Cadence robustness
The signal is essentially scale-invariant on this day: AUC moves by less than 0.003 across 50, 100, and 250 ms snapshots and Brier by less than 0.0003. At 50 ms (114,232 obs) the model reports AUC 0.568 and Brier 0.2466; at the 100 ms primary cadence (57,213 obs) it reports AUC 0.567 and Brier 0.2467; at 250 ms (22,971 obs) it reports AUC 0.570 and Brier 0.2464.
This is a real robustness check rather than a sub-second artifact — at 50 ms many snapshots reuse the same event-book state because LOBSTER updates do not occur every 50 ms (the sampler back-fills), while at 250 ms each snapshot reflects more information accumulated since the previous sample. Either way, the result weakens the case for sub-100 ms snapshotting in production for this signal.
Cost-after-execution
The decision rule converts predicted probabilities into trade actions dt ∈ {−1, 0, +1} via a symmetric threshold p★. Per-action taker cost is the full spread crossed at α = 1 plus a 1 bp taker fee on notional, scaled by a stress multiplier κ ∈ {0.5, 1.0, 1.5}×. The net result rt is the realized directional return on executed snapshots minus that cost.
At the primary 0.55 / 1.0× cell, the gross edge is roughly $0.003 per action while the average per-action transaction cost is $0.177 — decomposed into ~$0.129 of spread (the dominant term, mean 12.9 ticks) and ~$0.058 of fee (1 bp on a $582 mean mid). Spread dominates fees by roughly 2.2×. To clear cost as a pure taker, the model would need a ~60× improvement in per-action edge; alternatively, a maker-rebate execution model that recovers most of the spread would change the conclusion without changing the prediction itself.
| Thr. | Mult. | Actions | No-trade | Net EV / obs | Net EV / action |
|---|---|---|---|---|---|
| 0.50 | 0.5× | 57,213 | 0% | -$0.0895 | -$0.0895 |
| 0.50 | 1.0× | 57,213 | 0% | -$0.1831 | -$0.1831 |
| 0.50 | 1.5× | 57,213 | 0% | -$0.2768 | -$0.2768 |
| 0.55 | 0.5× | 16,584 | 71% | -$0.0227 | -$0.0782 |
| 0.55 | 1.0× | 16,584 | 71% | -$0.0483 | -$0.1668 |
| 0.55 | 1.5× | 16,584 | 71% | -$0.0740 | -$0.2553 |
| 0.60 | 0.5× | 341 | 99% | -$0.0003 | -$0.0504 |
| 0.60 | 1.0× | 341 | 99% | -$0.0007 | -$0.1188 |
| 0.60 | 1.5× | 341 | 99% | -$0.0011 | -$0.1872 |
Discussion and limitations
The full specification picks up genuine one-second-ahead directional information — AUC clears chance, calibration tracks the diagonal across the [0.42, 0.57] predicted-probability range, and the coefficient ranking is robust under feature ablation. It does not survive a taker execution model: every cell of the cost cube is negative, and the widest-spread-quintile hypothesis is not borne out, with Q3 (mid spreads) dominating instead.
The result is also scoped tightly. It speaks to a single instrument (AAPL) on a single day (2012-06-21), so no cross-day or cross-sectional variance is measured. The 45.6% tie share means the 1-second forward mid often does not change at all in 2012 AAPL, and ties are dropped by construction of the binary label. The cost overlay is taker-only — there is no maker, partial-fill, or queue-rebate model, so the negative number is specifically a taker result. Depth aggregates rather than own-order rank, which means no queue-position feature enters the panel. And the trade-sign feature leans on LOBSTER's explicit aggressor flag (100% coverage on this sample); on venues where that flag is missing, a tick-rule fallback would introduce additional noise into the dominant feature.