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 daily bars. Output: each trade, the equity curve, win rate, average R (average win ÷ average loss), profit factor and maximum drawdown. The rule shown is a 20-day moving-average crossover (long when the close is above its 20-day average, exit when it closes below, 8% stop). Fills happen at the bar close, so there is no look-ahead, replayed on daily history covering 2021-11-09 → 2026-11-12 (1258 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-11-09 → 2026-11-12 (1258 bars)
55
trades
+41.8%
win rate
2.76R
avg R (win/loss)
2.05
profit factor
-22.78%
max drawdown
+90.58%
total return

Measured over 2021-11-09 → 2026-11-12 (1258 daily bars) · one symbol, one rule, 55 trades. A dash marks a figure this sample cannot measure.

Assumptions & limitations
Period
2021-11-09 – 2026-11-12
Out-of-sample from
none — whole period in sample
Trades
55
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

03146299431257break-even (1.00×)
strategy NAV (starts 1.00×)x = bar index · 1258 bars · 2021-11-09 → 2026-11-12 · exposure +57%
Sharpe0.80Sortino1.16
Calmar0.61Annualized (extrapolated from 1258 bars)+13.80%
Avg win+6.34%Avg loss-2.30%

Fills at the close of the signal bar (no look-ahead). Profit factor = gross gains ÷ gross losses; average R = average win ÷ average loss; maximum drawdown = deepest peak-to-trough decline of the equity curve. A dash marks a figure this sample cannot measure: with no losing trade there is no profit factor, and with no drawdown there is no Calmar.

The rule under test

sidelong · size 1 · +8% stop
enter whenclose > sma20
exit whenclose < sma20
promotion resultOBSERVE4 of 6 gates passed · total return -69.60% under the 2x downside stress scenario
This rule on AAPL over 2021-11-09 → 2026-11-12 (1258 daily bars) returned +90.58% with a +22.78% worst drawdown and Sharpe 0.8; under a 2x downside shock it returns -69.6%. 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-11-09 → 2026-11-12 (1258 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-11-09 → 2026-11-12 (1258 daily bars) and it made a total return of +90.58% across 55 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.8, Sortino 1.16, Calmar 0.61.
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 +41.82%, profit factor 2.05 (avg win +6.34% vs avg loss -2.3%).
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.6% (vs +90.58% 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 — 55 trades

119 @ 171.1839 @ 174.9220 bars+2.18%rule
255 @ 170.3365 @ 168.6410 bars-0.99%rule
366 @ 168.8869 @ 168.883 bars+0.00%rule
489 @ 163.98105 @ 165.7516 bars+1.08%rule
5121 @ 166.02122 @ 156.771 bars-5.57%rule
6138 @ 149.64142 @ 145.384 bars-2.85%rule
7143 @ 146.14146 @ 142.643 bars-2.39%rule
8156 @ 141.66158 @ 137.442 bars-2.98%rule
9161 @ 138.93200 @ 163.6239 bars+17.77%rule
10239 @ 147.27247 @ 145.038 bars-1.52%rule
11253 @ 146.87264 @ 144.2211 bars-1.80%rule
12266 @ 148.03270 @ 142.914 bars-3.46%rule
13294 @ 133.49321 @ 148.4827 bars+11.23%rule
14329 @ 151.03334 @ 148.505 bars-1.68%rule
15335 @ 150.47356 @ 160.1021 bars+6.40%rule
16357 @ 165.56365 @ 163.778 bars-1.08%rule
17367 @ 168.41433 @ 192.5866 bars+14.35%rule
18452 @ 184.12458 @ 177.566 bars-3.56%rule
19478 @ 174.91488 @ 175.4610 bars+0.31%rule
20498 @ 177.57533 @ 193.6035 bars+9.03%rule
21549 @ 188.63558 @ 184.409 bars-2.24%rule
22562 @ 189.30564 @ 188.322 bars-0.52%rule
23591 @ 176.08593 @ 171.372 bars-2.67%rule
24597 @ 173.31598 @ 171.481 bars-1.06%rule
25607 @ 175.04610 @ 169.383 bars-3.23%rule
26617 @ 169.89618 @ 169.301 bars-0.35%rule
27619 @ 173.50621 @ 169.302 bars-2.42%rule
28622 @ 173.03678 @ 218.5456 bars+26.30%rule
29692 @ 221.27707 @ 220.8515 bars-0.19%rule
30718 @ 228.87730 @ 221.6912 bars-3.14%rule
31731 @ 225.77747 @ 230.1016 bars+1.92%rule
32760 @ 228.02790 @ 243.8530 bars+6.94%rule
33806 @ 238.26810 @ 228.014 bars-4.30%rule
34813 @ 233.22814 @ 227.631 bars-2.40%rule
35816 @ 232.62827 @ 237.3011 bars+2.01%rule
36828 @ 241.84829 @ 238.031 bars-1.58%rule
37849 @ 222.13852 @ 204.363 bars-8.00%stop
38865 @ 204.60873 @ 198.898 bars-2.79%rule
39878 @ 210.79884 @ 206.866 bars-1.86%rule
40905 @ 201.00931 @ 211.2726 bars+5.11%rule
41937 @ 213.25961 @ 226.7924 bars+6.35%rule
42963 @ 234.07983 @ 245.2720 bars+4.78%rule
43989 @ 262.241009 @ 267.4620 bars+1.99%rule
441013 @ 271.491028 @ 274.1115 bars+0.97%rule
451058 @ 258.281068 @ 261.7310 bars+1.34%rule
461070 @ 263.881072 @ 260.582 bars-1.25%rule
471074 @ 266.181078 @ 264.184 bars-0.75%rule
481101 @ 255.631147 @ 301.5446 bars+17.96%rule
491164 @ 308.631184 @ 308.9120 bars+0.09%rule
501197 @ 316.831198 @ 311.301 bars-1.75%rule
511202 @ 313.451225 @ 329.4023 bars+5.09%rule
521226 @ 333.021227 @ 330.321 bars-0.81%rule
531228 @ 333.691249 @ 338.3221 bars+1.39%rule
541251 @ 349.511253 @ 342.372 bars-2.04%rule
551254 @ 350.691257 @ 354.883 bars+1.19%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.