Historical Options Flow Replay: Trade Tape, Minute Volume & the OI Simulator | FlashAlpha

Historical Options Flow Replay: Trade Tape, Minute Volume & the OI Simulator

Most historical options products stop at end-of-day open interest and quotes. FlashAlpha replays the actual options trade tape - 4.66 billion prints back to January 2017 - as per-minute signed volume, plus an intraday open-interest simulator and the full flow analytics stack, all point-in-time with no lookahead. This is the part of the Historical API nobody knows about.

T
Tomasz Dobrowolski Quant Engineer
Jul 24, 2026
15 min read
HistoricalData OptionsFlow TradeTape OpenInterest Backtesting Quant OptionsAPI

If you have used the Historical API, you have probably read the line in the docs that says call_volume, put_volume and total_volume come back as 0. It is true, and it has caused more confusion than any other sentence we have published, because people reasonably conclude that we do not store options volume.

We do. Those fields read zero because the exposure and summary endpoints are built from the minute quote-and-greeks store, which carries bid, ask, sizes, IV and greeks but no per-bar volume column. Volume lives somewhere else entirely: in the raw trade tape, which has its own set of replay endpoints. This article is about that tape, the analytics built on it, and the intraday OI simulator that falls out of it.


The Problem With End-of-Day Open Interest

Every gamma-exposure model multiplies per-strike open interest by per-contract gamma. Open interest is published once per session, by the OCC, overnight. So when you compute GEX at 11:00 ET on Tuesday, you are using Monday's settled positions and Tuesday's greeks.

For a slow book that is fine. For 0DTE, or any session where a large position is opened and closed inside the day, it is badly wrong. The strikes that matter most for intraday hedging are frequently the ones that did not exist in size at last night's settlement.

The fix is to reconstruct what happened between settlement and now, from the prints. That is exactly what the flow layer does.


What Is Actually Stored

Two tape tables, both partitioned by day, both replayed point-in-time.

TapePrintsRangePer-row fields
Options4.66 billion2017-01-03 → presenttimestamp (millisecond), expiry, strike, right (C/P), price, size, bid at trade, ask at trade, side, source
Underlying8.2 billion2017-01-03 → presenttimestamp, price, size, bid at trade, ask at trade, side, source

The side tag is the same buy / sell / mid classification the live ingest pipeline applies, derived from where the print landed against the prevailing bid and ask. Replay runs the identical classifier, so a historical bucket and a live bucket are computed the same way rather than approximated.

Per-symbol print counts on the options tape:

SymbolPrintsSymbolPrintsSymbolPrints
SPY1.30 BIWM140 MTLT32.6 M
SPXW815 MMSFT114 MXSP20.7 M
TSLA593 MNFLX95.4 MGOOG18.5 M
QQQ533 MGOOGL67.6 MRUT7.0 M
NVDA389 MSPX45.4 MVIX0.25 M
AAPL296 MAMZN182 M

Tape coverage is narrower than analytics coverage. A symbol can have full minute-level quotes and greeks going back to 2017 and still have no tape, so check /v1/tickers before you plan a study around it.


The Endpoints

All of these take the same required at parameter as the rest of the Historical API, and all return the same JSON shape as their live counterparts.

EndpointWhat you get
/v1/flow/options/{symbol}/history?at=&minutes=NPer-minute buckets: buy, sell, mid and net volume, trade count, biggest trade, VWAP, high, low
/v1/flow/options/{symbol}/cumulative?at=&minutes=NRunning cumulative net volume through the session
/v1/flow/options/{symbol}/summary?at=Day-to-date totals as of that minute
/v1/flow/options/{symbol}/recent?at=&limit=Individual prints, newest first, each with expiry, strike, right, size, side
/v1/flow/options/{symbol}/blocks?at=&minSize=The same, filtered to prints at or above a size threshold
/v1/flow/stocks/{symbol}/…Identical five endpoints against the underlying's own tape
/v1/flow/options/{leaderboard,outliers}?at=Cross-symbol roll-up: who was being bought and sold hardest in that window
/v1/flow/oi/{symbol}?at=The OI simulator. Official, simulated and effective OI, plus intraday delta and a confidence score
/v1/flow/live/{symbol}?at=Flow-adjusted GEX, gamma flip, call wall, put wall, max pain, pin risk, dealer risk
/v1/flow/{gex,dex,levels,pin-risk,dealer-risk,summary,signals}/{symbol}?at=Flow-adjusted exposure and level analytics

A Real Minute

15:30 ET on 15 June 2020, five minutes of SPY option tape:

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://historical.flashalpha.com/v1/flow/options/SPY/history?at=2020-06-15T15:30:00&minutes=5"
{"symbol":"SPY","minutes":5,"count":5,"buckets":[
 {"ts":"2020-06-15T19:25:00","buyVolume":3288,"sellVolume":5991,"midVolume":2409,"netVolume":-2703,"tradeCount":1154,"biggestTrade":833,"vwap":2.27},
 {"ts":"2020-06-15T19:26:00","buyVolume":5752,"sellVolume":5427,"midVolume":2865,"netVolume":325,"tradeCount":1275,"biggestTrade":449,"vwap":2.80},
 {"ts":"2020-06-15T19:27:00","buyVolume":8533,"sellVolume":8549,"midVolume":3893,"netVolume":-16,"tradeCount":1900,"biggestTrade":600,"vwap":2.16},
 {"ts":"2020-06-15T19:28:00","buyVolume":9763,"sellVolume":5432,"midVolume":2124,"netVolume":4331,"tradeCount":1493,"biggestTrade":500,"vwap":2.00},
 {"ts":"2020-06-15T19:29:00","buyVolume":6319,"sellVolume":6897,"midVolume":2297,"netVolume":-578,"tradeCount":1361,"biggestTrade":400,"vwap":2.19}]}

Roughly 1,400 prints per minute, signed. The day-to-date summary at the same instant: 580,620 trades across 5,496 distinct contracts, 2,367,003 bought against 2,397,798 sold, 1,286,736 unclassifiable at the mid, net −30,795 contracts, largest single print 9,632 lots.

Bucket timestamps are UTC

The at parameter is ET wall-clock, but tape bucket timestamps come back in UTC. A 15:30 ET request returns buckets labelled 19:25 to 19:29. The analytics endpoints echo as_of in ET. Do not assume one convention across the whole API.


The OI Simulator

The tape is the input; the simulator is what most people actually want. It answers "what is open interest right now, mid-session" rather than "what was it at last night's settlement".

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://historical.flashalpha.com/v1/flow/oi/SPY?at=2020-06-15T15:30:00"
{"symbol":"SPY","as_of":"2020-06-15T19:30:00Z","expiry":null,
 "official_oi":26562722,"simulated_oi":26549508,"intraday_oi_delta":-13214,
 "oi_delta_confidence":0.43,"effective_oi":26562952,
 "contracts_total":10390,"contracts_with_flow":3453}
FieldMeaning
official_oiSettled open interest carried into the session
intraday_oi_deltaNet opening minus closing interest inferred from prints since the open
simulated_oiSettled OI walked forward by the tape
effective_oiThe blended figure the flow-adjusted analytics use
oi_delta_confidenceHow much of the day's volume the classifier could attribute with confidence
contracts_with_flowContracts that actually printed, against contracts_total listed

Mechanically: a per-minute snapshot is materialised by replaying the tape through the same side classifier and OI-delta estimator the live ingest uses, then any residual sub-minute prints between the minute floor and your exact at are applied on top. Replay and live therefore agree at the sub-minute boundary rather than drifting apart.

Feed that into /v1/flow/summary and you get the dealer-facing read at the same instant:

{"symbol":"SPY","underlying_price":307.025,"flow_direction":"amplifying",
 "intraday_oi_delta":-13214,"contracts_with_flow":3453,
 "live_gex":85103261.19,"flow_gex_pct_shift":1.37}

flow_gex_pct_shift is the number to watch: how far the day's flow has moved gamma exposure away from the settled-OI picture that every EOD-based GEX model is still showing.


Why This Is Leak-Free

Flow data is where lookahead bias is easiest to introduce and hardest to spot, so the controls are worth stating explicitly.

  1. Every tape and OI read is bounded ts <= at. There is no branch in the query layer that can see past the requested instant.
  2. Settled OI is start-of-day, not end-of-day. The open interest stamped on a date is the interest resulting from the previous session's settlement, so using it at 10:00 that morning is not cheating. You can verify this yourself on any newly listed contract: SPY 310 call expiring 2020-06-24 first printed on 2020-05-19 with volume 6 and open interest 0, then showed OI 5 the following session. Interest always trails volume by one day.
  3. Sub-minute residuals are replayed, not interpolated. Asking for 10:30:17 gives you the 10:30 snapshot plus the prints up to second 17, not the whole 10:30 bar.
  4. No wall-clock reads exist in the replay code. A source-level test fails the build if any file in the replay namespace references the system clock. The only clock is injected, which is what makes a replay reproducible.

Known Gaps

Things we would rather you read here than discover in week three of a research project.

  • Minute buckets are not split by call and put yet. Every print carries its right, and /recent and /blocks expose it, but the per-minute aggregate does not currently break out call volume from put volume. Reconstructing it means pulling raw prints, which is impractical at scale - SPY alone printed 580,620 times in the session above. A right= filter on the bucket endpoints is on the roadmap; if you need it, say so and it moves up.
  • Side classification is inferred, not exchange-supplied. It comes from where the print landed against the prevailing quote. midVolume is the unclassifiable residue and it is not small - roughly a quarter of volume in the example above. Treat netVolume as a strong signal, not ground truth.
  • official_oi returns 0 on the first trading day of each calendar year. A year-boundary gap in the settled-OI baseline. 2023-12-29 is fine, 2024-01-02 is zero, 2024-01-03 is fine. It affects one session per year and is queued for a fix; drop those sessions in the meantime.
  • Tape coverage lags live by days to weeks, per symbol. Hydration runs symbol by symbol and the largest names trail furthest. Front-fill recent sessions from the live API, not the historical host, and expect an overlap seam.
  • Analytics coverage does not imply flow coverage. /v1/tickers reports has_flow separately, and it refers to the simulator layer specifically - a symbol can have raw tape without the flow analytics being hydrated on top of it.

What You Can Build With It

  • Effective-OI gamma models. Recompute GEX against effective_oi instead of settled OI and measure whether the intraday correction improves your hedging-pressure signal. flow_gex_pct_shift tells you when the correction is large enough to matter.
  • Signed-volume momentum. Per-minute netVolume on the option tape against forward underlying returns, conditioned on the gamma regime from the exposure endpoints.
  • Block detection with survivorship intact. /blocks at a size threshold, replayed across years, gives you a clean study of what large prints preceded - without the survivorship bias of a curated "unusual activity" feed.
  • Cross-asset lead-lag. The underlying tape and the option tape share a clock, so you can measure whether option flow leads or follows the stock at minute resolution.
  • Cross-sectional heat. /v1/flow/options/leaderboard replayed daily gives a point-in-time ranking of which underlyings were absorbing the most directional option flow.
Historical API · Alpha tier · from $1,199/mo
Replay the options tape at any minute since 2017
Same response shape as live, leak-free by construction, 4.66 billion option prints and an intraday OI simulator on top.
View pricing →
Data freshness: tape hydration runs per symbol and lags live by days to weeks. Live coverage status at /v1/tickers.

Related Reading

Upgrade to Alpha API Spec

The tape has been there since January 2017 and the replay endpoints have been live for months; what was missing was anyone telling you. If your research needs intraday open interest, signed option volume, or dealer positioning that reflects what traded today rather than what settled last night, that is the flow layer, and it replays at minute resolution with the same no-lookahead guarantees as the rest of the Historical API.

Live Market Pulse

Get fast visibility into market shifts with full-chain analytics over low-latency REST and MCP polling.

Intelligent Screening

Screen millions of option pairs per second using your custom EV rules, filters, and setups.

Export-Ready

Export structured signals to your own execution stack or broker integration - FlashAlpha delivers the analytics, you keep control of order routing.

Join the Community

Discord

Engage in real time conversations with us!

Twitter / X

Follow us for real-time updates and insights!

GitHub

Explore our open-source SDK, examples, and analytics resources!