# Backtest engine

> How ChartRider simulates Trade Setup and WickScript trades – signals at candle close, market, limit and stop fills, stop before target, exits, position size, leverage, liquidation, fees and no lookahead.

Updated: 2026-10-25T01:30:08.000Z · https://chartrider.com/docs/strategies/backtest-engine/

**Backtest** (`F5`) and **Run strategy** use the same engine. It walks through the candles one by one, decides at each candle close, and books the trades into a simulated account in USDT. A [Trade Setup](https://chartrider.com/docs/strategies/trade-setup/) and a [WickScript strategy](https://chartrider.com/docs/wickscript/strategies/) are simulated with the same rules; WickScript only adds more ways to enter and manage a trade.

## Candles

- A backtest runs on the candles of the chart's timeframe. They are built from 1-minute candles on a UTC grid.
- Fills are decided from each candle's open, high, low and close. Ticks and the order book are not used for fills.
- **Backtest** uses the candles loaded on the chart; scrolling further back loads more history and recalculates. **Run strategy** loads the candles of each run's period – the Range or one date window.
- Indicators are calculated on the run's own candles, starting at the first candle of its period. An indicator needs some candles before it has values (a 50-period EMA needs 50); until then triggers and exits don't fire and filters let entries through. Short windows therefore lose a few candles at their start.
- On a live chart the last candle is still forming. No decision is taken on it until it has closed.

## Order of events in a candle

For every candle the engine does this, in this order:

1. **The open position**, from the candle after its entry on: first the stop, then partial targets (nearest to the entry first), then the target.
2. **A pending limit or stop order**: it expires, fills, or – a limit order – is dropped because the target was reached first.
3. **At the close**: exits (exit gates, `exit … when`), then stop adjustments (breakeven, trailing), then new triggers.

Everything a decision uses comes from candles up to and including the current one.

## Signals

- A **trigger** fires on the candle where its rule becomes true – true at this close, false at the one before. It does not fire again while the rule stays true.
- **Filters** are checked at the trigger candle.
- If long and short trigger on the same candle, there is no entry.
- A trigger is skipped while a position or order is open, or during the cooldown. The **Last F5** line of the Trade Setup counts every skipped trigger with its reason.

In WickScript, an `enter` inside a `when … end` block follows the same rule; an `enter` that runs on every candle (for example inside a plain `if`) acts on every candle where it runs.

## Entries

| Entry | Price | When |
|---|---|---|
| **Market** | Close of the trigger candle | Immediately at that close |
| **Limit** | The limit price | From the next candle on, as soon as the low (long) or high (short) touches it |
| **Stop** (WickScript only) | The stop price | From the next candle on, as soon as the high (long) or low (short) touches it |

- A long limit must lie below the close of the trigger candle and a long stop entry above it (mirrored for shorts); otherwise the trigger is skipped.
- Fills are exactly at the order price, also when a candle opens beyond it.
- An order that hasn't filled after **Valid bars** candles (default 10; WickScript `valid N bars`) expires.
- A limit order is dropped if the price reaches the target before the order fills.
- Filters are not checked again when the order fills.
- On the candle in which a limit or stop order fills, its stop already counts – the trade can be stopped out in its fill candle – but its target does not, because the order of prices inside the candle is unknown.

## Stop and target inside a candle

- A long is stopped when the low reaches the stop and reaches its target when the high reaches the target; shorts are mirrored. Touching the level is enough.
- **If a candle reaches both the stop and the target, the engine assumes the stop came first.** This is the cautious assumption: when a candle can't tell which level came first, the trade counts as stopped.
- Stops and targets fill exactly at their price, so a loss is at most 1 R before fees, even if the candle gapped beyond the stop (unless the position is liquidated – see below).
- Checks start on the candle after a market entry.

## Exits

- **Stop** and **target** as above. The stop is required for every trade; the target is optional when an exit gate (or a WickScript `exit`) covers that side.
- **Exit gates** and `exit … when` close the position at the close of the candle where their rule becomes true for the position's side – never on the entry candle.
- **Cooldown** blocks new triggers for that many candles after an exit. With a cooldown of 0, a new trade can open at the close of the exit candle.
- A position still open at the end of the data is closed at the last close (shown as **open at end**).

### Managing a trade (WickScript)

WickScript strategies can also manage an open trade. The Trade Setup has none of these.

- **Partial exits** – `exit half at 1R`, `exit 30% at …`: a share of the original size is closed when the price reaches the level, inside the candle, after the stop check and before the target. `exit half when …` scales out at the close.
- **Breakeven** – `move stop to entry after 1R`: once the best price since entry has reached 1 R, the stop moves to the entry price at that candle's close and counts from the next candle. The fee is not covered, so a breakeven exit is a small loss after fees.
- **Trailing stop** – `trail stop by … [after nR]`: at each close the stop follows the best high (long) or low (short) since entry at a fixed distance.
- A stop only ever moves in the direction of profit, and only while it stays on the right side of the close.

## One position at a time

A strategy holds at most one position per market: no adding to a position, no long and short at the same time, and no reversal on an opposite signal – the opposite trigger waits until the position is closed.

## Position size and risk

Every trade risks a fixed share of the current account between entry and stop:

- **Trade Setup:** 1 % per trade.
- **WickScript:** `risk N%` in the strategy line, 1 % by default.

The size is risk amount ÷ distance from entry to stop. Because the risk is a share of the current account, results compound: after a winning streak trades get larger, after losses smaller. Results in R (the MAE / MFE tab) are per trade and don't depend on the size.

**Leverage** caps the size. It comes from, in this order: the **Leverage** step of the run; WickScript `leverage N`; the leverage set in the trading panel for the chart's market (Run strategy uses it for every market of the watchlist); otherwise the smallest leverage that allows the risk. The position value can't exceed account × leverage, and margin plus fee can't exceed 95 % of the account. When the cap applies, the trade risks less than the nominal risk. If no position fits at all, the trigger is skipped (`stop too tight for the leverage (no position size)`).

## Liquidation

The simulated account has a liquidation price at entry minus 1 ÷ leverage of the entry price for a long (plus for a short) – 10 % away at 10x, 4 % at 25x. If any candle between entry and exit reaches it – including the candle in which the stop is hit – the position is liquidated and **the run's whole capital drops to zero**. Keep the liquidation price well beyond your stop: a lower leverage, or a stop that is much closer than 1 ÷ leverage.

## Fees

A taker fee of **0.11 %** of the position value is charged when a position opens; it stands for the entry and the exit together. A position closed at the end of the data pays an extra exit fee. The fee is fixed and shown as **Taker fee** in the Key metrics. In the R statistics of the Strategy Lab, the fee in R is 0.11 % × entry ÷ distance to stop, so tight stops cost more R; the **NET** values subtract it.

Slippage, spread and funding are not part of backtests. (Paper trading simulates them – see [Paper trading](https://chartrider.com/docs/trading/).)

## No lookahead

- Decisions at a candle use only that candle and earlier ones.
- Indicator lines used by gates, stops, targets and limits take the last value whose candle has closed. An indicator on a higher timeframe counts only once its higher-timeframe candle has closed.
- In WickScript, `… on 4h` and `… of BTCUSDT` read the last candle of that timeframe or market that closed at or before the current candle's close – never the running one.
- Some indicators redraw their past values when later candles arrive (they "repaint"). The Trade Setup marks such lines with **⚠ repaints**: a backtest on them looks into the future and is too optimistic.

## Several markets, windows and steps

Every market × step combination × date window is its own run with its own account of 10,000 USDT and freshly calculated indicators. Runs don't share capital and don't influence each other; the [Strategy Lab](https://chartrider.com/docs/strategies/strategy-lab/) combines them afterwards (see [Metrics](https://chartrider.com/docs/strategies/metrics/)).

## Trade Setup and WickScript compared

| | Trade Setup | WickScript |
|---|---|---|
| Entries | Market, limit | Market, limit, stop, per entry with its own validity |
| Stop / target | Indicator price lines with buffer and front-run | Any expression, targets also in R (`target at 2R`) |
| Exits | Exit gates | `exit … when`, partial exits, breakeven, trailing stop |
| Risk | 1 % | `risk N%` (default 1 %) |
| Leverage | Step, trading panel or automatic | Also `leverage N` |
| Extras | – | Custom metrics and tags for the Strategy Lab |

Backtest results describe how a strategy would have traded on past candles under these assumptions. They are not a forecast and not investment advice.
