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).

Backtesting Data Model

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.

Core entities

Use stable tables or structured caches for these objects:

EntityPurpose
Underlying barsSignal features, opening ranges, VWAP, volatility, and exit context.
Daily barsATR, prior-day filters, regime features, and long lookback indicators.
Contract universeListed option contracts as of the simulated date.
Option quotesBid/ask execution context and spread quality.
Option tradesActivity evidence and last-sale context, not guaranteed executable price.
Option barsOption price path when quote replay is unavailable or used as a fallback.
Coverage metadataData availability, missing intervals, provider status, and cache provenance.
Trade logFilled and rejected decisions with enough metadata for audits.

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.

Data quality contract

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

Those counters prevent a clean-looking equity curve from hiding a weak data path.

Read next: Backtesting Engine Loop, Options Contract Selection, and Quotes.

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 the live, historical, and chain workflows directly.