# The Backtesting Engine Spec — hand this to Claude Code

> Companion file for the YouTube video "from zero to a final backtesting engine".
> Paste this file (or link it) into your Claude Code session together with the
> how-to-code-a-trading-algorithm guide. It is the contract your engine must satisfy —
> every rule here exists because its absence produced a fake edge we later had to kill.
> Full war stories: https://tick-stream.xyz/blog

## What you are building

A tick-data backtesting engine (Rust recommended for anything beyond daily bars —
a 7-year tick-level sweep should take minutes, not hours, because speed is what makes
the placebo, walk-forward and Monte Carlo runs affordable instead of skipped).

## Non-negotiable rules

### 1. Fills — resolve every ambiguity against yourself
- On any bar that touches **both stop and target: the stop fills first.** Always.
- **No same-bar entry + target.** A target can only fill from the bar *after* entry.
- Limit entries fill only on a **true touch** of the level — and for breakout entries,
  fill at `max(level, open)`, never at a level the market gapped through.
- No signal computed on a bar's close may trade on that same close.
- If the data cannot tell you what happened first, you lose the ambiguity.

### 2. Costs — every trade pays
- Commission + slippage on every fill, sized for the instrument (for NQ: at least
  1 tick slippage per side plus commission; more in fast markets).
- A strategy that only works gross has no edge — measure net, always.

### 3. Lookahead — structurally impossible, not just avoided
- Signals may only read data with a timestamp **strictly before** the decision time.
- Rolling features must be warmed up on past data only; no full-day features traded
  intraday; no "smoothed" states that peek forward (this alone once faked a
  Sharpe 1.84 regime model that was honestly 0.59).

### 4. Splits — earn the right to believe the number
- **Train** on the early years, **holdout** the recent years, test on holdout **once**.
- Add a **walk-forward** pass for anything with fitted parameters.
- Report both, separately. A holdout that beats train is the best sign there is;
  a holdout that collapses is the answer, not an invitation to re-tune.

### 5. Placebo & Monte Carlo — beat your own shadow
- **Placebo:** the same trade skeleton (frequency, hold time, session) with a
  randomized or mirrored entry. If the strategy cannot beat its own placebo, the
  "edge" was structure (long bias, vol timing), not the signal.
- **Monte Carlo:** resample the trade sequence to see the distribution of outcomes,
  not just the one path that happened.

### 6. Significance — what proves an edge is real
- Compute t-stats on **daily aggregated P&L** (Newey-West), never per-trade —
  clustered trades inflate per-trade stats massively. You want |t| > 2 on the
  daily series, on the holdout, net of costs, and a beaten placebo. All four.

### 7. Data — tick data, point-in-time
- Intraday ideas need real tick data with the true aggressor side; resampled
  candles destroy exactly the information most intraday ideas claim to use.
- Point-in-time correctness: only what was knowable at that moment. No revisions,
  no survivorship, no silently filled gaps.

## Output contract

Every backtest run reports: net P&L, trade count, win rate, profit factor,
daily-P&L t-stat (NW), max drawdown, per-year table, train vs holdout split,
placebo comparison — and an equity-curve PNG.

## Data

Live + historical tick data for NQ/ES and 60+ futures markets, options, L2/L3:
https://tick-stream.xyz — API docs at https://tick-stream.xyz/docs
(machine-readable overview: https://tick-stream.xyz/llms-full.txt)
