CuteMarkets Docs

Backtesting Framework

Framework guides for engineers building realistic options backtests with causal data, quote-aware fills, and robust validation.

Tip: open /docs/backtesting-data-model.md directly for raw markdown (easy copy/paste into an LLM).

Quick definition: the backtesting data model is the set of tables, caches, and logs that prove what market data existed at each simulated decision time.

A realistic options backtester starts with the data model. If the framework cannot reconstruct what contracts, quotes, bars, and trades existed at the simulated time, the engine can accidentally test an instrument that was not available. The right model does not need to be complicated, but it must preserve enough context to explain every selected contract, rejected contract, entry fill, exit fill, and missing-data branch.

Why this matters

Options research has more ways to leak than stock-only research. The underlying ticker may be easy to replay, but the option chain changes across expirations, listings, strikes, corporate actions, and liquidity regimes. A trade that looks clean in a current chain can be impossible in the historical chain. A last trade can be old. A quote can be crossed or missing. A backtest that loses those details is hard to audit even when the code is technically correct.

The data model should answer three questions for every simulated decision: what was the model allowed to know, what market object did it choose, and what evidence supports or rejects the fill?

Core entities

Use stable tables or structured caches for these objects:

EntityPurposeJoin keys to preserve
Underlying barsSignal features, opening ranges, VWAP, volatility, and exit context.Ticker, timestamp, timespan, adjustment policy.
Daily barsATR, prior-day filters, regime features, and long lookback indicators.Ticker, date, adjustment policy.
Contract universeListed option contracts as of the simulated date.Underlying, OCC ticker, expiration, strike, type, as_of.
Option quotesBid/ask execution context and spread quality.OCC ticker, quote timestamp, bid, ask, size, exchange.
Option tradesActivity evidence and last-sale context, not guaranteed executable price.OCC ticker, trade timestamp, price, size, conditions.
Option barsOption price path when quote replay is unavailable or used as a fallback.OCC ticker, timestamp, timespan, OHLC, volume.
Coverage metadataData availability, missing intervals, provider status, and cache provenance.Request URL, time window, status, source, fetch timestamp.
Trade logFilled and rejected decisions with enough metadata for audits.Strategy id, signal timestamp, selected contract, fill source, reject reason.

These entities should be joined by ticker, option symbol, timestamp, expiration date, and simulated as_of date. The important field is not just the symbol. It is the symbol plus the point in time when the framework was allowed to know that symbol existed.

Historical contract discovery

Do not start a backtest from the current chain. Start by discovering contracts for the simulated date:

bash
curl "https://api.cutemarkets.com/v1/options/contracts/?underlying_ticker=SPY&as_of=2025-10-29&expiration_date=2025-11-21&limit=100" \
  -H "Authorization: Bearer YOUR_API_KEY"

After selecting a contract from that historical universe, request quote, trade, or aggregate history for the exact option ticker:

bash
curl "https://api.cutemarkets.com/v1/options/quotes/O:SPY251121C00500000/?timestamp.gte=2025-10-29T13:30:00Z&timestamp.lt=2025-10-29T20:00:00Z" \
  -H "Authorization: Bearer YOUR_API_KEY"

That sequence prevents stale-contract leakage. It also gives the framework a place to record why a contract was rejected: missing quote window, wide spread, insufficient volume, missing open interest, or DTE outside the target range.

Persistence and caches

DuckDB is a practical default for local research because it supports columnar scans, SQL diagnostics, and simple file-based experiment isolation. The design pattern matters more than the database:

  • Use one writable database per experiment branch or process group.
  • Keep provider response caches separate from final trade logs.
  • Store cache provenance, request windows, and fetch status.
  • Treat read-only databases as immutable inputs; never expect them to create missing tables or data.
  • Avoid sharing one writable database across unrelated concurrent jobs.

Cache keys must include every input that can change the selected contract or fill. For option selection that usually includes ticker, date, direction, DTE window, contract status, target moneyness or delta, liquidity filters, entry underlying price, quote mode, and selection timestamp when quote-aware ranking is enabled.

Implementation contract

Data decisionRequired recordFailure to avoid
Loading a sessionDate, ticker, bars loaded, missing intervals.Treating partial data as a clean trading day.
Discovering contractsRequest filters, as_of, returned count, selected expiration.Selecting from a current or generated chain.
Ranking contractsCandidate list, ranking fields, tie-breakers, rejects.Keeping only the winner and losing why it won.
Pricing entryQuote window, bid, ask, quote age, fill side.Filling from stale last price.
Pricing exitExit trigger, quote or bar source, timestamp, side.Applying a stop before the stop was observable.
Reporting resultsDaily PnL, trade log, rejected trades, config hash.Publishing metrics without a replayable artifact.

Data quality counters

Every framework should expose data-quality counters beside performance metrics:

  • sessions with missing underlying bars
  • sessions with no eligible contracts
  • contracts with no quote coverage near entry
  • contracts rejected for spread or size
  • bars or quotes loaded from fallback sources
  • provider fetch errors and cached responses
  • trades skipped by max signal age or market window rules

Those counters prevent a clean-looking equity curve from hiding a weak data path. They also tell the developer whether the next task is strategy work, data coverage work, or execution modeling work.

Read next

Next steps

Move from the docs into the product workflow

If you are evaluating the API rather than implementing a specific endpoint right now, the product pages map live and historical workflows for stocks, options, and WebSockets.