• Get $40 off VIP by signing up for a free account! Sign Up

Volatility Based Trailing Stop for ThinkorSwim


This Thinkscript indicator is a volatility-based trailing stop, similar to the Chandelier Stop. When direction switches from short to long (or vice versa), the initial stop level is a specified number of multiples of the Average True Range (ATR) of the last ‘n’ bars. Then the value is trailed, getting tighter should volatility decrease or price move to new extremes. A close through the stop level signifies a trend change in this indicator; crossing the value and closing back on the other side does not.


thinkScript Code

# Volatility-Based Trailing Stop
# By Prospectus @ http://readtheprospectus.wordpress.com
# Input Declarations:
input mult = 3.0; #Multiple of Average True Range to use
input length = 10; #Average True Range period
# Input to select Close or High/Low for switching:
input Style={default Close, HighLow};
def type;
case Close:
case HighLow:
# Set parameters based on switch selection:
def uu=if type then close else high;
def ll=if type then close else low;
def na=double.nan;
# Calculate average range for volatility:
def atr = expaverage(high-low,length);
# Calculate initial short and long volatility stop values:
def svs =low+ceil(mult*atr/ticksize())*ticksize();
def lvs =high-ceil(mult*atr/ticksize())*ticksize();
# Set up the trailing stop logic:
rec shortvs=if isnan(shortvs[1]) then svs else if uu>shortvs[1] then svs else min(svs,shortvs[1]);
rec longvs=if isnan(longvs[1]) then lvs else if ll<longvs[1] then lvs else max(lvs,longvs[1]);
# Detect if we breached the trailing stop (close or high/low):
def longswitch=if uu>=shortvs[1] and uu[1]<shortvs[1] then 1 else 0;
def shortswitch=if ll<=longvs[1] and ll[1]>longvs[1] then 1 else 0;
# This logic remembers the direction and changes when needed:
rec direction= compoundvalue(1,if isnan(direction[1]) then 0 else
if direction[1]<=0 and longswitch then 1
else if direction[1]>=0 and shortswitch then -1
else direction[1],0);
# Set up the two plots. "na" makes the current value disappear
# if we�re trading in the opposite direction:
plot short=if direction>0 then na else shortvs;
plot long=if direction<0 then na else longvs;
# Formatting:
# Alerts:
def alerttrigger= if direction[1]<=0 and longswitch then 1
else if direction[1]>=0 and shortswitch then 1 else 0;
input alerttext="Alert Text";
input UseAlerts = {false, default true};
input AlertType = {default "BAR", "ONCE", "TICK"};
def at=AlertType;
input AlertSound = {"Bell", "Chimes", default "Ding", "NoSound", "Ring"};
alert(alerttrigger AND UseAlerts, alerttext, if at==1 then Alert.ONCE else if at==2 then Alert.TICK else Alert.BAR, AlertSound);
Last edited by a moderator:

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Hi Everyone.

what do you think? is this similar or equivalent to the Vol Stop in trading view? with all the VIX work and trading system, this indicator comes up as a way to exit the trades. if not, is it worth porting?

#Volatility Stop
study("Volatility Stop", shorttitle="VStop", overlay=true)
length = input(20)
mult = input(2)
atr_ = atr(length)
max1 = max(nz(max_[1]), close)
min1 = min(nz(min_[1]), close)
is_uptrend_prev = nz(is_uptrend[1], true)
stop = is_uptrend_prev ? max1 - mult * atr_ : min1 + mult * atr_
vstop_prev = nz(vstop[1])
vstop1 = is_uptrend_prev ? max(vstop_prev, stop) : min(vstop_prev, stop)
is_uptrend = close - vstop1 >= 0
is_trend_changed = is_uptrend != is_uptrend_prev
max_ = is_trend_changed ? close : max1
min_ = is_trend_changed ? close : min1
vstop = is_trend_changed ? is_uptrend ? max_ - mult * atr_ : min_ + mult * atr_ : vstop1
plot(vstop, color = is_uptrend ? green : red, style=cross, linewidth=2)
Last edited:
"input Style={default Close, HighLow};"

My understanding based on the code is that it can be set based on the Close or High/Low, but for what period?

Also, can someone convert this to TOS? https://www.motivewave.com/studies/volatility_stops.htm The one from MotiveWave is based on a price action around a moving average, which seems more straightforward and useful since most trading systems use popular MAs.
there has been interest in Volatility Stops (VT) indicators recently, @john3 here is a port of the VT as requested:


#Volatility Stops (VT) from MotiveWave V1.2
#VT was authored by Welles Wilder. The VT identifies exit points for
#long and short positions. First, an exponential moving average (EMA)
#of the input is taken to determine the current trend. Then,
#the Average True Range (ATR) is calculated and multiplied by a user
#defined factor.
#If the EMA is increasing (uptrend), the ATR product is subtracted
#from the highest price for the period or, if the EMA is decreasing
#(down trend), it is added to the lowest price for the period.
#This final value of the VT is displaced to one future bar.
#The user may change the position (long), input (close), method (EMA)
#period lengths and percent factor.
# @john3 request
# 2019.12.16 @diazlaz - initial port/interpretation.
#set isLong to yes or no. default is long yes. (set to no for short)

declare upper;

input isLong = yes; #user defined, default is long (set to no for short)
input price = close;
input maP = 63;
input atrP = 21;
input fac = 3;
input showArrows = yes;
input showLabels = yes;

def longP = isLong;
def shortP  = !isLong;
def ma = ExpAverage(price, maP);

def upTrend = price > ma;
def dnTrend = price <= ma;

def na = Double.NaN;

def atrUp;
def atrDn;
def sic;
def vstop;

if (longP and upTrend) then {
    atrUp = ATR(atrP);
    atrDn = na;
    sic = highest(price, atrP);
    vstop = sic - (fac * atrUp);
} else
if (shortP AND dnTrend) then {
    atrUp = na;
    atrDn = ATR(atrP);
    sic = lowest(price, atrP);
    vstop = sic + (fac * atrDn);
} else {
    atrUp = na;
    atrDn = na;
    sic = na;
    vstop = na;

def prevP = price[1];
def vs = if !isNaN(vstop) then vstop else vs[1];
def sell = prevP > vs AND price < vs AND longP AND upTrend;
def buy = prevP < vs AND price > vs AND shortP AND dnTrend;

plot pUP = showArrows and buy;

plot pDown = showArrows and sell;

plot pVT = vs;

 if isLong then "(VT) LONG" else "(VT) SHORT",
 if isLong then COLOR.GREEN else COLOR.RED);

#END OF Volatility Stops (VT)
@Trading51, thank you, I appreciate it. Just to confirm, the default settings are EMA 63, ATR Period 21, ATR Factor 3. Correct?

Correct. Feel free to try different settings and timeframes.

//position = pos, user defined, default is long
//input = price, user defined, default is close
//method = moving average (ma), user defined, default is EMA
//period1 = maP, user defined, default is 63
//period2 = artP, user defined, default is 21
//factor = fac, user defined, default is 3
//art = Average True Range
//index = current bar number, prev = previous
//shortP = short position, longP = long position
Sure please post and we will try.
This is it, I want to be able to have at least 5 specific areas that i can have marked off sort of like my own pivot the main area and 2 levels above and 2 levels below below is the code

## Line
input arbitrary_number = 2800;

plot data2 = arbitrary_number;


plot data3 = highestall(if isnan(close[-1])then round(data2[1] / ticksize(),0) * ticksize()                        else double.nan);

addchartBubble(isnaN(close[3]) && !isnaN(close[4]),"price location" = data3, text = "Price = " + data3, color = Color.White);



Here you go @Trading51, please set the input to greater than 0 and it will render up to 6 manual S&R lines.

#Manual S&R
# @diazlaz - 2019.12.19 - uTS request

declare upper;

input level1 = 2800;
input level2 = 0;
input level3 = 0;
input level4 = 0;
input level5 = 0;
input level6 = 0;

def sLevel1 = level1;
def sLevel2 = level2;
def sLevel3 = level3;
def sLevel4 = level4;
def sLevel5 = level5;
def sLevel6 = level6;

#level 1
plot pLevel1 = highestall(if isnan(close[-1])then round(sLevel1[1] / ticksize(),0) * ticksize() else double.nan);
pLevel1.SetHiding(!level1 > 0);
addchartBubble(isnaN(close[3]) && !isnaN(close[4]),"price location" = pLevel1, text = "Price = " + pLevel1, color = Color.White);

#level 2
plot plevel2 = highestall(if isnan(close[-1])then round(slevel2[1] / ticksize(),0) * ticksize() else double.nan);
plevel2.SetHiding(!level2 > 0);
addchartBubble(isnaN(close[3]) && !isnaN(close[4]),"price location" = plevel2, text = "Price = " + plevel2, color = Color.White);

#level 3
plot plevel3 = highestall(if isnan(close[-1])then round(slevel3[1] / ticksize(),0) * ticksize() else double.nan);
plevel3.SetHiding(!level3 > 0);
addchartBubble(isnaN(close[3]) && !isnaN(close[4]),"price location" = plevel3, text = "Price = " + plevel3, color = Color.White);

#level 4
plot plevel4 = highestall(if isnan(close[-1])then round(slevel4[1] / ticksize(),0) * ticksize() else double.nan);
plevel4.SetHiding(!level4 > 0);
addchartBubble(isnaN(close[3]) && !isnaN(close[4]),"price location" = plevel4, text = "Price = " + plevel4, color = Color.White);

#level 5
plot plevel5 = highestall(if isnan(close[-1])then round(slevel5[1] / ticksize(),0) * ticksize() else double.nan);
plevel5.SetHiding(!level5 > 0);
addchartBubble(isnaN(close[3]) && !isnaN(close[4]),"price location" = plevel5, text = "Price = " + plevel5, color = Color.White);

#level 6
plot plevel6 = highestall(if isnan(close[-1])then round(slevel6[1] / ticksize(),0) * ticksize() else double.nan);
plevel6.SetHiding(!level6 > 0);
addchartBubble(isnaN(close[3]) && !isnaN(close[4]),"price location" = plevel6, text = "Price = " + plevel6, color = Color.White);

#END OF Manual S&R
I found a chandelier trailing stop on tradingview that I thought looked good code-wise and converted it to thinkorswim. I changed the ATR length period to 7 because 22 didn't make sense. Also it becomes Wilder's original volatility stop if you change both the lowest low and highest high to just closing prices, and you make the ATR length the same as the lookback length.
#Chandelier Volatility Trailing Stop


#Code taken and re-edited to thinkorswim from pipCharlie, who got it from LazyBear

input AtrMult = 3.0;
input ATRlength = 7;
input lookbackLength = 22;
input highestHigh = high;
input lowestLow = low;
input AvgType = AverageType.WILDERS;
input PaintBars = no;

def ATR = MovingAverage(AvgType, TrueRange(high, close, low), ATRlength);
def longstop = Highest(highestHigh,lookbackLength)-AtrMult*atr;
def shortstop = Lowest(lowestLow,lookbackLength)+AtrMult*atr;

def shortvs = if isNaN(shortvs[1]) then shortstop else if close>shortvs[1] then shortstop else min(shortstop,shortvs[1]);
def longvs = if isNaN(longvs[1]) then longstop else if close<longvs[1] then longstop else max(longstop,longvs[1]);

def longswitch= if close>=shortvs[1] and close[1]<shortvs[1] then 1 else 0;
def shortswitch = if close<=longvs[1] and close[1]>longvs[1] then 1 else 0;

def direction = if isNaN(direction[1]) then 0 else if direction[1]<=0 and longswitch then 1 else if direction[1]>=0 and shortswitch then -1 else direction[1];
def pc = if direction>0 then longvs else shortvs;

plot VolatilityStop = pc;
VolatilityStop.AssignValueColor(if direction < 0 then Color.RED else Color.GREEN);
AssignPriceColor(if PaintBars and direction < 0
                 then Color.RED
                 else if PaintBars and direction > 0
                      then Color.GREEN
                      else Color.CURRENT);
This is great, exactly what I was looking for! Does this script automatically enter a buy/sell order when you have an open position and the price crosses the indicator line? If not, how do I set that up?
So - from my screenshot - this keeps me in a long position even after 4 down candles - Please see screenshot


I am grateful for any comments
Thank you for your reply - I should have asked - why isn't the indicator turning red dots once the pullback starts? Or am I misunderstanding the purpose of the indicator?
@MatthewTherrien Ahhhh... And therein lies the definition of lagging indicators. They are slow to get in on the party and they are slow to leave...
Just to add to the collection...Volatility Trailing Stop by Steve Coombs

Where I found it

This post (Volatility Trailing Stop by Steve Coombs) has

While Scribd offers the use of this indicator. The agreement upon download is that it will not be shared.

Please do not post proprietary content.
Last edited by a moderator:
I have a Volatilty Stop indicator (Similar to ATR Trailing Stop) I would like to smooth out like a moving average (ex 20-Exp MA). Anyone could assist.

Thank you kindly
## Volatility Trailing Stop
## Version 1.1
## By Steve Coombs
## This ATR Trailing Stop is calculated using the Highest Close in an uptrend or
## the Lowest Close in a downtrend, rather than just the Close that is used
## in the standard TOS ATRTrailing Stop

Where I found it

This post (Volatility Trailing Stop by Steve Coombs) has

While Scribd offers the use of this indicator. The agreement upon download is that it will not be shared.

Please do not post proprietary content.
Last edited by a moderator:

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
322 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.