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.
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 and the Indicators page works in strategies too – show, mark, level, hud, inputs and functions.
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
endThe strategy line
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 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
endHow the backtest trades a script
The script and the backtest run together, candle by candle. For each candle:
- 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.
- Pending limit or stop order (from the candle after it was placed): it fills when the price reaches it, expires after its
validcandles, 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. - The script runs for this candle and sees the position as it stands after steps 1 and 2.
- 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
riskand 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
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 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
endStop and target
stop at <price>
target at <price>
target at <N>Rstop atis required in every block with anenter: 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 attakes a price or an R multiple.target at 2Ris the entry plus twice the distance to the stop (minus for shorts).- The target is optional when the script has an
exitfor that side (exit long when …,exit all when …,exit half when …). Without a target and without an exit, the entry is skipped. stop atandtarget atbelong to the lastenterof their block.stopandtargetare only keywords when followed byat;stop = lowis 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
exit long|short|all [at market] when <condition>
exit long|short|allexit 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 shortcloses shorts,exit alleither side.at marketis 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
exitwithoutwhenwould exit on every candle; the checker warns.
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
endPartial exits
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 positionexit … atbelongs 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 … whencloses 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.halfis 50 %. The share must be between 0 % and 100 %, written with%.
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 75Breakeven: move stop
move stop to entry after <N>R
move stop to <price> after <N>RIn 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
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 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 barsThe 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 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 redMetrics
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 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 LondonReading other indicators of the strategy: use
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.valueis the main line; other outputs by name:alias.signal,alias["REL kill"]. Names ignore upper/lower case and special characters, soalias.relKillis the same asalias["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.
useworks in strategies (F5, Run strategy, Strategy Lab preview). In the chart, a script withuseshows a message, and the values stayna.- To create an indicator inside the script instead, use
use indicator "Name" with … as …(see Indicators).
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
endBacktesting 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; the statistics and tabs of the Lab in Strategy Lab.
From the Trade Setup: Open as WickScript
Open as WickScript in the Trade Setup writes your setup as a strategy script into the Scripts tab, with the same trades:
- each trigger becomes a
when … endblock per side, its filters anifinside 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 xandx.valueorx["Output"]; - stop and target lines become
stop atandtarget atwith the buffer in %, limit entriesenter … 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 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.valueMore examples
RSI dip in an uptrend with a limit entry and a time exit:
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 barsStop and reverse on an EMA cross with trailing stops, filtered by the 4h trend:
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 slowExits 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 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 NewYorkPrevious day low sweep in the killzones, with metrics:
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 LondonIn 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).