Strasmore Research
Learn Matt ConnorBy Matt Connor

Does OPRA Have Depth of Book? Feed Explained

Does OPRA have depth of book? No, and here is what the options feed does carry, plus how options traders actually find size resting at a given strike.

Does OPRA have depth of book? No. The Options Price Reporting Authority carries two things a trader cares about: each US options exchange's best bid and best offer for every listed contract, and every trade print. Administrative messages ride alongside, marking halts and contract adjustments. Orders resting behind a venue's own best quote never travel on it, so anyone looking for a ladder of size at a strike is reading the wrong feed.

Does OPRA have depth of book? What the feed carries

OPRA is the consolidated tape for US listed options. A consolidated tape is one feed that merges what every exchange in a single asset class publishes, which is why an options quote looks much the same whichever broker renders it. Per contract, per exchange, the feed carries one bid price with its size and one offer price with its size. That shape is top of book, the options cousin of the equity quote described in level 1 versus level 2 market data.

Depth of book is the measurement one step down: the orders resting behind the best price. A depth feed publishes the second-best bid with its size, then the third, and onward, for one venue's own book. The OPRA message set has no field for a second price level. The best bid and offer across every venue, the NBBO, is computed from those per-venue tops, and it is still a single level.

Why the depth of book confusion is reasonable

More than a dozen exchanges list US options as of September 2026. Each publishes its own top of book for the same contract, so one contract generates many quotes at many prices, each with a size attached. Stack them and the output reads like a ladder. The panel below counts the venues that printed trades in five household names on a single pinned session, September 16, 2026.

QueryOptions trade prints by exchange count, five household names (Sep 16, 2026)
symbolvenues_printingbusiest_venue_share_pct
NVDA1813.7
AAPL1815.1
MSFT1816.9
SPY1817
KO1817.3
The exact SQL behind every number
WITH per_venue AS
(
    SELECT
        underlying_symbol AS symbol,
        exchange,
        count()           AS prints
    FROM global_markets.options_trades
    WHERE underlying_symbol IN ('AAPL', 'MSFT', 'NVDA', 'SPY', 'KO')
      AND sip_timestamp >= '2026-09-16 00:00:00'
      AND sip_timestamp <  '2026-09-17 00:00:00'
    GROUP BY symbol, exchange
)
SELECT
    symbol,
    count()                                   AS venues_printing,
    round(100 * max(prints) / sum(prints), 1) AS busiest_venue_share_pct
FROM per_venue
GROUP BY symbol
ORDER BY venues_printing DESC, busiest_venue_share_pct ASC
Run this yourself

Prints in NVDA landed on 18 separate options exchanges that day, and the busiest of them took 13.7% of that name's prints. The name with the fewest venues in the group, KO, still touched 18. Width across venues is a different property from depth inside one. A stack of per-venue bests tells you how much size sits at the front of each venue's queue, and nothing about what waits behind it.

What a stitched composite really shows

The next panel pins one minute, 11:00 a.m. ET on that session, for the AAPL contract with the most traded volume that day. One row per exchange quoting it, with the size each one was displaying.

QueryOne contract, one minute: displayed size at each exchange's best quote
venuebid_contractsask_contractsspread_cents
exch 320100312
exch 31570422
exch 32255312
exch 31345252
exch 31642392
exch 32511311
exch 3005371
exch 3022921
The exact SQL behind every number
WITH busiest AS
(
    SELECT ticker
    FROM global_markets.options_trades
    WHERE underlying_symbol = 'AAPL'
      AND sip_timestamp >= '2026-09-16 00:00:00'
      AND sip_timestamp <  '2026-09-17 00:00:00'
    GROUP BY ticker
    ORDER BY sum(size) DESC
    LIMIT 1
)
SELECT
    concat('exch ', toString(bid_exchange))               AS venue,
    toUInt32(argMax(bid_size, sip_timestamp))             AS bid_contracts,
    toUInt32(argMax(ask_size, sip_timestamp))             AS ask_contracts,
    round(100 * (toFloat64(argMax(ask_price, sip_timestamp))
               - toFloat64(argMax(bid_price, sip_timestamp))), 1) AS spread_cents
FROM global_markets.cache_options_quotes
WHERE ticker IN (SELECT ticker FROM busiest)
  AND sip_timestamp >= '2026-09-16 15:00:00'
  AND sip_timestamp <  '2026-09-16 15:01:00'
GROUP BY bid_exchange
HAVING argMax(bid_price, sip_timestamp) > 0
   AND argMax(ask_price, sip_timestamp) > 0
   AND argMax(bid_size, sip_timestamp) > 0
ORDER BY bid_contracts DESC, spread_cents ASC
Run this yourself

8 venues held a two-sided quote in that contract inside the minute. The largest displayed bid at any single venue was 100 contracts, quoted 2 cents wide. Summing the bid sizes across venues gives the total displayed size at the front of the market. A venue's own book would add rows underneath that, at worse prices, with sizes of their own. This panel is the ceiling of what a top-of-book tape can give you, and a vendor options ladder is often this same stack of tops presented as levels.

Full options depth is a bandwidth problem

The missing depth is arithmetic before it is policy. Start with how wide the quoted surface already is.

QueryContracts in the chain versus contracts that traded (Sep 16, 2026)
symbolcontracts_in_chaincontracts_traded
SPY56165616
QQQ45224522
MU40764076
AMD30253025
META28912891
GLD28452845
SNDK23772377
TSLA23712371
USO20692069
SOXL19721972
NVDA19591959
IWM18971897
The exact SQL behind every number
SELECT
    underlying_symbol                   AS symbol,
    countDistinct(ticker)               AS contracts_in_chain,
    countDistinctIf(ticker, volume > 0) AS contracts_traded
FROM global_markets.options_greeks
WHERE date = '2026-09-16'
  AND underlying_symbol NOT IN ('SPCX')
GROUP BY symbol
ORDER BY contracts_in_chain DESC
LIMIT 12
Run this yourself

On that session, SPY carried 5616 distinct option contracts, of which 5616 recorded any volume at all. Every contract in a chain can be quoted by every exchange, and each quote updates whenever the underlying ticks or a venue's order flow changes. Trading activity across the day sits in a narrow slice of that surface.

QueryDistinct AAPL option contracts trading, by hour of the session
et_hourcontracts_trading
09:00827
10:00922
11:00811
12:00747
13:00677
14:00855
15:00858
16:002
The exact SQL behind every number
SELECT
    formatDateTime(toTimeZone(window_start, 'America/New_York'), '%H:00') AS et_hour,
    countDistinct(ticker)                                                 AS contracts_trading
FROM global_markets.options_minute_aggs
WHERE ticker LIKE 'O:AAPL2%'
  AND window_start >= '2026-09-16 00:00:00'
  AND window_start <  '2026-09-17 00:00:00'
GROUP BY et_hour
ORDER BY et_hour
Run this yourself

Across 8 clock hours with prints, the count of distinct AAPL contracts trading runs from 827 in the 09:00 hour to 2 in the 16:00 hour. Quoting covers the whole chain regardless, traded or not.

Now multiply. One price level per side per venue is the single-level case, and the byte accounting for it is laid out in how big the options quote feed gets. A depth feed multiplies that by however many levels each venue chose to publish, for every contract in every chain, with no requirement that any of them trade. The consolidated tape stops at the top of each book where bandwidth, not permission, puts the wall.

Volume at a strike versus size at a strike

A chain's volume curve is the figure most often mistaken for depth. The panel below spreads one expiry's traded volume across its strikes.

QueryTraded volume across strikes, one AAPL expiry (Sep 16, 2026)
55 rows (showing 20)
strike_pricecall_volumeput_volume
150060
1600234
17004
18002
18505
19501
200410
20501
210012
21506
220578
2251604
230617
23510112
2401071
24502
25011263
255405
260538
2651102
The exact SQL behind every number
WITH busiest_expiry AS
(
    SELECT expiration_date
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'AAPL'
      AND date = '2026-09-16'
      AND days_to_expiry BETWEEN 20 AND 45
      AND volume > 0
    GROUP BY expiration_date
    ORDER BY sum(volume) DESC
    LIMIT 1
)
SELECT
    round(toFloat64(strike_price), 2)                            AS strike_price,
    sumIf(volume, startsWith(lower(toString(option_type)), 'c')) AS call_volume,
    sumIf(volume, startsWith(lower(toString(option_type)), 'p')) AS put_volume
FROM global_markets.options_greeks
WHERE underlying_symbol = 'AAPL'
  AND date = '2026-09-16'
  AND expiration_date IN (SELECT expiration_date FROM busiest_expiry)
  AND volume > 0
GROUP BY strike_price
ORDER BY strike_price
Run this yourself

55 strikes recorded volume on that expiry, running from $150 up to $470. Read the curve to see where the session's activity sat across the chain. Volume counts contracts that changed hands over a whole day, at prices long gone. Size available at a strike right now is a separate measurement, and only a quote feed carries it.

How to get real size at a strike

Four practical routes, in rough order of cost.

  • Stitch the per-exchange quotes yourself. Pull each venue's bid and offer with sizes for the contract in question and sort by price, which is what the composite panel above does. You get one level per venue, timestamped.
  • License one exchange's own depth product. Options exchanges sell direct feeds from their matching engines, and several publish price-level depth for their own book. That gives you one venue's ladder rather than the market's, and the tradeoffs are covered in SIP versus direct exchange feeds.
  • Buy a vendor composite, and read its documentation closely for whether any level past each venue's best is actually included. Plenty of composites are stacked tops wearing a ladder interface.
  • For historical work, use the prints. Traded size at a strike over a window is a workable proxy for what the market absorbed there, and where to find options trade data walks through the sources.

What you still will not get

Four limits survive all of those routes.

  • No order attribution. No US options feed names the firm behind a quote or a print.
  • No queue position. Price-level depth aggregates every order at a price into one number, so your place in line at that price stays unknowable from the data.
  • No market by order view. The per-order detail that futures traders know as MBO has no public options equivalent, and the distinction is drawn in MBO versus MBP order book data.
  • No guarantee that displayed size is all the size. Reserve interest and complex order books hold quantity that never appears in the simple quote. A position opened at one venue can be closed at another, since every US listed option clears at a single clearinghouse, a mechanic covered in one clearinghouse, many options exchanges.

FAQ

Is OPRA a depth of book feed?

No. It carries each options exchange's best bid and offer for every listed contract plus all trade prints. Orders resting behind each venue's best quote are not disseminated on it, and the message format has no second price level.

Does OPRA carry options trades as well as quotes?

Yes. Trade prints from every US options exchange travel on the same consolidated feed as the quotes, which is why last-sale data and the quote agree with one another across brokers.

How do I see how many contracts are available at a strike?

Sum the displayed bid or offer size across every exchange quoting that contract at the moment you care about. That gives the total size at the front of the market. Anything resting behind it requires an individual exchange's depth product.

Is there an MBO feed for US options?

No public one. US options venues publish aggregated price-level data at most, so per-order visibility and queue position are not available the way they are in some futures markets.

How many US options exchanges are there?

More than a dozen as of September 2026, and the count moves as venues launch or merge. The figure that matters for building a composite is how many actually quote the contract in front of you, which the panels above measure directly.

Data notes and basis
  • All five panels pin the September 16, 2026 session, so the figures stay put as newer data arrives.
  • Venues appear as exchange codes rather than names, which keeps each panel honest about what the print and quote records carry.
  • The chain breadth panel counts contract rows in the daily options analytics snapshot for that date, covering listed contracts with computed greeks, so it is a close read of chain size rather than an exchange listing file.
  • The composite panel keeps only venues holding a two-sided quote inside the pinned minute, which drops one-sided and placeholder quotes from the stack.

Every panel above ships with the SQL that produced it, so the stitching logic is open to inspection. To stack the per-venue quotes for a contract you follow, ask the question in plain English on the Strasmore terminal.