What it does
A fixed stop-loss distance ignores how much the market is actually moving. This indicator draws a trailing stop that sits a multiple of the Average True Range away from price, so it gives more room in volatile conditions and less in quiet ones.
While price rises, the stop trails below it and only ever moves up. When a bar closes below the stop, the line flips above price and starts trailing downward. Each flip is marked and can trigger an alert.
How it works
- ATR = Average True Range over ATR length bars. Offset = multiplier × ATR.
- Long side (stop below price): new stop = the higher of the previous stop and (source − offset). The stop never moves down while on this side.
- If the source closes below the previous stop, the side flips to short and the stop is reset to source + offset.
- Short side (stop above price): new stop = the lower of the previous stop and (source + offset). It never moves up while on this side.
- If the source closes above the previous stop, the side flips back to long and the stop resets to source − offset.
- Flip markers and alerts are evaluated on confirmed bars only.
How to use it
The most direct use is as a reference for a trailing stop on an open position. If you are long, the line below price shows where a volatility-adjusted stop would be. Some traders move their actual stop order to the line once per bar; others use it only as a "has the move ended?" check.
The flips also work as a simple trend filter: only look for long setups while the stop is below price, and short setups while it is above. Many traders test multipliers between 2 and 4. Lower values hug price and flip often; higher values survive deeper pullbacks but give back more of a move before flipping.
Pair the stop distance with a position size that keeps the loss acceptable. The Position Size Calculator converts a stop distance in pips into a lot size, and basic risk management covers why that matters.
Settings
| Input | Default | What it changes |
|---|---|---|
| ATR length | 14 | Smoothness of the volatility estimate. |
| ATR multiplier | 3.0 | Stop distance. Larger = fewer flips, wider stops. |
| Price used for trailing and flips | close | Close is standard; hl2 reduces reaction to single closes at extremes. |
| Show flip markers | on | L and S labels at flips. |
| Color price bars by direction | off | Paints candles by active side. |
| Long-side / short-side stop color | teal / red | Line colors. |
Limitations
- On the live bar the line can move as price moves; it settles when the bar closes. Flip markers wait for the close.
- In sideways markets the stop flips back and forth, producing a series of small losses if used for entries.
- Gaps and fast news moves can jump far beyond the line. A real stop order may fill at a worse price because of slippage.
- Because flips use closing prices, an intrabar spike through the line that closes back on the right side does not flip it. A broker stop order at the same level would have been hit.
- ATR is a lagging measure; after a sudden volatility jump the stop distance catches up gradually.
Pine Script source
In TradingView open Pine Editor, paste the code, click Save and then Add to chart.
FXP_ATRTrailingStop.pine
59 lines
// © FXPIPS ONLINE — https://fxpips.online/tradingview-indicators/atr-trailing-stop/
// License: MIT. Educational tool — not financial advice. Trading involves substantial risk.
//@version=6
indicator("FXP ATR Trailing Stop", shorttitle = "FXP ATR Trail", overlay = true)
// ── Inputs ─────────────────────────────────────────────────────────────
grpT = "Trailing stop"
atrLen = input.int(14, "ATR length", minval = 1, group = grpT)
atrMult = input.float(3.0, "ATR multiplier", minval = 0.1, step = 0.1, group = grpT)
src = input.source(close, "Price used for trailing and flips", group = grpT, tooltip = "Close is the usual choice. hl2 reacts a little slower to single spikes.")
grpVis = "Display"
showSig = input.bool(true, "Show flip markers", group = grpVis)
paintBar = input.bool(false, "Color price bars by direction", group = grpVis)
longCol = input.color(color.teal, "Long-side stop color", group = grpVis)
shortCol = input.color(color.red, "Short-side stop color", group = grpVis)
// ── Calculation ────────────────────────────────────────────────────────
float atr = ta.atr(atrLen)
float loss = atrMult * atr
// dir = 1: stop trails below price (long side). dir = -1: stop trails above price (short side).
var float stop = na
var int dir = 1
if not na(loss)
float prevStop = stop
if na(prevStop)
stop := src - loss
dir := 1
else if dir == 1
if src < prevStop
dir := -1
stop := src + loss
else
stop := math.max(prevStop, src - loss)
else
if src > prevStop
dir := 1
stop := src - loss
else
stop := math.min(prevStop, src + loss)
bool flipLong = barstate.isconfirmed and dir == 1 and dir[1] == -1
bool flipShort = barstate.isconfirmed and dir == -1 and dir[1] == 1
// ── Plots ──────────────────────────────────────────────────────────────
plot(dir == 1 ? stop : na, "Long-side stop", color = longCol, linewidth = 2, style = plot.style_linebr)
plot(dir == -1 ? stop : na, "Short-side stop", color = shortCol, linewidth = 2, style = plot.style_linebr)
plot(stop, "Stop (data window)", display = display.data_window)
plotshape(showSig and flipLong, "Flip to long side", shape.labelup, location.belowbar, longCol, text = "L", textcolor = color.white, size = size.tiny)
plotshape(showSig and flipShort, "Flip to short side", shape.labeldown, location.abovebar, shortCol, text = "S", textcolor = color.white, size = size.tiny)
barcolor(paintBar ? (dir == 1 ? longCol : shortCol) : na)
// ── Alerts ─────────────────────────────────────────────────────────────
alertcondition(flipLong, "ATR stop flipped long", 'FXP ATR Trail: price closed above the stop on {{ticker}} {{interval}}; stop now trails below at {{plot("Stop (data window)")}}')
alertcondition(flipShort, "ATR stop flipped short", 'FXP ATR Trail: price closed below the stop on {{ticker}} {{interval}}; stop now trails above at {{plot("Stop (data window)")}}')

