Backtest¶
Output
Graph output — runs the backtest AND drives the chart. Wire entry / exit signals to trade. Indicators render on the chart via per-output eye toggles (legend + node sockets); they do not need to be wired here. SL / TP / lot size accept either an inline value or a wired series (ATR stop, RR target, percent-risk sizing, etc.).
The Backtest block (often just "the Tester") is where every strategy ends. It's the sink: you wire your entry and exit signals into it, and it runs the full backtest and drives the chart at the same time. It turns the graph you've built into an equity curve, a trade list, and the complete metrics pack (Sharpe, profit factor, drawdown, expectancy, and the rest). Nothing happens — no trades, no stats, no honest result — until signals reach this block. It is the single most important node on the canvas.
How it works¶
You don't wire bars in. The backtest runs on the bars from your Data Source / the chart header automatically, so it always trades the same symbol and timeframe you're looking at — you only wire signals and risk legs here, never price bars.
Entries and exits. Wire a boolean into Buy to go long when it's true, Sell to go short. Exit Long / Exit Short close an open position for reasons that aren't a fixed price — an oscillator threshold, a time-of-day rule, a structure break. Signal-based entries and exits fill at the next bar's open (honest — no acting on the close that fired the signal, which is the classic lookahead trap). Exits resolve in a strict priority each bar: a hit SL or TP wins over an Exit signal, which wins over the time stop.
Risk legs are inline-or-wired. SL, TP, and Lot each take either the slider value on the node or a wired series — and the wired series overrides the slider per bar. That's how you get a volatility stop (wire ATR×N into SL), a reward-multiple target (wire an Tester into TP), or percent-risk sizing (wire a series into Lot). Each leg has an Enable toggle; turn SL or TP off and the trade exits only on a signal, the other leg, or end of data.
The trade-management stack layers on top of any open position:
- Trailing stop — once in profit, the SL ratchets to (best price reached − Trail pips) and never loosens. Crucial gotcha: with no trigger it arms on the first profitable bar, so a tight trail + wide SL stops you out on the first wiggle. Set Trail trigger ≥ your SL distance so the trail only engages after the trade is ~1R in profit ("lock in a winner").
- Break-even — move the SL to entry once profit reaches BE pips, so a winner can't become a loser. BE offset lets you lock partial profit (offset 5 = "lock 5 pips").
- Time stop — close at the next open once a trade has been open Time stop bars; for "if it hasn't worked in N bars, it won't," and for capping mean-reversion duration.
Entry order types. Market fills at the next open (default). Limit rests an order that fills when price returns to the level — pullback entries. Stop rests an order that fills when price breaks through the level — breakout entries. The level is the wired Entry @ socket (an FVG edge, pivot, MA) or the signal-bar close ± Entry offset. Unfilled orders cancel after Entry expiry bars (0 = good-till-filled within the data).
Scaling and pyramiding. Partial TP banks TP1 close % of the position at TP1 pips and lets the rest run to the full TP; pair with SL→BE after TP1 for a risk-free runner. Max positions > 1 enables pyramiding — that many independent same-direction entries (each with its own SL/TP/sizing), with an opposite signal closing the whole stack and new entries still gated by free margin.
Account realities live on the Tester panel, not the block. Starting balance, leverage, spread, commission, slippage, and risk-based sizing are set on the panel — so the strategy stays portable across accounts, and your costs are modelled in one place.
Indicators don't need wiring. Any indicator's plot renders on the chart through its own eye toggle (legend + node socket) — you only wire signals into the Tester, not the lines you want to see.
When to use it¶
Always — it's the terminal block of any backtestable strategy. Build your logic, wire the final entry/exit signals here, set or wire your risk legs, and run. Start simple (Buy + SL + TP), confirm the idea has an edge on realistic costs, then layer on trailing, break-even, partials, and pyramiding one at a time so you can see what each change actually does to the equity curve.
Example¶
A complete trend-pullback long: wire a Crosses Above entry into Buy, an ATR×2 series into SL for a volatility stop, an Tester of 2× into TP, and enable the trailing stop with Trail trigger set to your SL distance so it only ratchets after 1R of profit. Run it, read the equity curve, drawdown, and trade list — then toggle SL→BE after TP1 on and compare. That's how you learn whether each rule earns its place.
Tips & gotchas¶
- Nothing runs until signals reach here. No Buy/Sell wired = no trades, no stats.
- The trail trigger is the #1 footgun. Trailing with trigger 0 + a wide SL tightens aggressively and stops you out early. Set trigger ≥ SL distance.
- Costs are not optional. Set spread, commission, and slippage on the panel before you trust any number — a strategy that only profits at zero cost is not profitable.
- Signal exits fill next-bar-open; SL/TP wins ties. Honest fills, no same-bar-close peeking; design oscillator/structure exits knowing they're the lower-priority path.
- Wired risk legs override the sliders per bar — that's the whole point of ATR stops and Testers.
- Add complexity one layer at a time. Trailing + BE + partials + pyramiding interact; enable them individually so you can attribute the effect.
- You wire signals, not plots. Indicators show via eye toggles — don't wire a line in expecting a trade.
Related blocks¶
Inputs¶
| Socket | Type | What to wire in |
|---|---|---|
| Buy (optional) | signal |
Enter long when this signal is true |
| Sell (optional) | signal |
Enter short when this signal is true |
| Exit Long (optional) | signal |
Close any open long when this signal is true. Use for exits that aren't a fixed price level (oscillator thresholds, time-of-day exits, structure breaks). Fills at next bar's open. SL/TP still wins if both fire. |
| Exit Short (optional) | signal |
Close any open short when this signal is true. Mirror of Exit Long for short positions. |
| SL (optional) | series |
Per-bar stop loss in pips (wire ATR*N, etc.). Falls back to the inline value when not wired. |
| TP (optional) | series |
Per-bar take profit in pips. Falls back to the inline value when not wired. |
| Lot (optional) | series |
Per-bar lot size. Overrides the account's risk-based sizing. Falls back to the inline value when not wired. |
| Entry @ (optional) | series |
Pending-entry price LEVEL (absolute price), used only when Entry order type is Limit or Stop. Wire a level (e.g. an FVG edge, pivot, MA). When not wired, the order rests at the signal bar's close ± Entry offset. |
| Trail (optional) | series |
Trailing-stop distance in pips. Once a trade is in profit, SL ratchets to (favorable extreme − this many pips). Never loosens. 0 disables. ⚠ With trigger=0, trail arms on the FIRST profitable bar — a tight trail (e.g. 5 pips) combined with a wider SL (e.g. 20 pips) will tighten the SL aggressively and likely stop you out on a small pullback. To trail only after meaningful profit, set trail_trigger_pips ≥ your SL distance. |
| Trail trigger (optional) | series |
Profit threshold (pips) that arms the trailing stop. While profit is below this, SL stays at its original level. 0 = trail from the first profitable bar (aggressive — see Trail's warning). Recommended: set trigger ≥ your SL distance so trailing only kicks in after the trade is at least 1R in profit ('lock in a winner' semantics). |
| BE (optional) | series |
Profit threshold (pips) at which SL moves to entry price. Locks in no-loss once the trade has run far enough. 0 disables. |
| BE offset (optional) | series |
When BE fires, target SL = entry ± this offset instead of plain entry. 0 = lock at entry. Positive offset locks partial profit (e.g. offset = 5 → 'lock 5 pips'; offset = 0.25 × SL distance → 'lock 0.25R'). |
| Time stop (optional) | series |
Close at the next bar's open once the trade has been open for ≥ this many bars. Useful for 'if the idea hasn't worked in N bars it isn't going to' exits and for capping trade duration in mean-reversion strategies. |
| Trail level (optional) | series |
Per-bar ABSOLUTE price the stop-loss ratchets toward (needs 'Enable trail-to-level'). Wire a trailing level — e.g. RunningMinSince / RollingMin of the low for a long, or a swing / chandelier / MA line. The SL only tightens toward it, never loosens. This is how you make the SL follow the last-N-bar low/high. |
Parameters¶
| Parameter | Type | Default | What it does |
|---|---|---|---|
| Enable SL | on / off | True |
When off, no stop-loss exit fires regardless of the SL slider value or anything wired to the SL socket. Trade exits only on TP, signal, or end of data. |
| SL unit | choice (auto, pips, percent, atr, price) |
auto |
How the SL is read. auto = ATR-based (volatility-scaled — self-adapts to each pair, the recommended default). pips = fixed pip distance. percent = percent of the entry price. atr = a multiple of ATR. price = the wired SL socket is an ABSOLUTE price level (a swing / pivot / NearestLevel), captured at entry. (Wiring the socket is pips unless the unit is 'price'.) |
| SL | number · 0.1–500.0 | 20.0 |
Inline stop distance, read in the unit chosen by 'SL unit' (pips, or % of price). Ignored when the sl socket is wired. |
| Enable TP | on / off | True |
When off, no take-profit exit fires regardless of the TP slider value or anything wired to the TP socket. Trade exits only on SL, signal, or end of data. |
| TP unit | choice (auto, pips, percent, atr, price) |
auto |
How the TP is read. auto = ATR-based (volatility-scaled — self-adapts to each pair). pips = fixed pip distance. percent = percent of the entry price. atr = a multiple of ATR. price = the wired TP socket is an ABSOLUTE price level (e.g. the next support/resistance), captured at entry — 'put the TP at the next level'. (Wiring the socket is pips unless the unit is 'price'.) |
| TP | number · 0.1–2000.0 | 40.0 |
Inline target distance, read in the unit chosen by 'TP unit' (pips, or % of price). Ignored when the tp socket is wired. |
| ATR period | number · 2–200 | 14 |
Lookback for the ATR used when SL or TP unit is 'atr' (Wilder smoothing). Ignored for pips/percent. |
| Lot size | number · 0.01–100.0 | 0.1 |
Inline fallback when the lot_size socket is not wired. Unit: standard lots. |
| Enable trail | on / off | False |
When off, no trailing-stop logic runs regardless of the slider value or anything wired to the Trail socket. |
| Trail (pips) | number · 0.0–500.0 | 10.0 |
Trailing-stop distance, used when the Trail socket is not wired. Tight trail + wide SL with trigger=0 stops out aggressively — see the Trail socket's tooltip for the safe pattern. |
| Enable trail trigger | on / off | False |
When off, trailing (if enabled) arms on the FIRST profitable bar — same as setting trigger to 0. When on, trailing only arms after profit reaches the trigger. |
| Trail trigger (pips) | number · 0.0–500.0 | 20.0 |
Profit (pips) before trailing arms. Set ≥ SL distance to trail only after 1R profit. |
| Enable trail-to-level | on / off | False |
When on, the SL ratchets toward the price wired to the 'Trail level' socket (a RunningMinSince/RollingMin of lows, a swing, an MA…). Only tightens, never loosens. Independent of the pip-based trailing stop above. No effect unless the socket is wired. |
| Enable BE | on / off | False |
When off, no break-even SL move happens regardless of the slider value or anything wired to the BE socket. |
| BE (pips) | number · 0.0–500.0 | 20.0 |
Profit (pips) at which SL moves to entry price. |
| BE offset (pips) | number · -500.0–500.0 | 0.0 |
Lock SL at entry ± this offset when BE fires. 0 = exact entry. Positive = lock partial profit. |
| Enable time stop | on / off | False |
When off, no time-based exit fires. When on, the trade closes at the next bar's open once it has been open for ≥ the configured number of bars. |
| Time stop (bars) | number · 1–10000 | 50 |
Maximum trade age in bars. Inline fallback used when the Time stop socket is not wired. |
| Entry order | choice (market, limit, stop) |
market |
How a trade opens once your strategy signals. • Market — open right away at the next bar's price (simplest, default). • Limit — wait for price to come BACK to your level first (buying the dip). • Stop — wait for price to PUSH PAST your level first (buying the breakout). The level is the 'Entry @' input if you wire one, otherwise the signal bar's close shifted by 'Entry offset'. |
| Entry offset (pips) | number · 0.0–1000.0 | 10.0 |
Only used for Limit/Stop entries with no 'Entry @' wire. How far from the signal bar's close to place the order, in pips (e.g. 10 = 0.0010 on EUR/USD). Buy-limits/sell-stops sit below price; buy-stops/sell-limits sit above. |
| Entry expiry (bars) | number · 0–100000 | 0 |
For Limit/Stop entries: if the order hasn't filled after this many bars, cancel it. 0 = leave it resting until it fills (or the data ends). |
| Partial TP (scale-out) | on / off | False |
Bank part of the trade at a nearer target (TP1), then let the rest ride to the full take-profit. Off = the whole position closes at once (the normal behaviour). |
| TP1 (pips) | number · 0.0–10000.0 | 20.0 |
How far in profit (in pips) the first, partial target sits — e.g. 20. Keep it NEARER than your full take-profit, or it never triggers. Defaults to 20 when Partial TP is on. |
| TP1 close % | number · 1.0–99.0 | 50.0 |
What share of the position to close at TP1 — e.g. 50 means sell half there and let the other half run to the full target, stop, or exit signal. |
| SL→BE after TP1 | on / off | False |
After TP1 banks profit, slide the stop-loss up to your entry price so the rest of the trade can't end in a loss — a 'risk-free runner'. |
| Max positions | number · 1–20 | 1 |
How many trades in the SAME direction can be open at once (pyramiding / adding to a winner). 1 = only ever one at a time (default). Each add has its own stop, target and size; an opposite-side signal closes them all; new adds still need free margin. |
Reference auto-generated from the block catalog · category Output.