Strasmore Research
Learn am Matt ConnorBy Matt Connor · Updated 2026-07-25 · data as of July 25, 2026 · refreshed weekly

How big di OPRA options quote feed dey?

We count one full day of OPRA-scale NBBO updates for our warehouse, measure am against di whole stock quote tape. Di options feed na di biggest market data stream for US.

Di options quote feed na di biggest stream of market data for US: every listed option contract carry im own best bid and best ask, and OPRA — wey be di Options Price Reporting Authority, di consolidated tape for US listed options — dey publish every update for every one of dem. On 2026-07-13, just one ordinary session, our warehouse record 8.23 billion options quote updates — wey be 16.8 times di size of di whole stock quote tape for dat same day. Dis page dey measure di firehose directly, wit di exact query wey support every number join for body.

Why the options quote feed big like dis?

One stock get one national best bid and offer — na one bid-ask spread wey dem dey keep current. Option chain dey multiply dat one: each contract wey dem list — every combination of expiration date, strike price, and whether e be call or put — dey quote im own NBBO. For 2026-07-13, SPY alone keep 9156 distinct contracts wey dey quote, if you count only im 2026 expiries.

The multiplication no stop for contract count. An option value dey move with im underlying stock, and when di share price tick, market makers dey refresh quotes across di chain — every strike, every expiry, at once, weda anybody dey trade dose contracts or not. Dat na di shape of di arithmetic wey dem measure below: quote updates dey reach billions per session, and 776 quote updates for every options trade wey dem execute.

One day wey we count di options tape

How much data dey for practice? Di panel wey dey below count everi options quote update wey our warehouse store for 2026-07-13 — di most recent session wey don complete at least five calendar days back, one rule wey dem explain for di scarcity section — and set am against di same session full stock quote tape, di same head-to-head wey di July 7 market recap run for im Monday tape. Both counts cover di full calendar day, bounded for universal time (UTC), wey span di entire US options session.

QueryOne session, two tapes: every options NBBO update vs. every stock NBBO update
The exact SQL behind every number
WITH (
    SELECT max(toDate(toTimeZone(window_start, 'America/New_York')))
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'SPY'
      AND window_start >= toDateTime(today() - 10)
      AND window_start < toDateTime(today() - 4)
) AS session_day,
(
    SELECT (count(), uniqExact(ticker))
    FROM global_markets.cache_stocks_quotes
    WHERE sip_timestamp >= toDateTime(session_day)
      AND sip_timestamp < toDateTime(session_day + 1)
) AS stock_tape,
(
    SELECT (count(), uniqExact(ticker))
    FROM global_markets.options_trades
    WHERE sip_timestamp >= toDateTime(session_day)
      AND sip_timestamp < toDateTime(session_day + 1)
) AS option_trades_t,
(
    SELECT toUInt32(max(sip_timestamp)) - toUInt32(min(sip_timestamp))
    FROM global_markets.cache_options_quotes
    WHERE ticker >= 'O:SPY26' AND ticker < 'O:SPY27'
      AND sip_timestamp >= toDateTime(session_day)
      AND sip_timestamp < toDateTime(session_day + 1)
) AS spy_span_seconds
SELECT
    toString(session_day) AS session_date,
    round(count() / 1e9, 2) AS option_quote_updates_bn,
    round(stock_tape.1 / 1e6, 0) AS stock_quote_updates_m,
    stock_tape.2 AS stock_symbols_quoted,
    round(count() / stock_tape.1, 1) AS option_to_stock_ratio,
    round(option_trades_t.1 / 1e6, 1) AS option_trades_m,
    round(option_trades_t.2 / 1e3, 0) AS option_contracts_traded_k,
    round(count() / option_trades_t.1, 0) AS quote_updates_per_trade,
    round(count() / spy_span_seconds / 1e3, 0) AS avg_updates_per_second_k
FROM global_markets.cache_options_quotes
WHERE sip_timestamp >= toDateTime(session_day)
  AND sip_timestamp < toDateTime(session_day + 1)

Di whole options tape come to 8.23 billion NBBO updates. Na only 338 thousand distinct contracts actually TRADE dat day — di quote stream dey reprice plenty more of di chain pass wetin ever change hands. Di same day stock tape — everi consolidated quote update for everi listed stock and ETF, premarket and after-hours join body — measure 491 million updates across 12958 symbols. Di ratio na di headline: di options quote stream run 16.8 times di size of di stock quote stream.

Two more readings from di same scan give di feed im texture. Wen we average am across di session quoting span (wey we measure on SPY chain, di deepest one for di tape), updates arrive at 339 thousand per second. And di options market print 10.6 million actual trades dat day — 776 quote updates for everi one of dem. Na quoting, no be trading, dey fill di pipe.

One root im own slice: SPY option chain for one day

One whole-tape number dey hard to feel, and the whole tape sef dey expensive to scan — so cut one slice. The panel wey dey below dey count every quote update for SPY option contracts wey dey expire for 2026, over the same session and the same UTC-bounded day: one underlying im chain, wey dem carve out from the firehose by one ticker range.

QuerySPY 2026-expiry option chain — one root share of di quote firehose
The exact SQL behind every number
WITH (
    SELECT max(toDate(toTimeZone(window_start, 'America/New_York')))
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'SPY'
      AND window_start >= toDateTime(today() - 10)
      AND window_start < toDateTime(today() - 4)
) AS session_day
SELECT
    toString(session_day) AS session_date,
    round(count() / 1e6, 1) AS spy_quote_updates_m,
    uniqExact(ticker) AS spy_contracts_quoted,
    round(count() / uniqExact(ticker) / 1e3, 1) AS avg_updates_per_contract_k,
    uniqExactIf(ticker, substring(ticker, 6, 6) = formatDateTime(session_day, '%y%m%d')) AS same_day_expiry_contracts,
    round(100.0 * countIf(substring(ticker, 6, 6) = formatDateTime(session_day, '%y%m%d')) / count(), 1) AS same_day_expiry_pct_of_updates,
    quantileExactWeightedIf(0.5)(toInt32(round(toFloat64(ask_price - bid_price) * 100)), 1, bid_price > 0 AND ask_price >= bid_price AND substring(ticker, 6, 6) = formatDateTime(session_day, '%y%m%d')) AS same_day_median_width_cents,
    quantileExactWeightedIf(0.5)(toInt32(round(toFloat64(ask_price - bid_price) * 100)), 1, bid_price > 0 AND ask_price >= bid_price) AS all_spy_median_width_cents,
    round(countIf(NOT (bid_price > 0 AND ask_price >= bid_price)) / 1e3, 0) AS dropped_invalid_quotes_k,
    formatDateTime(toTimeZone(min(sip_timestamp), 'America/New_York'), '%H:%i') AS spy_first_quote_et,
    formatDateTime(toTimeZone(max(sip_timestamp), 'America/New_York'), '%H:%i') AS spy_last_quote_et,
    toHour(toTimeZone(min(sip_timestamp), 'America/New_York')) * 60 + toMinute(toTimeZone(min(sip_timestamp), 'America/New_York')) AS spy_first_quote_et_minute,
    toHour(toTimeZone(max(sip_timestamp), 'America/New_York')) * 60 + toMinute(toTimeZone(max(sip_timestamp), 'America/New_York')) AS spy_last_quote_et_minute
FROM global_markets.cache_options_quotes
WHERE ticker >= 'O:SPY26' AND ticker < 'O:SPY27'
  AND sip_timestamp >= toDateTime(session_day)
  AND sip_timestamp < toDateTime(session_day + 1)

One underlying produce 337.1 million options quote updates for just one day: 9156 contracts dey quote, na average of 36.8 thousand updates per contract. For scale, the entire stock tape for the panel wey dey above — every listed share and ETF join body — measure 491 million updates that session.

Same-day expiries dey tell the sharper story. 0DTE options — contracts wey dey trade on their own expiration day — dey dominate options trading, and the parsed table wey dey further down show every one of the session im five busiest SPY contracts wey dey expire that same day. For the quote stream, dem be small sliver: the 334 same-day contracts account for 4.5% of SPY im quote updates. Market makers dey keep the entire chain priced — December im strikes dey update all session long whether anybody trade dem or not.

Width na the other measurement wey worth to take here. Among those same-day SPY contracts, the median quoted width — ask minus bid, wey dem take across every valid NBBO update — measure 3¢; across the full 2026-expiry chain the same median measure 4¢. (197 thousand one-sided or crossed updates dem exclude from the width medians and count for the panel.)

How to read option ticker (OCC symbology)

Every contract wey dey inside these panels get one OCC option symbol — na the standard format wey the Options Clearing Corporation dey manage. Our warehouse dey put O: for im front. Make you use O:SPY261218C00700000 as example wey dem work:

  • RootSPY: na the option root, e fit reach six characters, and e usually be the underlying own ticker.
  • Expiration261218: na the expiry date as YYMMDD — December 18, 2026.
  • TypeC for call, P for put.
  • Strike00700000: na the strike price wey dem multiply by 1,000 and pad with zero to reach eight digits — $700.00.

Na that fixed format dey allow make dem carve out one root chain with just plain ticker range: every SPY contract wey dey expire for 2026 dey sort between O:SPY26 and O:SPY27, na im be the exact filter for the panel wey dey up. Na the five SPY contracts wey busy pass for this session with the symbol wey dem unpack:

QueryDi five busiest SPY option contracts for di session, symbol unpacked
The exact SQL behind every number
WITH (
    SELECT max(toDate(toTimeZone(window_start, 'America/New_York')))
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'SPY'
      AND window_start >= toDateTime(today() - 10)
      AND window_start < toDateTime(today() - 4)
) AS session_day
SELECT ticker AS occ_ticker,
       any(underlying_symbol) AS root,
       concat('20', substring(ticker, 6, 2), '-', substring(ticker, 8, 2), '-', substring(ticker, 10, 2)) AS expiry_parsed,
       if(any(option_type) = 'C', 'call', 'put') AS call_or_put,
       any(toFloat64(strike_price)) AS strike_usd,
       round(sum(size) / 1e3, 1) AS contracts_traded_k,
       if(substring(ticker, 6, 6) = formatDateTime(session_day, '%y%m%d'), 1, 0) AS expires_same_day
FROM global_markets.options_trades
WHERE sip_timestamp >= toDateTime(session_day)
  AND sip_timestamp < toDateTime(session_day + 1)
  AND ticker >= 'O:SPY26' AND ticker < 'O:SPY27'
GROUP BY ticker
ORDER BY contracts_traded_k DESC, ticker
LIMIT 5

The top of the volume table na pure same-day traffic: all five contracts expire on 2026-07-13, wey be the session own date, and the one wey busy pass among dem — O:SPY260713P00749000, na $749-strike put contract — trade 732.2 thousand contracts. Put am near the quote panel wey dey before am: trading dey concentrate for the front of the chain, and quoting spreads dey across all of am.

Why options quote data dey scarce

To store dis feed mean say we go add one day like di one wey dem measure up there — every session, forever. Na di economics for one line. Most market-data products, both retail and professional, dey carry stock prices and sometimes options trades; full options quote history dey rare for any shelf, at any price. Our own warehouse hold equity quote history wey go back to 2003 and options trade history wey go back to 2014, while di options quote table start for 2022 — na di youngest tick history wey we keep, and by wide margin na di largest table wey we dey operate.

One disclosure suppose dey for plain sight: options quotes still be di slowest-arriving dataset wey we hold. New sessions normally land one or two days behind di calendar — sometimes e fit pass — while equity quotes usually settle within one day. Every panel for dis page anchor to di most recent completed session wey dey at least five calendar days back (2026-07-13 for di current run), and di weekly refresh dey re-run every query on dat same rule, so each number dey measured over one fully ingested day instead of one half-loaded front edge.

FAQ

How big the OPRA options feed dey per day?

As we measure am for our warehouse: 8.23 billion options quote updates on 2026-07-13 — na average of 339 thousand updates per second across the quoting time for that session. The raw OPRA feed dey carry trade and administrative messages on top of quotes, and im official message counts still dey higher.

The options quote feed big pass the stock quote feed?

Yes — e big pass by multiples, no be by percent. For the session wey we measure up there, options quote updates run reach 16.8 times the count of stock quote updates: 8.23 billion against 491 million. Each stock dey keep one NBBO current; im option chain dey keep hundreds or thousands.

Why options market data dey so expensive?

Scale na the part wey dey visible: a feed wey dem dey measure in billions of updates per session need real infrastructure to receive, store, and query, and the bill dey repeat every trading day. Exchange licensing fees dey sit on top of the engineering. The panels up there show exactly wetin full options quote dataset gats carry.

How many option contracts dey quote for normal day?

Dem plenty pass trade, by wide margin. On 2026-07-13, 338 thousand distinct contracts print at least one trade, while SPY im 2026-expiry chain alone keep 9156 contracts dey quote — and the full quoted universe dey span every root the way SPY im chain dey span im strikes. (To count every distinct contract for one day quote stream na im be scan wey big sotey we no dey put am for page wey dey refresh weekly — na the one number here wey we deliberately no dey publish.)

Options dey quote after hours?

Listed US equity options dey keep exchange hours. For the session wey we measure up there, SPY im first option quote land by 09:30 ET and im last one by 16:15 ET — no overnight session. The stock tape, for comparison, dey quote through premarket and after-hours.


Every panel up there dey come with the exact SQL wey produce am — expand one, swap in different root or day, and size the slice of the feed wey you dey actually trade on the Strasmore terminal.