rule backtest — trades, equity curve & drawdown, no look-ahead

Rule backtest — every trade, the equity curve and the drawdown

A trading rule is replayed bar by bar over the price path, and the full record is published: every trade, the equity curve, the win rate, average R (the reward-to-risk of a typical trade), profit factor and maximum drawdown — with a note on what each number means. The rule shown is a 20-day moving-average crossover (long when price closes above its 20-day average, exit when it closes below, with an 8% stop). Fills happen at the bar close, so there is no look-ahead, replayed on daily history covering 2021-09-13 → 2026-09-11 (1249 daily bars). Results are gross of costs — no commission, spread or slippage is deducted.

AAPL20-day moving-average crossover, long-only, 8% stopprice history · 2021-09-13 → 2026-09-11 (1249 bars)
52
trades
+42.3%
win rate
3.11R
avg R (win/loss)
2.36
profit factor
-22.78%
max drawdown
+126.45%
total return

Measured over 2021-09-13 → 2026-09-11 (1249 daily bars) · one symbol, one rule, 52 trades. A dash means this sample could not measure that number — it is not a zero.

Assumptions & limitations
Period
2021-09-13 – 2026-09-11
Out-of-sample from
none — whole period in sample
Trades
52
Costs charged
0 bps per side 0 bps commission + 0 bps slippage, charged on every position change

Hypothetical, backtested results — not the record of a traded account. Past results do not predict future returns; the strategy set was chosen with knowledge of the history it is measured on, and no financing, borrow, tax or capacity constraints are modelled. One name’s result does not generalise. There is no out-of-sample split: every bar behind these figures was already available when the rule was chosen.

Equity curve — the rule's running NAV

03126249361248break-even (1.00×)
strategy NAV (starts 1.00×)x = bar index · 1249 bars · 2021-09-13 → 2026-09-11 · exposure +57%
Sharpe0.98Sortino1.45
Calmar0.79Annualized (extrapolated from 1249 bars)+17.94%
Avg win+7.34%Avg loss-2.36%

Fills execute at the bar CLOSE on the signal bar — no look-ahead. Profit factor = gross gains ÷ gross losses; avg R = average win ÷ average loss; max drawdown = the deepest peak-to-trough fall in this curve. A dash is a number this sample could not measure (no losing trade → no profit factor; no drawdown → no Calmar) — never a zero and never an infinity.

The rule under test

sidelong · size 1 · +8% stop
enter whenclose > sma20
exit whenclose < sma20
promotion verdictOBSERVEcleared 4/6 gates · -69.93% under 2x downside
This rule on AAPL over 2021-09-13 → 2026-09-11 (1249 daily bars) returned +126.45% with a +22.78% worst drawdown and Sharpe 0.98; under a 2x downside shock it returns -69.93%. Verdict: observe.
Below, the agent explains each metric — what it measures, why it matters, and what your number suggests — so you can judge a strategy yourself before risking real money. This is replayed on real daily price history over 2021-09-13 → 2026-09-11 (1249 daily bars), gross of trading costs — your decisions, your risk.
What a backtest actually proves (and does not)
We replayed your rule bar-by-bar over AAPL over 2021-09-13 → 2026-09-11 (1249 daily bars) and it made a total return of +126.45% across 52 trade(s).
A backtest replays your exact entry/exit rules over historical bars to see how they WOULD have done. It is a sanity check, not a promise: the future is not the past, and a rule that fits old data can fail live. That is why we also stress it and slice it by market regime before trusting it. It is also gross of costs — no commission, spread or slippage is deducted.
→ It was profitable in this sample — keep validating.
Risk-adjusted return — Sharpe, Sortino, Calmar
Sharpe 0.98, Sortino 1.45, Calmar 0.79.
Return alone is misleading — a strategy that doubles then halves is not "good." Sharpe divides return by total volatility (reward per unit of wiggle). Sortino is the same but only penalises DOWNSIDE wiggle (you do not mind upside surprises). Calmar divides annual return by the worst peak-to-trough drop. Higher is better; Sharpe ≥ 1 is the usual "worth a look" line.
→ Risk-adjusted return is below the usual bar — returns came with a lot of volatility.
The worst it got — max drawdown
The deepest peak-to-trough fall was +22.78%.
Max drawdown is the largest drop from a high-water mark to a later low. It is the question "how much pain would I have had to sit through?" — the number that actually makes people abandon a strategy at the worst moment. A high Sharpe with a 60% drawdown is usually un-tradeable in real life.
→ Drawdown was tolerable (≤ 25%).
Edge quality — hit-rate & profit factor
Hit-rate +42.31%, profit factor 2.36 (avg win +7.34% vs avg loss -2.36%).
Hit-rate is the share of trades that won. But winning often is not the same as making money — profit factor (gross profit ÷ gross loss) tells you whether your winners outweigh your losers. A 40% hit-rate with big wins and small losses beats a 70% hit-rate that gives it all back. Profit factor > 1 means the edge is net positive.
→ Winners comfortably outweigh losers.
Stress test — what 2x downside does
Under a 2x downside shock the same rule returns -69.93% (vs +126.45% unshocked).
We amplify every down-bar move and re-run the rule. It answers "if the bad days were twice as bad, does this strategy still survive?" A rule that only works in calm markets is a trap. Promotion sim→live requires surviving the shock, not just the base case.
→ Falls apart under stress — do not promote.
Promotion verdict: OBSERVE
Cleared 4/6 gates (score 0.67).
Sim-to-live promotion is the whole point: only rules that pass return, risk, drawdown, profit-factor, stress and across-regime checks get handed to the model foundry as a candidate. "Promote" = ship to live paper/real; "observe" = keep collecting data; "reject" = back to the drawing board.
→ Promising but not proven — keep it in sim.

Backtest glossary

Backtest
Replaying a fixed set of trading rules over historical prices to estimate how they would have performed.
Sharpe ratio
Annualised return divided by the volatility of returns — reward per unit of total risk.
Sortino ratio
Like Sharpe but only counts downside volatility in the denominator.
Calmar ratio
Annualised return divided by the maximum drawdown — reward per unit of worst-case pain.
Max drawdown
The largest drop from a peak in the equity curve to a subsequent trough.
Profit factor
Gross profit divided by gross loss; above 1 means the strategy is net profitable.
Exposure
The fraction of bars the strategy was actually in a position (capital at work).
Stress test
Re-running the strategy on a deliberately worse price path to see if it survives bad conditions.
Sim-to-live promotion
The gate that decides whether a paper-traded rule-set is trustworthy enough to run with real consequences.

Trade ledger — all 52 fills

123 @ 143.7642 @ 147.9219 bars+2.89%rule
244 @ 149.9980 @ 174.9236 bars+16.62%rule
396 @ 170.33106 @ 168.6410 bars-0.99%rule
4107 @ 168.88110 @ 168.883 bars+0.00%rule
5130 @ 163.98146 @ 165.7516 bars+1.08%rule
6162 @ 166.02163 @ 156.771 bars-5.57%rule
7179 @ 149.64183 @ 145.384 bars-2.85%rule
8184 @ 146.14187 @ 142.643 bars-2.39%rule
9197 @ 141.66199 @ 137.442 bars-2.98%rule
10202 @ 138.93241 @ 163.6239 bars+17.77%rule
11280 @ 147.27288 @ 145.038 bars-1.52%rule
12294 @ 146.87305 @ 144.2211 bars-1.80%rule
13307 @ 148.03311 @ 142.914 bars-3.46%rule
14335 @ 133.49362 @ 148.4827 bars+11.23%rule
15370 @ 151.03375 @ 148.505 bars-1.68%rule
16376 @ 150.47397 @ 160.1021 bars+6.40%rule
17398 @ 165.56406 @ 163.778 bars-1.08%rule
18408 @ 168.41474 @ 192.5866 bars+14.35%rule
19493 @ 184.12499 @ 177.566 bars-3.56%rule
20519 @ 174.91529 @ 175.4610 bars+0.31%rule
21539 @ 177.57574 @ 193.6035 bars+9.03%rule
22590 @ 188.63599 @ 184.409 bars-2.24%rule
23603 @ 189.30605 @ 188.322 bars-0.52%rule
24632 @ 176.08634 @ 171.372 bars-2.67%rule
25638 @ 173.31639 @ 171.481 bars-1.06%rule
26648 @ 175.04651 @ 169.383 bars-3.23%rule
27658 @ 169.89659 @ 169.301 bars-0.35%rule
28660 @ 173.50662 @ 169.302 bars-2.42%rule
29663 @ 173.03719 @ 218.5456 bars+26.30%rule
30733 @ 221.27748 @ 220.8515 bars-0.19%rule
31759 @ 228.87771 @ 221.6912 bars-3.14%rule
32772 @ 225.77788 @ 230.1016 bars+1.92%rule
33801 @ 228.02831 @ 243.8530 bars+6.94%rule
34847 @ 238.26851 @ 228.014 bars-4.30%rule
35854 @ 233.22855 @ 227.631 bars-2.40%rule
36857 @ 232.62868 @ 237.3011 bars+2.01%rule
37869 @ 241.84870 @ 238.031 bars-1.58%rule
38890 @ 222.13893 @ 204.363 bars-8.00%stop
39906 @ 204.60914 @ 198.898 bars-2.79%rule
40919 @ 210.79925 @ 206.866 bars-1.86%rule
41946 @ 201.00972 @ 211.2726 bars+5.11%rule
42978 @ 213.251002 @ 226.7924 bars+6.35%rule
431004 @ 234.071024 @ 245.2720 bars+4.78%rule
441030 @ 262.241050 @ 267.4620 bars+1.99%rule
451054 @ 271.491069 @ 274.1115 bars+0.97%rule
461099 @ 258.281109 @ 261.7310 bars+1.34%rule
471111 @ 263.881113 @ 260.582 bars-1.25%rule
481115 @ 266.181119 @ 264.184 bars-0.75%rule
491142 @ 255.631188 @ 301.5446 bars+17.96%rule
501205 @ 308.631219 @ 308.9114 bars+0.09%rule
511232 @ 316.831233 @ 311.301 bars-1.75%rule
521237 @ 313.451248 @ 332.2711 bars+6.00%eod

Exit reasons: rule = the exit predicate fired; stop = the protective stop was hit; target = the take-profit was hit; eod = closed at the last bar. Bar index = position in the price path, not a calendar date.