Alphanume

Insights

How to Backtest Options Without Survivorship Bias

Alphanume Team · July 23, 2026

Remove options survivorship bias by selecting equities from each historical month's actual optionable universe before joining contracts, quotes, or strategy signals.

An options backtest has survivorship bias when it starts with today's optionable ticker list and applies that membership to earlier years. That admits stocks before their options existed and removes names that later lost listings, changed symbols, failed, or disappeared. Alphanume's Historical Optionable Tickers dataset provides monthly point-in-time snapshots of US equities with listed options.

The historical optionable tickers guide describes the membership fields and snapshot methodology. The dataset also includes expiration-density context. It does not provide historical option prices, contract definitions, bid-ask spreads, volume, open interest, or fills.

Construct the universe before testing the signal

For every signal date, select the latest optionable snapshot available on or before that date. Use the returned first-trading-day snapshot, not an assumed month label. Test membership first, then apply the strategy signal, then retrieve eligible historical contracts. This order prevents future option listings from entering earlier research.

Bias source

Incorrect method

Point-in-time method

Current membership

Use today's optionable list

Join dated monthly snapshot

Failed names

Require a current symbol

Retain historical members and outcome status

Weekly availability

Assume today's weeklies existed

Use historical density fields

Contract history

Fill missing quotes

Require actual contemporaneous contract data

Corporate actions

Join by raw ticker forever

Use dated security identifiers

Monthly snapshots introduce interval uncertainty. They identify membership on the snapshot date, not the exact intramonth listing or removal time. A conservative rule begins eligibility at the first observed snapshot and does not infer an earlier listing date.

Retrieve dated membership without page loss

Request exact dates or a multi-month range. Results paginate by date and ticker, so pass both values from next_cursor until has_more is false. Validate uniqueness on snapshot date and ticker and preserve all pages as a research artifact.

GET /v1/optionable-tickers
date_gte=2020-01-01
date_lte=2025-12-31

for each signal_date, ticker:
  snapshot = max(date where date <= signal_date)
  eligible = exists(snapshot, ticker)
  weekly = has_weeklies at snapshot
  spacing = avg_days_between at snapshot

keep rejected signals with snapshot and reason

The expiration-density fields describe listed structure. avg_days_between is the mean of four gaps after the first observed expiration gap, and has_weeklies=1 means that average is under nine days. Neither confirms exact consecutive weekly contracts or that a particular strike, quote, or liquid contract existed.

Compare current-list and historical-list tests

A useful diagnostic runs the same signal twice. Version A uses today's optionable tickers across all history. Version B uses the actual monthly membership. Compare candidate counts, missing outcomes, return distributions, and the identities admitted only by Version A. The gap quantifies the effect of the universe shortcut in that strategy.

  • Freeze signal logic, costs, and outcomes across both versions.
  • Report additions and removals by monthly snapshot.
  • Keep delisted and ticker-changed names in the outcome ledger.
  • Show how many trades lack valid contemporaneous contracts or quotes.

The current-list version can look better because it selects securities that remained healthy and optionable. It can also show artificially broad past coverage by admitting later listings. Direction and magnitude depend on the strategy, so measure rather than assume the bias.

Compare the two versions before any optimization. Show how universe choice changes the number of eligible underlyings, signals, contracts, and completed outcomes at each month. Then decompose the performance gap into names admitted too early, historical members missing from the current list, and mapping failures. This diagnostic is more useful than one aggregate return difference because it shows exactly where the bias enters.

Delisted securities are especially important. A current optionable list removes them by construction, and many market-data joins also lose their final observations. Maintain an outcome status for traded normally, halted, delisted, acquired, renamed, or unavailable. Use documented terminal values where supported and sensitivity bounds where they are not. Deleting those rows is not a neutral data-cleaning choice.

The historical universe should be versioned as a first-class backtest input. Save its extraction date, date range, pagination audit, and join rule beside the strategy configuration so a later researcher can reproduce eligibility independently of returns.

Control the remaining options biases

Fixing universe survivorship does not make an options backtest realistic. Contract-selection lookahead, stale or midpoint fills, crossed markets, ignored spreads, missing delisted outcomes, and corporate-action errors can remain. Use point-in-time contract masters and quotes, define execution rules, and apply conservative costs.

Ticker strings are not durable security identifiers. For long samples, use a dated mapping and audit ambiguous changes. If a failed name lacks a clean price or option settlement, keep the event with an unavailable-outcome state rather than deleting it.

Run a two-universe audit

As a concrete next action, choose one completed year and generate monthly eligibility tables from the historical API. Run one unchanged strategy with historical membership and again with today's list. Export every candidate with signal date, chosen snapshot, membership status, weekly flag, contract-data status, and outcome status. Review the names unique to each version. This audit exposes universe survivorship before performance is attributed to the strategy.