Skip to content

A trend-following strategy ​

How do you write a breakout strategy that rides a trend and limits the loss when it fails? This one buys a close above the highest high of 55 bars. Its stop starts three ATRs under that close and rises to the lowest low of 20 bars whenever that is higher, and it never comes down. It is a teaching example, not a recommendation.

pine
//@version=6
strategy("Breakout trend", overlay = true, initial_capital = 10000,
  default_qty_type = strategy.percent_of_equity, default_qty_value = 100,
  commission_type = strategy.commission.percent, commission_value = 0.1)
int entryLen = input.int(55, "Entry channel", minval = 2)
int exitLen = input.int(20, "Exit channel", minval = 2)
float atrMult = input.float(3.0, "ATR stop", minval = 0.5)

// [1]: the channel up to the bar before, so this bar can break it
float upper = ta.highest(high, entryLen)[1]
float lower = ta.lowest(low, exitLen)[1]
float atr = ta.atr(20)
plot(upper, "Entry", color.teal)
plot(lower, "Exit", color.maroon)

var float stop = na
if close > upper and strategy.position_size == 0
    strategy.entry("Long", strategy.long)
    // The first stop: atrMult ATRs under the breakout close
    stop := close - atrMult * atr
if strategy.position_size > 0
    // Raised to the channel low when that is higher, never lowered
    stop := math.max(stop, lower)
// Placed on every bar, so the stop waits for the entry's fill
strategy.exit("Stop", "Long", stop = stop)
plot(strategy.position_size > 0 ? stop : na, "Stop", color.red,
  style = plot.style_linebr)

How it works ​

  • ta.highest(high, entryLen)[1] is the highest high of the 55 bars before this one. Without [1], this bar's own high would be in it, and a close could never be above it.
  • ta.atr(20) is the average true range, a measure of how far a bar usually moves.
  • var float stop keeps the stop from bar to bar. The entry sets it three ATRs under the breakout close, which caps the first loss.
  • math.max(stop, lower) raises it to the channel low once that is higher. Neither a wider ATR nor a falling channel can lower it, so the stop only tightens.
  • strategy.exit(..., stop = stop) is placed on every bar, so it rests before the entry fills and protects the fill bar too. A stop fills when the price trades through it, at the stop price or at the open if the bar gaps past it.

Traps ​

  • A gap fills worse than the stop. When a bar opens below the stop, the fill is at that open, as on TradingView.
  • A breakout on the bar's close fills at the next open, which after a strong close is usually higher. That cost is real, and the backtest pays it.

See also ​

AmenoScript is compatible with Pine Script v6. Pine Script is a trademark of TradingView, Inc., which has no part in AmenoScript.