Backtest, replay and stress-test trading strategies

A backtester, a replay simulator, situational search and a journal — and the honest limits of each.

Backtest a trading strategy without writing code

Say the rule out loud, build it as a rule tree, and see what it did over years of 1-minute history — including the days it would not have traded.

Most intraday strategies are already written down somewhere — in a notebook, in a Discord message, in the sentence you say to yourself at 9:31. "Long the break of the second 15-minute bar, stop under it, take twice the bar's height." That is a complete, testable specification. The only thing standing between it and four years of evidence is usually a Python environment and a week of plumbing.

Strategy Lab takes the specification directly. You describe the strategy as a rule tree in the browser, and the engine replays it across historical sessions bar by bar.

Strategy → result
TriggerBreak of 15m bar #2 (long)
StopOpposite side of bar #2
Target2 × bar height
SessionOne trade per day, flat by 15:30
Trades211
Win rate41%
Profit factor1.06
Expectancy+0.8 pts
Max drawdown−212 pts

418 days scanned, 211 traded. No trade on the rest: ref bar does not exist (124), ref bar closed against entry side (83).

Illustrative figures, not a published result. A profit factor near 1.0 is what an unfiltered breakout usually looks like before costs — which is the honest version of this demo.

What you can express

  • Entries. The break of a reference bar, the close of a reference bar, or the break of the overnight range. The reference bar is any of the first few 5-minute or 15-minute bars of the session, or the pre-open bar. Long, short, or both ways — a both-ways rule mirrors itself rather than making you hand-build the short leg. Any trigger can be faded instead of followed, and armed for a limited number of bars.
  • Patterns, not just levels. Consecutive-bar streaks, double tops and bottoms, support and resistance retests — each usable as the condition half of a condition → action chain, so "after a three-bar down streak, fade the next break" becomes a rule instead of a judgement call.
  • Stops and targets. Stops at the opposite side of the reference bar, a fixed distance, or a multiple of that bar's height. Targets as an R-multiple, fixed points, a multiple of bar height, or a price level read off a reference bar. Trailing and pyramiding are part of the definition, not an adjustment you make afterwards.
  • Session and day gates. Earliest and latest entry time, a forced flat time, one trade per day — plus day filters, so a strategy can be restricted to gap-up days, or to days whose early bar structure matches a particular shape.

What comes back

The headline statistics — trades, win rate, net points, profit factor, expectancy and maximum drawdown — plus the equity curve, a drawdown series, the breakdown by exit reason, R-multiple and streak analysis, a month-by-month matrix, a rolling win rate, and how far price ran in your favour before each trade actually closed.

It also reports the days it didn't trade, and why: the reference bar never existed, the bar closed against the entry side, there was no overnight range that day, the day was filtered out. A strategy that looks excellent over eleven trades in four years is a completely different object from one that trades every session, and the no-trade breakdown is where that difference shows up first. What counts as enough is not a round number like 100 — it falls out of the strategy's own signal-to-noise ratio.

Every run states its execution assumptions instead of burying them: signals are read on the reference timeframe but execution is replayed on 1-minute bars; when a stop and a target are both reachable inside the same bar, the stop is taken first; a gap through a level fills at the bar open, not at the level; and slippage and commission are zero. That last one is deliberate, and it matters — one tick of slippage was enough to erase the entire gross profit of a four-year, 5,069-trade result we published.

Tell whether a backtested edge is overfitted

Three independent checks: a train/test split with a stated verdict, resampled equity curves, and a sweep that rewards plateaus over peaks.

A rule builder expressive enough to describe a real strategy is expressive enough to describe noise. Nudge the stop by five points, move the cut-off time, try the other timeframe — after twenty variations something will look excellent, and it will look excellent for the same reason a coin that came up heads eight times looks lucky rather than weighted. The reported result stops being a typical outcome and becomes a maximum over however many things you tried.

This is the failure mode the product is most opinionated about, so the checks are built in rather than left as an exercise.

The in-sample / out-of-sample split

Every backtest can be partitioned at a date: the earlier trades are the ones you tuned on, the later ones are the ones the rules had never seen. Both sides get their own full summary, side by side, and the split verdict is stated plainly rather than left for you to eyeball. Three specific degradations are called out — in-sample made points while out-of-sample lost them; out-of-sample expectancy came in under half the in-sample figure; in-sample profit factor was strong while out-of-sample fell below 1.

In-sample / out-of-sample
In-sampleOut-of-sample
Trades14863
Win rate47%35%
Profit factor1.710.82
Expectancy+2.4 pts−1.1 pts

DegradedIn-sample profit factor was strong, but out-of-sample is below 1 — it loses money on unseen data.

Illustrative figures. This is the shape a curve-fit makes: strong on the half the rules were tuned on, gone on the half they had never seen.

The default boundary puts about 70% of trades in the training half and snaps forward to a session start, so a single day never straddles the split, and you can move it. Under 20 trades on either side the result is labelled low-sample instead of pretending to a verdict — noise, not evidence either way. The split always partitions all the trades in the run, never whatever window you happen to be zoomed into; an overfit check that quietly covers half the data is the exact thing it exists to catch. This is a single train/test cut, not a rolling walk-forward.

Monte Carlo resampling

A split tells you whether the edge survives new data. Monte Carlo tells you how much of the equity curve's shape was the order the trades happened to arrive in. The realised trade outcomes are resampled hundreds of times — shuffled, keeping the same win rate and profit factor but a different sequence, or bootstrapped with replacement, which additionally stresses how much the result leans on a handful of outlier trades. You get a median path with a 5th-to-95th-percentile band around your actual curve, the share of simulations that end net negative, and where your realised drawdown ranks among them. A drawdown at the 90th percentile of simulations is not the drawdown to plan around.

Parameter sweeps, with a plateau check

Sweeping a parameter is how curve-fits are usually manufactured, so the sweep is built to expose them instead. Up to twenty combinations run at once, every cell scored and split at one shared calendar boundary — a per-cell boundary would give each variant a different test period and quietly stop being a comparison at all. The grid then gets a plateau check: a peak surrounded by neighbours that performed badly is a fit to the sample, while a broad region that all works is closer to an edge. The former is the shape you should distrust, and it is the shape a leaderboard sorted by net points hands you first.

None of this makes overfitting impossible. The out-of-sample half is only out-of-sample once — the moment you re-tune after seeing it, it has become training data, and the honest move is to say so. Why your backtest lies covers the biases these tools cannot see, and what a realistic profit factor looks like covers the range that should make you go looking for a bug.

Replay historical market sessions bar by bar

The ending is hidden, the orders fill on real price, and every trade records how far it went against you before it worked.

A backtest answers what a rule would have done. It cannot answer whether you would have done it — whether you would have taken the entry after three losers, or moved the stop at the moment the bar went against you. Reading a completed chart left to right is no help either: once you can see the right-hand side, every entry is obvious and every exit is early. You need the session to arrive one bar at a time, with the ending genuinely unknown.

Market Replay does that with real historical sessions. Bars print forward at your pace, the rest of the day is hidden, and you trade it as it comes.

How a session is built

A replay session is a queue of days, and the queue comes from a search — so you can drill one specific situation rather than whatever days happen to be next on the calendar. Fifty gap-up Mondays. Every session that broke the opening range downward and closed higher. Optionally the queue is randomised, which matters more than it sounds: dates are recognisable, and knowing you are looking at a well-remembered session is enough to contaminate the rehearsal. Progress is checkpointed at the bar, so a session survives closing the tab.

What you can do inside one

  • Real order types. Market, limit and stop orders, long or short, with stops and targets attached and adjustable while the trade is live — including on the chart itself. Working orders fill when price actually reaches them, not when you decide they would have.
  • Sizing in money. Set dollars per point and the trade log is in P&L, not in abstract points, which is the unit your risk tolerance is actually calibrated in.
  • Notes per day. Written while the outcome is still unknown, which is the only time a note about your reasoning is worth anything.

What it records

Every filled trade keeps its entry and exit, the exit reason, and two numbers that only exist because the engine can see the bars you couldn't: maximum adverse and maximum favourable excursion — how far the trade went against you before it worked, and how far it ran before you closed it. A trade log full of winners that first went 15 points against you is a different story from the same log with 3-point excursions, and it is the fastest way to find out that your stop is in the wrong place.

The stop as it stood at the fill is recorded separately and never overwritten, so dragging the stop to breakeven later doesn't quietly rewrite what you were risking when you took the trade. Without that, every R-multiple in the log is flattering by construction.

Replay is practice and it produces a sample like any other — twenty replayed sessions is a feel for the setup, not a measurement of it. When you want the measurement, put the same rules through a backtest and read how many trades that actually takes.

Find historical days that look like today

Describe the session you are looking at as filters, and get back every historical day that matched — all of them, not the two you remember.

"Gapped up 40 points, faded the first fifteen minutes, still above yesterday's close." That sentence describes today, and it also describes some number of days in the last several years. How many of them closed the gap? How many kept going? That is a base rate, it is knowable, and almost nobody looks it up — because looking it up normally means writing a script against data you don't have.

Situational search is that lookup. You describe the shape of a session and get back every historical day that matched it.

What you can filter on

  • The gap. Direction, and a minimum and maximum size in points — so "gapped up" can mean 10 points or 60, which are not the same market.
  • Early bar structure. The direction and type of the opening 5-minute and 15-minute bars, stackable at different offsets, so you can specify the first three bars rather than just the first.
  • What happened to the gap. Whether it closed within the first two 15-minute bars, and whether it closed on a news release — two very different reasons for the same chart shape.
  • The rest of the day. Daily change, whether the opening range broke, day of week, and specific dates excluded when you want a period gone.

What you get back

Every matching session, grouped by month so the distribution over time is visible at a glance — thirty matches that all fell in one quarter is a regime, not a pattern. Each one opens on an intraday candlestick chart across multiple timeframes with the opening range boxed, the gap marked, and a measure tool for the move you actually care about. The point isn't the count. It's that you can look at all forty of them in a few minutes and notice the thing no filter would have described.

Searches you rely on can be saved and re-run in a click as new sessions print, and any search can be handed straight to Market Replay as a session queue or reused as the day filter on a backtest — so "these are the days that look like today" becomes "these are the days I'm going to rehearse" or "this is the population my strategy is tested against" without rebuilding the query.

A base rate over eleven matching days is a story, not a statistic, and search makes it very easy to filter your way down to eleven days that agree with you. Watch the match count as hard as you watch the outcome — the arithmetic of how much evidence you need applies to a sample of days exactly as it applies to a sample of trades.

Keep an honest record of what you actually traded

Enter one number a day. Drawdown, streaks, weekday patterns and deposit-adjusted returns all derive themselves from it.

Ask a trader how last quarter went and you'll usually get a story: a couple of memorable losses, one very good week, and a general sense of roughly breaking even. The story is almost never the arithmetic. Memory over-weights the trades that hurt, under-weights the flat days entirely, and quietly counts a deposit as progress.

The Journal exists to replace the story with the number. One journal per broker account, one entry per day: the day's P&L, and a note if you want one.

What it derives

Everything else falls out of those entries — trading days, green and red day counts, average green day against average red day, best and worst, expectancy per day, profit factor across days, peak-to-trough drawdown on the equity curve, current streak, longest winning and losing runs, and a steadiness figure — average daily P&L over its standard deviation, the same idea as a Sharpe ratio applied to your own days.

Alongside that: an equity curve, a daily P&L histogram, a weekday breakdown, and a month-by-month matrix. The weekday view is the one that most often surprises people. A single bad weekday can carry an entire year of results, and no amount of reviewing individual trades will surface it, because the pattern doesn't exist at the level of a trade.

Deposits are not profit

Deposits and withdrawals are logged in a separate cash-flow ledger, and the Journal tracks two distinct lines because they answer two different questions: account performance, which is your trading P&L alone, and net worth, which includes the money you put in and took out. Returns are expressed against the balance the period actually opened with.

This is not a technicality. Funding a drawdown and watching the balance recover is the single most common way a losing period gets recorded as a flat one — the account is bigger, so it feels like nothing went wrong. Two separate lines make that impossible to tell yourself.

This is a daily P&L journal, deliberately: you enter one number per day, and there is no broker sync and no per-trade import. The rehearsal record with individual fills, stops and excursions lives in Market Replay instead. If you want per-trade attribution on live orders out of your broker, this isn't that tool — and a daily journal you actually fill in beats a per-trade one you abandon in March. What the numbers mean once you have them is covered in what a realistic profit factor looks like.

Which markets you can test, and how far back

18 futures markets at 1-minute resolution back to 2020 — and a plain statement of what a 2020 floor cannot tell you.

Every claim on this page rests on the same thing: minute-resolution history you can actually query. So it's worth being specific about what that covers, because "years of data" is the vaguest sentence in this industry.

The markets

18 futures markets. Index futures across three continents — DOW, DAX, Nasdaq, S&P, Russell, Nikkei, FTSE and Euro Stoxx — plus metals, energy, treasuries and grains, all in one workspace and all queryable the same way. Session boundaries, opening ranges and gaps are computed per market against its own trading hours, which is the part that quietly breaks when a tool treats every instrument as if it opened at the New York bell.

What isn't here: single-name equities, FX pairs and crypto. The product is built around the structure of an index-futures session — the gap, the opening range, the early bars — and that framing doesn't transfer cleanly to a 24-hour market with no open.

The history

One-minute bars back to 2020. That is the resolution the backtest engine replays execution on, not just the resolution charts are drawn at — the two are frequently confused, and a strategy tested on 15-minute bars while claiming intrabar stop behaviour is making things up about the fills.

Since 2020 the archive spans a genuinely useful spread of regimes: the 2020 volatility, the 2021 grind, the 2022 trend down, and the range-bound years after it. That matters more than raw length. A strategy that only ever saw one regime hasn't been tested, it has been described — which is the whole argument for the out-of-sample split.

It is also, honestly, a limit worth stating: this is not a twenty-year archive, so it cannot tell you how a setup behaved in 2008. Anyone quoting you a profit factor from data they can't show you should be asked which years it covers.

Free vs Pro. A free account reaches back 60 days — enough to see how the tools behave on real data, not enough to make a claim about an edge. Pro opens the full archive with arbitrary date ranges, which is what the split, the sweep and the base-rate lookups all need. See pricing for the caps.