Strikeline is a replay simulator for SPX 0DTE options (options that expire on the day they are traded). It replays a historical session with the complete SPXW option chain at 10-second resolution and simulates order execution, margin and settlement against the recorded quotes. At no point does the application expose data from after the replay clock.
A synthetic FOMC session from the bundled demo data: the index chart (left), the option chain rendered as a price ladder aligned to the chart's price axis (right), and two open spreads with a working bracket order (bottom).
- Purpose: deliberate practice of intraday options trading on historical sessions, at real time or accelerated up to 300x.
- Scope: unlike chart-only replay, Strikeline replays every strike's bid and ask and fills orders against those quotes.
- Evaluation: a bundled synthetic data set lets it run without a data subscription or broker account (Quick start).
- Engineering: specification-driven development, approximately 1,400 automated tests, a lookahead gate, an independent oracle, and CI on Linux and Windows (Engineering).
- Stack: Python 3.13, FastAPI, pyarrow and DuckDB, SQLite, vanilla JavaScript, TradingView Lightweight Charts.
Status. Strikeline is a personal project, developed for my own trading practice. It is extensively tested within its scope, but it has not undergone the independent review, hardening and operational work that production software requires. The live-broker connectors are experimental and have not been used with a real account.
Contents: Quick start · Features · Engineering · Using real data · Documentation · License
Requires Python 3.13 (on Windows, use py -3.13 if it is not the default python).
git clone https://github.com/triwebb1/strikeline.git
cd strikeline
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
python launch.py
On first run, the launcher generates the demo data set in data/, starts the server on
http://127.0.0.1:8765 and opens a browser. Create a workspace on any session from
2030-04-08 to 2030-04-12 and start playback. On Windows, Strikeline.cmd launches the
application once the package is installed.
The demo data is synthetic (src/strikeline/demo.py): a random-walk index with intraday
volatility seasonality and event shocks, and option quotes priced with Black-Scholes on a
skewed volatility smile and rounded to the SPXW tick grid. It is dated 2030 so that it cannot
be mistaken for historical data.
- Price ladder. The option chain is rendered on the chart's price axis, with each strike at its price level, call and put bid / mid / ask, and $5 vertical spread prices between strikes. Positions, working orders and the order being composed share the same rows, alongside a P&L-at-expiration profile. Selecting a price opens an order ticket; optional one-click mode submits directly.
- Lookahead-free replay. The server owns the clock and filters every response to data stamped at or before it. Playback runs at 1x to 300x, steps in 10-second increments, jumps, or advances with Next to one second before the next fill, trigger or session event. Blind mode starts on a random session and conceals the date.
- Orders. Market, limit, stop and SPX-level trigger orders; OCO brackets; and multi-leg combinations (verticals, iron condors, butterflies) that fill atomically at the adverse side of every leg.
- Account. Long and short positions per leg, Reg-T style margin with covered pairs margined together, buying-power checks at fill time, commissions, and cash settlement at the official close.
- Chart. 10-second to 30-minute candles including the overnight session, VWAP with standard-deviation bands, prior-session levels, opening ranges, an EMA, and economic-event markers (CPI, FOMC, NFP) that appear only once the event would have been known.
- Journal and statistics. Fills, an event log, a trade journal with notes and tags, and statistics across sessions. Each workspace is a simulated account persisted to SQLite and resumed exactly where it was left.
![]() |
![]() |
| Selecting a spread price on the ladder opens a ticket with an order preview. | The synthetic FOMC announcement: the bracket's stop fills through a price gap. |
Strikeline was developed over approximately one week using specification-driven development, with Claude Code as the implementation tool. The process below is what made that pace compatible with correctness:
- Specification first. Every rule (what constitutes a fill, when an order may act, how margin pairs legs, what the ladder displays) is defined in SPEC.md before implementation. The specification is versioned (v1.0 to v1.5), and code and tests cite its sections, so each behavior is traceable to a recorded decision.
- Correctness by design. The architecture makes the most consequential failures
structurally difficult: the server owns the clock and gates every response, the engine is
side-effect-free logic over integer cents, and all trading passes through a single
Backendinterface, which a test enforces. - Phased delivery with acceptance. The data pipeline, engine, API and UI were built in sequence, each accepted before the next began. Data decisions rest on measurement; for example, the candle-wick method was selected by evaluating candidates against the actual index.
- Independent verification. In addition to unit and integration tests, an oracle with its own implementation re-derives each outcome from the raw data, a headless browser exercises the real UI, and a dedicated review followed each major change. Findings and their resolutions are documented (for example, docs/live/LIVE_REVIEW_FINDINGS.md).
I was responsible for the product and engineering decisions: the trading workflow and the ladder concept, the specification, the architecture, the testing strategy, and the acceptance of each feature through use. Claude Code wrote most of the code to that specification.
The suite contains approximately 1,400 automated tests: about 690 for the replay product (engine, data, server and UI) and 700 for the experimental broker connectors, which run against simulated brokers. The 1,200 tests that require no market data run in CI on every push, together with the end-to-end checks below on freshly generated demo data. The remainder replay licensed historical sessions (circuit-breaker halts, early closes, FOMC days) and run locally.
| Check | What it verifies |
|---|---|
| Lookahead gate | No response contains data stamped after the clock, and every view recomputed from data with the future removed is identical (tests/demo/test_demo_gate.py). |
| Oracle | Independent code, trading through the API as the UI does, predicts every fill, stop, margin figure and final cash balance to the cent from the raw quote files (tests/e2e/oracle_check.py). |
| Browser | Playwright drives the real UI in headless Chromium and fails on any console error (tests/web/demo_tour.py, which also produces these screenshots). |
| Architecture | The server does not bypass the Backend interface (tests/test_architecture.py). |
| Local-only server | The server binds to 127.0.0.1 and rejects non-local Host headers and cross-origin requests, so other web pages cannot control it. |
| Input robustness | Out-of-range prices and quantities are rejected before any state changes, and concurrent open and close operations or failed saves leave workspaces consistent. |
| Data validation and lint | The demo data must pass the format validator; Ruff checks the code. |
The complete suite runs with one command, on the demo data or on a local data set:
pip install -e ".[dev]" && python -m playwright install chromium
python tests/e2e/run_e2e.py --demo
flowchart LR
subgraph Browser["Browser (vanilla JS + Lightweight Charts)"]
UI["chart · ladder · ticket · positions"]
end
subgraph Server["FastAPI server"]
API["HTTP + WebSocket API"]
Gate["lookahead gate<br/>(T ≤ clock)"]
WS["workspaces<br/>(SQLite)"]
end
subgraph Backends["Backend interface"]
Replay["ReplayBackend<br/>engine + replay clock"]
Live["Live backends<br/>(experimental)"]
end
Data[("replay store + option snapshots<br/>(parquet)")]
Pipeline["offline pipeline"] --> Data
Demo["demo generator"] --> Data
UI <--> API
API --> Gate --> Replay
API --> WS
Replay --> Data
Live -.-> Brokers["IBKR · TradeStation · Massive"]
| Package | Responsibility |
|---|---|
strikeline.engine |
Pure trading logic: orders, fills, per-leg positions, margin, settlement and clock processing, with no I/O (docs/ENGINE.md). |
strikeline.data |
Read-only loaders for the replay store and option snapshots, path configuration, and the format validator. |
strikeline.backends |
The Backend interface the server depends on; ReplayBackend wraps the engine, and backends/live contains the experimental broker connectors. |
strikeline.server |
FastAPI application, clock loop, lookahead gate, indicators, ladder and chain views, and workspaces (docs/API.md). |
strikeline.pipeline |
Offline builder of the replay store from raw vendor files. |
strikeline.demo |
Synthetic demo data generator. |
web/ |
Frontend: ES modules with no build step and no framework. |
The engine represents money as integer cents and time as UTC epoch seconds on a 10-second grid.
Historical SPX option quotes are licensed per user, so none are included. Strikeline reads a documented, file-based parquet format, specified file by file in docs/DATA_FORMAT.md. A validator checks a data set against that specification:
python -m strikeline.data.validate --replay <dir> --options <dir>
The minimum requirement is 10-second SPXW option snapshots (bid and ask per strike; files
in ThetaData's layout are read directly) and an index bar series with a trading calendar
(the replay store). The included pipeline (python -m strikeline.pipeline build, rules in
docs/PIPELINE.md) builds the replay store from the snapshots and
1-second ES futures bars (DataBento CSV), which also supply the overnight chart and VWAP.
For other sources, writing the replay store directly is usually simpler;
src/strikeline/demo.py is a complete reference writer.
| Document | Contents |
|---|---|
| SPEC.md | Product specification: every rule the application follows |
| docs/DATA_FORMAT.md | Data contract for supplying your own data |
| docs/ENGINE.md | Trading engine: fills, orders and account |
| docs/API.md | HTTP and WebSocket API used by the web UI |
| docs/PIPELINE.md | Pipeline rules for building the replay store from raw data |
| docs/wick_validation.md | Evaluation behind the candle-wick method |
| docs/live/ | Experimental live trading: design, broker notes and reviews |
| docs/mockups/price_ladder_v11.html | Design mockup of the price ladder (a standalone HTML page; open it in a browser) |
GNU AGPL v3.0 or later. You may use, study, modify and share Strikeline. If you distribute it, or make a modified version available to others over a network, you must provide the source of that version under the same license. Bundled third-party code is listed in THIRD_PARTY_NOTICES.md.
Strikeline is a training and research tool. It does not provide investment advice and is offered without warranty (see the license).


