# Writing strategies in WickScript

> How to write WickScript strategies you can backtest – entries, stops and targets in R, exits, partial exits, breakeven, trailing stops, tags, metrics and the Trade Setup conversion.

Updated: 2026-10-25T00:01:51.000Z · https://chartrider.com/docs/wickscript/strategies/

A strategy script is an indicator script that also trades. It starts with `strategy "Name"` instead of `indicator "Name"`, and its `enter`, `stop at`, `target at` and `exit` statements become the trades of the backtest. Everything from the [Language guide](https://chartrider.com/docs/wickscript/language/) and the [Indicators](https://chartrider.com/docs/wickscript/indicators/) page works in strategies too – `show`, `mark`, `level`, `hud`, inputs and functions.

```wickscript
wickscript 1
strategy "EMA cross" risk 1%
fast = ema(close, input 9 "Fast")
slow = ema(close, input 21 "Slow")
show fast as line "Fast" color amber
show slow as line "Slow" color blue
when fast crosses above slow
    tag "cross long"
    enter long at market
    stop at lowest(low, 10) - 2 * tick
    target at 2R
end
when fast crosses below slow
    tag "cross short"
    enter short at market
    stop at highest(high, 10) + 2 * tick
    target at 2R
end
```

## The strategy line

```text
strategy "Name" [risk <percent>] [leverage <number> | leverage auto] [cooldown <N> bars] [minR <N>R]
```

| Option | Meaning | Without it |
|---|---|---|
| `risk 1%` | share of the capital risked per trade; the position size follows from the distance between entry and stop | 1 % |
| `leverage 5` | fixed leverage for every trade | `leverage auto`: the leverage of the strategy settings, otherwise the smallest leverage that allows the risk |
| `cooldown 5 bars` | candles without new entries after a trade has closed | no cooldown |
| `minR 1.5R` | skips entries whose target is closer than 1.5 × the risk | no minimum |

The options can come in any order. A leverage chosen as Step 1 / Step 2 parameter takes precedence over `leverage`. The checker also accepts `fees …` and `capital …`, but they currently have no effect – fees and starting capital are those of the backtest.

```wickscript
wickscript 1
strategy "Options" risk 0.5% leverage 3 cooldown 5 bars minR 1.5R
when close crosses above ema(close, 50)
    enter long at market
    stop at lowest(low, 20)
    target at 3R
end
```

## How the backtest trades a script

The script and the backtest run together, candle by candle. For each candle:

1. **Open position** (from the candle after its entry): the stop is checked first, then the partial targets (the one closest to the entry first), then the target. If the stop and the target are both inside the candle, the stop counts.
2. **Pending limit or stop order** (from the candle after it was placed): it fills when the price reaches it, expires after its `valid` candles, or – a limit order – is cancelled when the target is reached before the fill. In the fill candle the stop counts, the target doesn't.
3. **The script runs** for this candle and sees the position as it stands after steps 1 and 2.
4. **At the candle's close:** exits (`exit … when …`) close the position at the close price, stop moves (breakeven, trailing) are applied, and new entries are placed.

Further rules:

- **One position at a time.** An entry while a position or a pending order exists, or during the cooldown, is skipped.
- If a long and a short entry fire on the same candle, neither is taken.
- Decisions are made only on closed candles; the still forming last candle never trades.
- An entry is skipped when its levels are on the wrong side: a long needs stop < entry < target, a short the reverse.
- The position size comes from `risk` and the stop distance, limited by the leverage. Entries whose stop is too tight for the leverage are skipped.
- All prices of an entry – limit or stop price, stop-loss, target, partial targets, trailing distance – are calculated on the signal candle.

## Entries

```text
enter long|short [at market]
enter long|short at limit <price> [valid <N> bars]
enter long|short at stop <price> [valid <N> bars]
```

| Order | Fills | Rules |
|---|---|---|
| `at market` (also just `enter long`) | at the close of the signal candle | stop and target are checked from the next candle |
| `at limit <price>` | at the price, when the market reaches it, from the next candle | a long limit must be below the close, a short limit above; cancelled if the target is reached first |
| `at stop <price>` | at the price, when the market reaches it, from the next candle | a long stop entry must be above the close, a short one below – for breakouts |

`valid N bars` sets how many candles a limit or stop order waits; without it, 10 candles. `enter` signals an entry on every candle on which its statement runs – while no position is open, that is a new trade on each of those candles – so put it inside a `when … end` block (the checker warns otherwise). The block that contains `enter` must also contain `stop at`.

```wickscript
wickscript 1
strategy "Entry types" risk 1%
fast = ema(close, 9)
slow = ema(close, 30)
when fast crosses above slow
    tag "pullback"
    enter long at limit fast + 0.05% valid 4 bars
    stop at slow - 0.4%
    target at 2R
end
when fast crosses below slow
    tag "breakdown"
    enter short at stop lowest(low, 5) - 2 * tick valid 3 bars
    stop at highest(high, 10)
    target at 2R
end
```

## Stop and target

```text
stop at <price>
target at <price>
target at <N>R
```

- **`stop at` is required** in every block with an `enter`: it sets the position size. Typical stops: `lowest(low, 10) - 2 * tick`, `low - 0.2%`, `close - 2 * atr(14)` (a market entry fills at the close).
- **`target at`** takes a price or an R multiple. `target at 2R` is the entry plus twice the distance to the stop (minus for shorts).
- The target is optional when the script has an `exit` for that side (`exit long when …`, `exit all when …`, `exit half when …`). Without a target and without an exit, the entry is skipped.
- `stop at` and `target at` belong to the last `enter` of their block.
- `stop` and `target` are only keywords when followed by `at`; `stop = low` is a normal variable.

## Tags

`tag "Name"` names the entries of its block. The name is shown in the chart's trade signals and in the statistics, so you can compare the setups of one strategy. Without a tag, an entry is named after its line, like "line 9".

## Exits

```text
exit long|short|all [at market] when <condition>
exit long|short|all
```

- `exit long when <condition>` closes a long position at the close of the candle on which the condition **becomes** true (it was false on the previous candle), checked from the candle after the entry. If the condition was already true before the entry, it fires only after it has been false once.
- `exit short` closes shorts, `exit all` either side. `at market` is optional; exits always fill at the close.
- Without `when`, inside a block: the exit fires on every candle on which the block runs. Use this to exit while a condition holds.
- At the top level, an `exit` without `when` would exit on every candle; the checker warns.

```wickscript
wickscript 1
strategy "Exits" risk 1%
trend = ema(close, 50)
when close crosses above trend
    enter long at market
    stop at close - 2 * atr(14)
end
exit long when close crosses below trend
exit long when bars since entry >= 48 bars
if position.long and rsi(close, 14) > 80 then
    exit long
end
```

## Partial exits

```text
exit half at <price>        exit half at <N>R          # in the block with enter
exit 30% at <price>         exit 30% at <N>R
exit half when <condition>  exit 30% when <condition>  # anywhere, for any open position
```

- **`exit … at`** belongs to the entry of its block and takes the share at a price or at N R, like a partial take-profit. The share is a share of the **initial** size; all partial exits of a block must add up to less than 100 % (the rest closes at the target, the stop or an exit).
- In one candle the stop comes first, then the partial targets (closest to the entry first), then the target. A partial target at or beyond the target never fills.
- **`exit … when`** closes the share at the close of the candle on which the condition becomes true. A full exit on the same candle takes precedence. If nothing is left after a partial exit, the trade ends.
- `half` is 50 %. The share must be between 0 % and 100 %, written with `%`.

```wickscript
wickscript 1
strategy "Scale out" risk 1%
when close crosses above ema(close, 20)
    enter long at market
    stop at lowest(low, 10)
    exit 30% at 1R
    exit 30% at 2R
    target at 4R
end
exit half when rsi(close, 14) crosses above 75
```

## Breakeven: `move stop`

```text
move stop to entry after <N>R
move stop to <price> after <N>R
```

In the block with `enter`. As soon as the best price since the entry (the high for longs, the low for shorts) has reached N R, the stop moves to the entry price (or the given price) at the close of that candle and applies from the next candle. The stop only moves in the profitable direction, and only when the new stop is below the close (longs) or above it (shorts); otherwise it waits for a later candle.

## Trailing stop: `trail stop`

```text
trail stop by <distance> [after <N>R]
```

In the block with `enter`. The stop follows the best price since the entry at a fixed distance, adjusted at each candle's close, only in the profitable direction and only while it stays on the right side of the close. The distance is a price (`2 * atr(14)`, `50 * tick`) or a percentage of the best price (`1%`), fixed on the signal candle. With `after 1.5R`, trailing starts once the best price has reached 1.5 R.

```wickscript
wickscript 1
strategy "Breakout" risk 1%
# buy the break of the recent high, take half at 1R, then let the rest run
len = input 20 "Range"
top = highest(high, len)
bottom = lowest(low, len)
show top as line "Top" color green
show bottom as line "Bottom" color red
when close crosses above ema(close, 50) and not position.open
    tag "breakout"
    enter long at stop top + 2 * tick valid 5 bars
    stop at bottom
    exit half at 1R
    move stop to entry after 1R
    trail stop by 2 * atr(14) after 1.5R
    target at 4R
end
exit long when bars since entry >= 100 bars
```

## The open position

| Value | Meaning | Without a position |
|---|---|---|
| `position.open` | a position is open | false |
| `position.long`, `position.short` | its side | false |
| `position.entry` | entry price | `na` |
| `position.stop` | current stop (after breakeven or trailing) | `na` |
| `position.target` | target price | `na` |
| `position.size` | open share of the initial size, in % (100 until a partial exit) | 0 |
| `position.r` | open result in R at the candle's close | `na` |
| `position.bars` | candles since the entry | `na` |
| `bars since entry` | the same as `position.bars` | `na` |

The script sees the position at the close of each candle, after stops, partial targets, targets and orders of that candle, and before its own decisions. A market entry made on a candle is visible from the next candle on (`position.bars` is 1 there). `entry` alone is not a value; write `position.entry` or `bars since entry`. `position` and `bars since entry` only work in strategies and not inside functions.

```wickscript
wickscript 1
strategy "Position" risk 1%
fast = ema(close, 9)
slow = ema(close, 30)
when fast crosses above slow and not position.open
    enter long at market
    stop at lowest(low, 10)
end
exit long when position.r >= 1R or position.bars >= 15 bars
show position.stop as line "Current stop" color red
```

## Metrics

```text
metric "Name" = <expression>
```

`metric` stores the value of the expression on each trade's **signal candle**. In the strategy statistics, every metric becomes a dimension to group the results by: numbers in five ranges (quintiles such as "≤ 32.1", "32.1 – 45" … "> 70.2", "n/a" without a value), or the values themselves when there are at most five different ones. A metric needs a number or a yes/no value, and each name may be used once. Write metrics at the top level of the script.

```wickscript
wickscript 1
strategy "Metrics" risk 1%
r = rsi(close, 14)
when close crosses above ema(close, 20)
    enter long at market
    stop at lowest(low, 10)
    target at 2R
end
metric "RSI at entry" = r
metric "ATR %" = pct(close + atr(14), close)
metric "London" = session is London
```

## Reading other indicators of the strategy: `use`

```text
use <TechName> as <alias>
```

`use` reads the outputs of another indicator of the same strategy by its tech name (the name like `RSI1`, `EMA2` or `WS1` shown in the strategy's indicator list):

- `alias.value` is the main line; other outputs by name: `alias.signal`, `alias["REL kill"]`. Names ignore upper/lower case and special characters, so `alias.relKill` is the same as `alias["REL kill"]`.
- Values are aligned like the gates of the Trade Setup: the value at each candle's close, indicators on higher timeframes with their delay.
- `use` works in strategies (F5, Run strategy, Strategy Lab preview). In the chart, a script with `use` shows a message, and the values stay `na`.
- To create an indicator inside the script instead, use `use indicator "Name" with … as …` (see [Indicators](https://chartrider.com/docs/wickscript/indicators/)).

```wickscript
wickscript 1
strategy "RSI filter" risk 1%
use RSI1 as r
use EMA1 as trend
when close crosses above trend.value and r.value > 50
    enter long at market
    stop at trend.value - 0.5%
    target at 2R
end
```

## Backtesting a script

- In **Strategy Lab → Scripts**, a strategy script shows a backtest preview of your draft while you type: trades, short/long, win rate, total R and R per trade, plus any messages.
- **Trade with this script** in the Scripts tab makes the strategy trade with the script. From then on, F5 (backtest on the chart) and Run strategy use the applied version. Only the first strategy script of a strategy trades.
- **Trade with this Trade Setup** in the Trade Setup tab switches back to the Trade Setup.
- Inputs can be Step 1 / Step 2 parameters for the heatmap, like the settings of any indicator.

How the backtest simulates fills, fees and position sizes is described in [Backtest engine](https://chartrider.com/docs/strategies/backtest-engine/); the statistics and tabs of the Lab in [Strategy Lab](https://chartrider.com/docs/strategies/strategy-lab/).

## From the Trade Setup: Open as WickScript

**Open as WickScript** in the [Trade Setup](https://chartrider.com/docs/strategies/trade-setup/) writes your setup as a strategy script into the Scripts tab, with the same trades:

- each trigger becomes a `when … end` block per side, its filters an `if` inside it (a filter without a value lets the trade through, like in the Trade Setup: `isna(x) or …`);
- the indicator lines are read with `use <TechName> as x` and `x.value` or `x["Output"]`;
- stop and target lines become `stop at` and `target at` with the buffer in %, limit entries `enter … at limit … valid N bars`;
- exit gates become `exit long when …` / `exit short when …`; cooldown and minimum R go into the strategy line;
- sides without a stop line don't trade, as in the Trade Setup.

From then on the script trades; your Trade Setup stays saved. The conversion works in one direction only – a script can't be turned back into a Trade Setup. A converted setup looks like this:

```wickscript
wickscript 1
# from the Trade Setup of "Trend pullback" – the same triggers, filters, exits, stops and targets
strategy "Trend pullback" risk 1% cooldown 3 bars
use EMA1 as ema1
use RSI1 as rsi1

when close >= ema1.value
    tag "Long · EMA"
    if (isna(rsi1.value) or rsi1.value >= number(50)) then
        enter long at market
        stop at ema1.value - 0.4%
    end
end
exit long when close <= ema1.value
```

## More examples

RSI dip in an uptrend with a limit entry and a time exit:

```wickscript
wickscript 1
strategy "RSI dip" risk 0.5% cooldown 5 bars
r = rsi(close, input 14 "RSI length")
trend = ema(close, 200)
when r crosses below 30 and close > trend
    tag "RSI dip"
    enter long at limit close - 0.2% valid 3 bars
    stop at lowest(low, 20) - 0.1%
    target at 2R
end
exit long when r crosses above 70
exit long when bars since entry >= 48 bars
```

Stop and reverse on an EMA cross with trailing stops, filtered by the 4h trend:

```wickscript
wickscript 1
strategy "Trend rider" risk 1% leverage 3
fast = ema(close, 20)
slow = ema(close, 50)
up4h = close > ema(close, 50) on 4h
show fast as line "Fast" color amber
show slow as line "Slow" color blue
when fast crosses above slow and up4h
    enter long at market
    stop at close - 2 * atr(14)
    trail stop by 3 * atr(14) after 1R
end
when fast crosses below slow and not up4h
    enter short at market
    stop at close + 2 * atr(14)
    trail stop by 3 * atr(14) after 1R
end
exit long when fast crosses below slow
exit short when fast crosses above slow
```

Exits run before entries at a candle's close, so the long is closed and the short opened on the same candle.

Asia range breakout in the London session:

```wickscript
wickscript 1
strategy "Asia range breakout" risk 1%
inAsia = session is Asia
keep top = na
keep bottom = na
when inAsia
    top = high
    bottom = low
end
if inAsia then
    top = max(top, high)
    bottom = min(bottom, low)
end
show top as line "Asia high" color teal
show bottom as line "Asia low" color teal
when session is London and close crosses above top
    tag "London long"
    enter long at market
    stop at (top + bottom) / 2
    exit half at 1R
    move stop to entry after 1R
    target at 3R
end
when session is London and close crosses below bottom
    tag "London short"
    enter short at market
    stop at (top + bottom) / 2
    exit half at 1R
    move stop to entry after 1R
    target at 3R
end
exit all when session is NewYork
```

Previous day low sweep in the killzones, with metrics:

```wickscript
wickscript 1
strategy "PDL sweep" risk 1%
pdl = low on 1d
swept = low < pdl and close > pdl
when swept and killzone is London or NewYork
    tag "PDL sweep"
    enter long at market
    stop at low - 2 * tick
    target at 2R
end
metric "Sweep depth %" = pct(pdl, low)
metric "Killzone London" = killzone is London
```

In `swept and killzone is London or NewYork`, the `or NewYork` belongs to `is`: the condition means `swept and (killzone is London or killzone is NewYork)`.
