Strasmore Research
Learn am Matt ConnorBy Matt Connor · Updated 2026-07-25

How Much E Dey Cost to Trade Options?

Options commissions fit dey zero, but bid-ask spread na real money. See the median cost to trade SPY, QQQ, IWM, GLD, and TSLA options, for basis points.

Commissions for listed options dey zero for most brokerages, but every marketable options order still dey pay the bid-ask spread — the gap between the best price wey buyer go pay and the best price wey seller go accept. Options dey usually trade for dollar price way lower pass the stock dem dey reference, so the same cents-wide gap na much bigger share of the trade. For 2026-07-02, SPY options (every 2026-expiry contract) quote median spread of 80.97 basis points during regular hours, while SPY stock imself quote 0.27 bps — gap of about 299.9×. Every figure below na dem measure am from the consolidated options quote and trade tapes, with the exact SQL wey dey behind each number attached.

Why option spread dey different from stock spread

Make we look stock wey dem quote am $745.00 bid / $745.02 ask. The two-cent spread na about 0.27 bps of the share price. One at-the-money call for the same stock fit quote $7.20 bid / $7.30 ask — ten-cent spread, wey work out to around 138 bps of the $7.25 midpoint. The option wider pass for cents, and hundreds of times wider as share of the price wey person really pay. The option low dollar price na im dey do the mechanical work: ten cents small amount for absolute terms and big percentage of $7.25 contract.

The professional unit wey dem dey use take compare costs across instruments na the basis point (bp) — one hundredth of one percent. Standard option contract cover 100 shares of the underlying, so the dollar consequence of trade go scale with the underlying, but dem dey measure the spread against the option own quoted price. Na that unit dem dey use throughout this page.

SPY options vs. SPY stock: head-to-head

SPY na the options product wey get the most liquid inside US, and even for there the cost gap sharp well well. The panel below dey put SPY options and SPY stock side by side for the same session: quote traffic, executed trades, and the median quoted spread of each one.

QuerySPY options vs. SPY stock for one session: quote count, trade count, and median quoted spread
The exact SQL behind every number
WITH
    opt_q AS (
        SELECT
            count() AS opt_updates,
            quantileDeterministic(0.5)((toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2), cityHash64(ticker, sip_timestamp)) AS opt_median_spread_ratio
        FROM global_markets.cache_options_quotes
        WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
          AND ticker >= 'O:SPY26' AND ticker < 'O:SPY27'
          AND bid_price > 0 AND ask_price > 0 AND ask_price > bid_price
    ),
    stock_q AS (
        SELECT
            count() AS stock_updates,
            quantileDeterministic(0.5)((toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2), cityHash64(ticker, sip_timestamp)) AS stock_median_spread_ratio
        FROM global_markets.cache_stocks_quotes
        WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
          AND ticker = 'SPY'
          AND bid_price > 0 AND ask_price > 0 AND ask_price > bid_price
    ),
    opt_t AS (
        SELECT count() AS opt_trades FROM global_markets.options_trades
        WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
          AND ticker >= 'O:SPY26' AND ticker < 'O:SPY27'
    ),
    stock_close AS (
        SELECT round(argMax(toFloat64(close), window_start), 2) AS spy_close
        FROM global_markets.delayed_stocks_minute_aggs
        WHERE ticker = 'SPY' AND window_start >= '2026-07-02 13:30:00' AND window_start < '2026-07-02 20:00:00'
    )
SELECT
    '2026-07-02' AS session_date,
    opt_q.opt_updates AS spy_opt_updates,
    stock_q.stock_updates AS spy_stock_updates,
    round(opt_q.opt_updates / stock_q.stock_updates, 1) AS opt_to_stock_update_ratio,
    opt_t.opt_trades AS spy_opt_trades,
    round(opt_q.opt_updates / opt_t.opt_trades, 1) AS quotes_per_trade,
    round(opt_q.opt_median_spread_ratio * 10000, 2) AS spy_opt_median_spread_bps,
    round(stock_q.stock_median_spread_ratio * 10000, 2) AS spy_stock_median_spread_bps,
    round(opt_q.opt_median_spread_ratio / stock_q.stock_median_spread_ratio, 1) AS ratio_opt_to_stock_spread,
    stock_close.spy_close AS spy_underlying_close
FROM opt_q CROSS JOIN stock_q CROSS JOIN opt_t CROSS JOIN stock_close

The median SPY options spread of 80.97 bps mean say a round-trip market order — to buy for the ask and later sell for the bid — go give up something like the full quoted spread if you compare am to the midpoint, about half for each side of the trade. The same round trip inside SPY stock go give up something like 0.27 bps. The quote traffic dey tell the same liquidity story from another angle: market makers print 256.5 SPY option quote updates for every executed SPY options trade, dey reprice thousands of strike-and-expiry combinations tick by tick.

How SPY options spread dey distribute: e no be one number

Median dey useful, but di spread wey one trader go pay depend on di contract. Near-the-money, near-expiration SPY options dey quote di tightest; far out-of-the-money and far-dated contracts fit be much wider. Di panel below show di full distribution across valid two-sided SPY option quotes for di session.

QuerySPY options quoted-spread distribution: percentiles in basis points
The exact SQL behind every number
WITH opts AS (
    SELECT
        (toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000 AS spread_bps,
        cityHash64(ticker, sip_timestamp) AS det
    FROM global_markets.cache_options_quotes
    WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
      AND ticker >= 'O:SPY26' AND ticker < 'O:SPY27'
      AND bid_price > 0 AND ask_price > 0 AND ask_price > bid_price
)
SELECT
    round(quantileDeterministic(0.10)(spread_bps, det), 2) AS p10_bps,
    round(quantileDeterministic(0.25)(spread_bps, det), 2) AS p25_bps,
    round(quantileDeterministic(0.50)(spread_bps, det), 2) AS median_bps,
    round(quantileDeterministic(0.75)(spread_bps, det), 2) AS p75_bps,
    round(quantileDeterministic(0.90)(spread_bps, det), 2) AS p90_bps,
    count() AS valid_two_sided_quotes
FROM opts

Di middle half of SPY option quotes fall between 49.65 bps and 147.12 bps. One quote out of ten tight pass 35.51 bps, and one out of ten wide pass 316.51 bps. Di wide tail dey track illiquid strikes and far-dated expiries — exactly di contracts wey casual buyer go likely stumble enter.

SPY na the benchmark, but no every options product dey quote tight like dat. The panel wey dey below dey measure the median regular-hours quoted spread, for basis points, across five option roots wey people dey trade well-well: three index ETFs (SPY, QQQ, IWM), one gold ETF (GLD), and one single stock wey get deep options liquidity (TSLA). Dem filter each root to im 2026-expiry ticker range so the query go prune the (ticker, sip_timestamp) index, and dem list the rows alphabetically so each product go keep one fixed position.

QueryOptions bid-ask spreads by product: median basis points, July 2, 2026 regular hours
The exact SQL behind every number
SELECT
    root,
    round(count() / 1e6, 1) AS quote_updates_millions,
    round(quantileDeterministic(0.5)(spread_bps, det), 2) AS median_spread_bps,
    round(quantileDeterministic(0.5)(width_cents, det), 2) AS median_width_cents
FROM (
    SELECT 'SPY' AS root, (toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000 AS spread_bps, (toFloat64(ask_price) - toFloat64(bid_price)) * 100 AS width_cents, cityHash64(ticker, sip_timestamp) AS det
    FROM global_markets.cache_options_quotes
    WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
      AND ticker >= 'O:SPY26' AND ticker < 'O:SPY27'
      AND bid_price > 0 AND ask_price > 0 AND ask_price > bid_price
    UNION ALL
    SELECT 'QQQ' AS root, (toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000 AS spread_bps, (toFloat64(ask_price) - toFloat64(bid_price)) * 100 AS width_cents, cityHash64(ticker, sip_timestamp) AS det
    FROM global_markets.cache_options_quotes
    WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
      AND ticker >= 'O:QQQ26' AND ticker < 'O:QQQ27'
      AND bid_price > 0 AND ask_price > 0 AND ask_price > bid_price
    UNION ALL
    SELECT 'IWM' AS root, (toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000 AS spread_bps, (toFloat64(ask_price) - toFloat64(bid_price)) * 100 AS width_cents, cityHash64(ticker, sip_timestamp) AS det
    FROM global_markets.cache_options_quotes
    WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
      AND ticker >= 'O:IWM26' AND ticker < 'O:IWM27'
      AND bid_price > 0 AND ask_price > 0 AND ask_price > bid_price
    UNION ALL
    SELECT 'GLD' AS root, (toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000 AS spread_bps, (toFloat64(ask_price) - toFloat64(bid_price)) * 100 AS width_cents, cityHash64(ticker, sip_timestamp) AS det
    FROM global_markets.cache_options_quotes
    WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
      AND ticker >= 'O:GLD26' AND ticker < 'O:GLD27'
      AND bid_price > 0 AND ask_price > 0 AND ask_price > bid_price
    UNION ALL
    SELECT 'TSLA' AS root, (toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000 AS spread_bps, (toFloat64(ask_price) - toFloat64(bid_price)) * 100 AS width_cents, cityHash64(ticker, sip_timestamp) AS det
    FROM global_markets.cache_options_quotes
    WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
      AND ticker >= 'O:TSLA26' AND ticker < 'O:TSLA27'
      AND bid_price > 0 AND ask_price > 0 AND ask_price > bid_price
)
GROUP BY root
ORDER BY root ASC

The index ETFs own the tight end of the board: SPY quote median spread of 80.97 bps, QQQ 123.71 bps, and IWM 130.72 bps. For the wide end, TSLA options quote 309.93 bps and GLD options 786.75 bps — one different cost regime entirely. The quote-updates column (for millions) dey tell the companion story: the products wey dem dey quote pass na im dey sit for the tight end of the board.

The 0DTE and weekly effect: shorter life, wider spread

Contracts wey get less time left dey trade for lower dollar prices, and dis one mechanically push the spread for basis points even when the gap in cents still small. The panel below dey group near-the-money SPY option quotes (strikes 730–760) by expiration date — every 2026 expiry wey print at least one million quote updates for the session, in calendar order.

QuerySPY options median spread by expiration date, near-the-money strikes only
The exact SQL behind every number
WITH opts AS (
    SELECT
        toFloat64(ask_price) - toFloat64(bid_price) AS width,
        (toFloat64(ask_price) + toFloat64(bid_price)) / 2 AS mid,
        substring(ticker, -15, 6) AS expiry_code,
        toUInt32OrZero(substring(ticker, -8)) / 1000 AS strike,
        cityHash64(ticker, sip_timestamp) AS det
    FROM global_markets.cache_options_quotes
    WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
      AND ticker >= 'O:SPY26' AND ticker < 'O:SPY27'
      AND bid_price > 0 AND ask_price > 0 AND ask_price > bid_price
      AND strike BETWEEN 730 AND 760
)
SELECT
    expiry_code,
    round(count() / 1e6, 1) AS quote_updates_millions,
    round(quantileDeterministic(0.5)(width / mid * 10000, det), 2) AS median_spread_bps,
    round(quantileDeterministic(0.5)(width * 100, det), 2) AS median_width_cents
FROM opts
GROUP BY expiry_code
HAVING count() >= 1000000
ORDER BY expiry_code ASC

The same-day contract — expiry code 260702, the 0DTE — show median spread of 113.64 bps on median width of just 2 cents. The longest-dated expiry across the bar, 261231, quote wider in cents (11) but materially tighter in basis points, at 37.16 bps. Na dat one be the core lesson of options trading costs: one-cent or two-cent spread no automatically cheap when the option itself dey trade for few dollars. Wetin be 0DTE options dey explain the mechanics of same-day contracts.

Wetin the trade-size data dey show about who dey pay these costs

Options dey trade inside contracts, and one standard contract cover 100 shares. The median executed options trade for 2026-07-02 na just 1 contract; even the 90th percentile print na only 10 contracts. Most options trades dey small, and the retail-sized trader na the one wey exposure to the quoted spread pass — one big institutional order fit often negotiate price improvement or slice itself across time.

QueryOptions trade size distribution on July 2, 2026 (whole-tape contracts per print)
The exact SQL behind every number
WITH trades AS (
    SELECT toFloat64(size) AS size FROM global_markets.options_trades
    WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
)
SELECT
    round(quantileExact(0.50)(size), 0) AS median_contracts,
    round(quantileExact(0.90)(size), 0) AS p90_contracts,
    round(avg(size), 1) AS avg_contracts,
    count() AS total_prints
FROM trades

FAQ

Abeg, options cost pass stocks to trade?

Normally na so, if you measure am as share of the price wey dem trade am at. Deep liquid ETF like SPY dey pay quoted spread well under one basis point for the stock itself; the same underlying options dey pay tens of basis points. The dollar amount go depend on the option price and how many contracts, but the spread as percentage of the option value almost always big pass the stock own.

Why 0DTE options spread so wide for basis points?

Same-day and weekly options dey trade at low dollar prices — sometimes under $1.00 — as dem dey reach the end of their life. One-cents or two-cents spread on $0.50 option na 2–4% of the price, or 200–400 bps. The cents dey look small; the percentage cost no dey small. Na why traders dey compare spreads for basis points, no be cents.

Commission pass spread?

For single-lot retail trade, the spread dey dominate. $1.00 / $1.05 quote go cost $5.00 per contract for full round trip (100 shares per contract) before any commission. For low-priced or wide-spread products, the spread alone fit pass any commission wey you fit think.

I fit avoid the spread with limit orders?

Limit order wey dey inside the spread fit fill for less than the full spread, but e no get guarantee say e go fill. Marketable order go pay the spread by definition. The spread na the price of immediacy, no be fee wey your broker dey charge.

Which options products get tightest spreads?

Based on the measurements for this page, the big index ETFs — SPY, QQQ, IWM — dey quote tightest medians, and dem also carry the heaviest quote traffic. Commodity ETFs (GLD) and single-stock options fit quote much wider. The spread dey change contract by contract — same underlying, different strike and expiry — so one median go hide plenty variation.

Data notes

All timestamps dey stored for UTC; regular hours for July 2, 2026 dem filter as sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00' (9:30 am–4:00 pm ET). Spread statistics dey use only valid two-sided quotes (bid_price > 0, ask_price > 0, ask_price > bid_price), dem cast Decimal prices to Float64 before division, and dem use deterministic median estimators (quantileDeterministic, keyed by hash of ticker and timestamp) so regeneration go reproduce identical figures. The census below dey count every SPY-options record for the window and e dey show how much of the raw feed those valid two-sided quotes represent.

Quote-quality census and full methodology
QuerySPY options quote quality: valid, one-sided, and locked/crossed records
The exact SQL behind every number
WITH opts AS (
    SELECT
        bid_price,
        ask_price
    FROM global_markets.cache_options_quotes
    WHERE sip_timestamp >= '2026-07-02 13:30:00' AND sip_timestamp < '2026-07-02 20:00:00'
      AND ticker >= 'O:SPY26' AND ticker < 'O:SPY27'
)
SELECT
    count() AS total_updates,
    countIf(bid_price > 0 AND ask_price > 0 AND ask_price > bid_price) AS valid_two_sided,
    round(100.0 * countIf(bid_price > 0 AND ask_price > 0 AND ask_price > bid_price) / count(), 2) AS valid_pct,
    countIf(bid_price = 0 OR ask_price = 0) AS one_sided,
    round(100.0 * countIf(bid_price = 0 OR ask_price = 0) / count(), 2) AS one_sided_pct,
    countIf(bid_price > 0 AND ask_price > 0 AND ask_price <= bid_price) AS locked_or_crossed,
    round(100.0 * countIf(bid_price > 0 AND ask_price > 0 AND ask_price <= bid_price) / count(), 2) AS locked_or_crossed_pct
FROM opts

More than 99.94% of SPY option quote records for the session be valid two-sided quotes; one-sided records be 0.06% of the feed, and locked or crossed records be negligible. Every spread number above dem compute am on the valid two-sided subset — the cost wey trader fit actually observe for the NBBO.

  • Market data source: consolidated OPRA-style options quote tape (global_markets.cache_options_quotes), the matching stock quote tape, and the consolidated options trade tape (global_markets.options_trades; the trade-size panel deliberately cover the whole tape, not just SPY).
  • OCC ticker format: O: + root + six-digit expiry (YYMMDD) + C/P + seven-digit strike ×1000. The 0DTE panel dey parse expiry and strike from the ticker; spread calculations dey aggregate calls and puts together. Each root filter cover im 2026-expiry range (O:SPY26..O:SPY27 and equivalents), which dey keep every scan pruned on the (ticker, sip_timestamp) index.
  • Spread definition: (ask − bid) / midpoint × 10,000, for basis points, on valid two-sided quotes only.
  • Medians and percentiles: quantileDeterministic reservoir estimators keyed by cityHash64(ticker, sip_timestamp) — bounded memory, and identical output on every regeneration.
  • Underlying close: last regular-hours minute bar from delayed_stocks_minute_aggs.
  • Session window: 13:30–20:00 UTC, dem check am against observed SPY minute bars rather than calendar arithmetic.
  • Pinned session: July 2, 2026 — one completed full session wey dey comfortably behind the warehouse ~1–2 day ingest lag at authoring time (July 9, 2026). Date literals dey fixed, so regeneration go reproduce the same figures.

You wan know wetin one specific contract go cost? Every panel above na stored query — run dem, or your own variation, for the Strasmore terminal. For more on the mechanics, see the cost to trade stocks, wetin bid-ask spread be, 0DTE options, the size of the options quote feed, and options volume vs. open interest.