Nothing Special   »   [go: up one dir, main page]

Indicator: Title Shorttitle Overlay Linktoseries Timeframe

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 5

//@version=5

// © SimpleCryptoLife
indicator(title='ATR + Trailing Stops', shorttitle='ATR Trail', overlay=true, linktoseries=true,
timeframe='')

// ============================== ABOUT THIS SCRIPT


==================================

// == Description ==
// Simple visualisation of Average True Range in Pinescript V4, displayed over the main chart. The script
has two modes: Running and Trailing.
// In Trailing mode, it displays the ATR line above or below the price until price crosses it. When price
crosses it, it flips from long to short or vice-versa.
// In Running mode, it continuously displays the ATR above and below the price.
// Specifically, it displays the High and Low price plus and minus the ATR times a user-supplied
multiplier.

// == Usage ==
// Running ATR can be helpful for visualising volatility. Trailing ATR can be used as a stop loss.
// The different weightings for wicks and bodies might be interesting if you have overly spiky assets, but
you want to exit only on close
// Works on any market on any timeframe. Obviously, the lower the timeframe, the more chop.
// Use with market structure, support & resistance, and your other favourite indicators.

// == Settings ==
// ATR Lookback Period - The period over which the average is calculated. Higher = smoother; lower =
more reactive.
// ATR Multiplier - ATR is usually used with a multiplier of 2 or 3. I like 2.4 for BTC. Experiment for
your asset.
// Trail Mode - Whether the ATR is recalcualted every bar or allowed to trail.
// Flip Trail on - What counts as crossing the ATR - a close beyond, or a wick into it.
// The following settings are advanced and probably don't need to be touched for most applications.
// Percentage of Body to Include - To emulate the standard ATR, leave this and the wick percentage both
at 100. To give greater weight to candle bodies, increase this and decrease the wick percentage.
// Percentage of Wick to Include - To emulate the standard ATR, leave this and the body percentage both
at 100. To give greater weight to wicks, increase this and decrease the body percentage.
// Using wick-based ATR tends to keep it closer to price when there's a large move. Experiment for your
trading style.
// ATR Smoothing Mode - The built-in atr function uses RMA as a smoothing method. This gives you the
option to choose RMA, SMA, EMA, or WMA.

// == Alerts==
// One alert is preconfigured for price crossing the trailing ATR. You can set this to trigger Once, or Once
per bar close, in the
// TradingView alert configuration screen. You can use this for soft stops or to look for entries.

// == No Repainting ==
// This indicator does not repaint, meaning, it doesn’t go back and alter any bars in the past.
// However, until a candle closes, the indicator can only use the current price, and so the drawings,
colours and warnings for the current candle
// (including any lines that join the current candle to the previous one) will change as the price changes.
Once the candle closes, they are fixed.

// == Credits ==
// Original concept for plotting running ATR on a chart from a script by Bluephantom, modified by
RickSanchex
// Completely rewritten and extended by @SimpleCryptoLife to include trailing option and made
compatible with PineScript v4
// The function for applying different moving averages based on user input is from the TradingView ATR
template

// == Disclaimer ==
// You retain full responsibility for your trading at all times. Before trading with actual money, first make
sure your risk management is professional-level.

// ============================== GET INPUTS


==================================

atrLookback = input.int(defval=21, title='ATR Lookback Period')


atrMultiplier = input.float(defval=3, title='ATR Multiplier', step=0.1, minval=0.5, maxval=4)
atrTrailMode = input.string(title='Trail Mode', defval='Trailing', options=['Running', 'Trailing'])
atrFlipInput = input.string(title='Flip Trail on:', defval='Close', options=['Close', 'Wick'])
atrBodyPercent = input.int(title='Percentage of Body to Include', defval=100, minval=0, maxval=200,
step=10, group="Advanced Settings")
atrWickPercent = input.int(title='Percentage of Wick to Include', defval=100, minval=0, maxval=200,
step=10)
atrSmoothingMode = input.string(title='ATR Smoothing Mode', defval='RMA', options=['RMA', 'SMA',
'EMA', 'WMA'])

// ============================== CALCULATE ATR


==================================

f_ma(_source, _length, _atrSmoothingMode) =>


if _atrSmoothingMode == 'RMA'
ta.rma(_source, _length)
else
if _atrSmoothingMode == 'SMA'
ta.sma(_source, _length)
else
if _atrSmoothingMode == 'EMA'
ta.ema(_source, _length)
else
ta.wma(_source, _length)

float atrBodyTrueRange = math.max(math.abs(open - close), math.abs(open - close[1]), math.abs(close -


close[1]))
float atrWickTrueRange = high - math.max(open, close) + math.min(open, close) - low
float atrPercentAdjustedTrueRange = atrBodyTrueRange * (atrBodyPercent / 100) + atrWickTrueRange
* (atrWickPercent / 100)
float atrValue = f_ma(atrPercentAdjustedTrueRange, atrLookback, atrSmoothingMode)
float atrMultiplied = atrValue * atrMultiplier

// Plot the price plus or minus the ATR


float atrLow = low - atrMultiplied
float atrHigh = high + atrMultiplied

// ============================== CALCULATE TRAILING ATR


==================================

f_trail(_source, _trail, _direction) =>


// This function trails the source series up or down
_direction == 'down' and _source >= _trail ? _trail : _direction == 'up' and _source <= _trail ? _trail :
_source

// Need to declare these variables here, in the global scope, so we can use them in other functions later
var float trailAtrLong = atrLow
var float trailAtrShort = atrHigh

// Trail the high (short) stop down and the low (long) stop up
trailAtrLong := f_trail(atrLow, trailAtrLong, 'up')
trailAtrShort := f_trail(atrHigh, trailAtrShort, 'down')

// // DEBUG
// plot(atrTrailMode == "Trailing" ? trailAtrLong : na, "Trailing ATR Long Stop Highlight",
color=color.teal, style=plot.style_linebr, linewidth=1, transp=0)
// plot(atrTrailMode == "Trailing" ? trailAtrShort : na, "Trailing ATR Short Stop Highlight",
color=color.red, style=plot.style_linebr, linewidth=1, transp=0)

// ============================== FLIP WHEN PRICE CROSSES


==================================

f_flip(_flipInput, _longTrail, _shortTrail, _longReset, _shortReset) =>


// This function flips from a trailing long stop to a trailing short stop and vice-versa. It takes the
following inputs:
// _flipInput - A string that defines whether to consider a touch of the stop line as a flip, or a close
beyond it
// _longTrail - The long trailing stop (trails up, below the price)
// _shortTrail - The short trailing stop (trails down, above the price)
// _longReset - The value to reset the long stop to, when it's hit
// _shortReset - The value to reset the short stop to, when it's hit
// The function returns the following outputs:
// _longTrailOutput - The long trailing stop. Normally the same as it was input, unless it's reset.
// _shortTrailOutput - The short trailing stop. Normally the same as it was input, unless it's reset.
// _longTrailPlot - The long trailing stop to plot. This is na if we are not long.
// _shortTrailPlot - The short trailing stop to plot. This is na if we are not short.
//
// These variables say whether we are flipping long or short this very bar. Usually they are both false.
Only one of them can be true at once.
var bool _flipLongNow = false
var bool _flipShortNow = false
// These variables say what state we're in: long or short. One or both are always true.
// In the beginning, we haven't hit any trails yet, so we start off both long and short, to display both
lines.
var bool _isLong = true
var bool _isShort = true
// Get the source, depending whether it's on close or on touch
float _flipLongSource = _flipInput == 'Close' ? close : _flipInput == 'Wick' ? high : na
float _flipShortSource = _flipInput == 'Close' ? close : _flipInput == 'Wick' ? low : na
// Are we flipping long or short this bar?
_flipLongNow := _isShort[1] and _flipLongSource > _shortTrail ? true : false
_flipShortNow := _isLong[1] and _flipShortSource < _longTrail ? true : false
// In the edge case where we manage to flip both long and short, we need to reset that based on the
close. The close is definitive for history and intra-candle it will take the current value.
_flipLongNow := _flipShortNow and _flipLongNow and close > _longTrail ? true : _flipShortNow and
_flipLongNow and close <= _longTrail ? false : _flipLongNow
_flipShortNow := _flipLongNow and _flipShortNow and close < _shortTrail ? true : _flipShortNow
and _flipLongNow and close >= _shortTrail ? false : _flipShortNow
// Set the long and short state variables. Set if we flip (simple), initialise to true if this is the first time
(needed), otherwise persist.
_isLong := _flipLongNow ? true : _flipShortNow ? false : na(_isLong[1]) ? true : _isLong[1]
_isShort := _flipShortNow ? true : _flipLongNow ? false : na(_isShort[1]) ? true : _isShort[1]
// Update the trailing price. If we flip this bar, reset to the nearest fractal - which goes against the trail
direction, which is why we need to use another series.
_longTrailOutput = _longTrail
_shortTrailOutput = _shortTrail
_longTrailOutput := _isLong and not _isLong[1] ? _longReset : _longTrailOutput
_shortTrailOutput := _isShort and not _isShort[1] ? _shortReset : _shortTrailOutput
// Hide the trailing long stop if we are short, and hide the trailing short stop if we are long. Show both if
we are both long and short.
float _longTrailPlot = _isLong ? _longTrailOutput : _isLong and _isShort ? _longTrailOutput : na
float _shortTrailPlot = _isShort ? _shortTrailOutput : _isLong and _isShort ? _shortTrailOutput : na
[_longTrailOutput, _shortTrailOutput, _longTrailPlot, _shortTrailPlot]

// Get the plots for the trails, to show only long stop when long and short stop when short.
[trailAtrLongTemp, trailAtrShortTemp, trailAtrLongPlot, trailAtrShortPlot] = f_flip(atrFlipInput,
trailAtrLong, trailAtrShort, atrLow, atrHigh)

// Put these variables back in the global scope so we can persist them and use them as inputs to the
function next bar.
trailAtrLong := trailAtrLongTemp
trailAtrShort := trailAtrShortTemp

// ============================== PLOT LINES


==================================

// If we are in Running mode, plot the price plus and minus the ATR
plot(atrTrailMode == 'Running' ? atrLow : na, 'Running ATR Low', color=color.new(color.white, 60),
linewidth=1)
plot(atrTrailMode == 'Running' ? atrHigh : na, 'Running ATR High', color=color.new(color.white, 60),
linewidth=1)

plot(atrTrailMode == 'Trailing' ? trailAtrLongPlot : na, 'Trailing ATR Long Stop',


color=color.new(color.navy, 50), style=plot.style_linebr, linewidth=3)
plot(atrTrailMode == 'Trailing' ? trailAtrLongPlot : na, 'Trailing ATR Long Stop Highlight',
color=color.teal, style=plot.style_linebr, linewidth=1)

plot(atrTrailMode == 'Trailing' ? trailAtrShortPlot : na, 'Trailing ATR Short Stop',


color=color.new(color.maroon, 50), style=plot.style_linebr, linewidth=3)
plot(atrTrailMode == 'Trailing' ? trailAtrShortPlot : na, 'Trailing ATR Short Stop Highlight',
color=color.red, style=plot.style_linebr, linewidth=1)

// ============================== ALERTS ==================================

// Alert for crossing the trailing ATR. You can set this to trigger Once, or Once per bar close, in the
// TradingView alert configuration screen. You can use this for soft stops or to look for entries.

float atrFlipLongSource = atrFlipInput == 'Close' ? close : atrFlipInput == 'Wick' ? high : na


float atrFlipShortSource = atrFlipInput == 'Close' ? close : atrFlipInput == 'Wick' ? low : na

bool alertCrossAtrShortStop = atrFlipLongSource > trailAtrShortPlot[1] and atrFlipLongSource[1] <=


trailAtrShortPlot[2] ? true : false
bool alertCrossAtrLongStop = atrFlipShortSource < trailAtrLongPlot[1] and atrFlipShortSource[1] >=
trailAtrLongPlot[2] ? true : false

bool alertCrossAtr = alertCrossAtrShortStop or alertCrossAtrLongStop


alertcondition(alertCrossAtr, title='Price crossed ATR', message='Price crossed trailing ATR')

// ====================================================== //
// //
// (╯°□°)╯︵ ˙ƃᴉq ooʇ sᴉ ǝʞɐɔ oʇ ǝldoǝd ɟo oᴉʇɐɹ ǝɥ┴ //
// //
// ====================================================== //

You might also like