Multi-TimeFrame ATR Trailing Stops for ThinkorSwim

TOS007

New member
This is my first post, a question, really. I have seen plethora of codes for MTF studies on the internet, but having troubles to find any MTF ATR Trailing Stops for thinkscript. I think it is helpful to trade against different time frames. I am asking, if any one of you can kindly write a code for it? Thanks!

Can anyone help me with this code, please? The problem is with the line for plotting the ATR. I truly appreciate for your help. Thanks.

Code:
#
# TD Ameritrade IP Company, Inc. (c) 2009-2020
# MTF_ATR

input Period = aggregationPeriod.DAY;
input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 3.5;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;

Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);

def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod));
def HRef = if low <= high[1]
    then high - close[1]
    else (high - close[1]) - 0.5 * (low - high[1]);
def LRef = if high >= low[1]
    then close[1] - low
    else (close[1] - low) - 0.5 * (low[1] - high);

def trueRange;
switch (trailType) {
case modified:
    trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
    trueRange = TrueRange(high, close, low);
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);

def state = {default init, long, short};
def trail;
switch (state[1]) {
case init:
    if (!IsNaN(loss)) {
        switch (firstTrade) {
        case long:
            state = state.long;
            trail =  close - loss;
        case short:
            state = state.short;
            trail = close + loss;
        }
    } else {
        state = state.init;
        trail = Double.NaN;
    }
case long:
    if (close > trail[1]) {
        state = state.long;
        trail = Max(trail[1], close - loss);
    } else {
        state = state.short;
        trail = close + loss;
    }
case short:
    if (close < trail[1]) {
        state = state.short;
        trail = Min(trail[1], close + loss);
    } else {
        state = state.long;
        trail =  close - loss;
    }
}

def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
def SellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);

plot TrailingStop = trail(AvgType, close(period = Period), Length);

TrailingStop.SetPaintingStrategy(PaintingStrategy.POINTS);
TrailingStop.DefineColor("Buy", GetColor(0));
TrailingStop.DefineColor("Sell", GetColor(1));
TrailingStop.AssignValueColor(if state == state.long
    then TrailingStop.Color("Sell")
    else TrailingStop.Color("Buy"));
 
Last edited by a moderator:
Solution
@TOS007 Here is the MTF version of the ATR Trailing Stop indicator

Code:
# ATR Trailing Stop MTF (Multi Timeframe) Version
# Added support for MTF by BenTen at UseThinkScript.com
# Uses the original ATRTrailingStop code provided by ThinkorSwim

input aggregationPeriod = AggregationPeriod.HOUR;
def high = high(period = aggregationPeriod);
def low = low(period = aggregationPeriod);
def close = close(period = aggregationPeriod);

input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 3.5;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;

Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);

def HiLo = Min(high - low, 1.5 * Average(high - low...
@TOS007 Here is the MTF version of the ATR Trailing Stop indicator

Code:
# ATR Trailing Stop MTF (Multi Timeframe) Version
# Added support for MTF by BenTen at UseThinkScript.com
# Uses the original ATRTrailingStop code provided by ThinkorSwim

input aggregationPeriod = AggregationPeriod.HOUR;
def high = high(period = aggregationPeriod);
def low = low(period = aggregationPeriod);
def close = close(period = aggregationPeriod);

input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 3.5;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;

Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);

def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod));
def HRef = if low <= high[1]
    then high - close[1]
    else (high - close[1]) - 0.5 * (low - high[1]);
def LRef = if high >= low[1]
    then close[1] - low
    else (close[1] - low) - 0.5 * (low[1] - high);

def trueRange;
switch (trailType) {
case modified:
    trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
    trueRange = TrueRange(high, close, low);
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);

def state = {default init, long, short};
def trail;
switch (state[1]) {
case init:
    if (!IsNaN(loss)) {
        switch (firstTrade) {
        case long:
            state = state.long;
            trail =  close - loss;
        case short:
            state = state.short;
            trail = close + loss;
        }
    } else {
        state = state.init;
        trail = Double.NaN;
    }
case long:
    if (close > trail[1]) {
        state = state.long;
        trail = Max(trail[1], close - loss);
    } else {
        state = state.short;
        trail = close + loss;
    }
case short:
    if (close < trail[1]) {
        state = state.short;
        trail = Min(trail[1], close + loss);
    } else {
        state = state.long;
        trail =  close - loss;
    }
}

def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
def SellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);

plot TrailingStop = trail;

TrailingStop.SetPaintingStrategy(PaintingStrategy.POINTS);
TrailingStop.DefineColor("Buy", GetColor(0));
TrailingStop.DefineColor("Sell", GetColor(1));
TrailingStop.AssignValueColor(if state == state.long
    then TrailingStop.Color("Sell")
    else TrailingStop.Color("Buy"));

plot pUp = BuySignal;
pUp.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
pUp.SetLineWeight(1);
pUp.AssignValueColor(COLOR.CYAN);

plot pDown = SellSignal;
pDown.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
pDown.SetLineWeight(1);
pDown.AssignValueColor(COLOR.MAGENTA);
 
Solution

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

Thank you so much!

Let's see how price will behave around Daily ATR. (Hull 34 period)

2MsqIE0.png
 
Great posts above. Is there a way to split the trailing stop for the long only and short only trades? When I use the scripts above sometimes the trails don't work.
 
@BenTen

I've created a strategy to short the MES when MACD value goes below average and when DMI Oscillator is negative. I also have a long in the opposite direction.

Here is the study:

Code:
# Buy= pos MACD, positive DMI+ and positive trailing order

# Sell is DMI- below DMI + or trailing stop loss


# TSL

input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 3.5;
input firstTrade = {default long, short};

Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);

def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod));
def HRef = if low <= high[1]
  then high - close[1]
  else (high - close[1]) - 0.5 * (low - high[1]);
def LRef = if high >= low[1]
  then close[1] - low
  else (close[1] - low) - 0.5 * (low[1] - high);
def ATRMod = ExpAverage(Max(HiLo, Max(HRef, LRef)), 2 * ATRPeriod - 1);
def loss;
switch (trailType) {
case modified:
    loss = ATRFactor * ATRMod;
case unmodified:
    loss = ATRFactor * Average(TrueRange(high,  close,  low),  ATRPeriod);
}

def state = {default init, long, short};
def trail;

switch (state[1]) {
case init:
    if (!IsNaN(loss)) {
        switch (firstTrade) {
        case long:
            state = state.long;
            trail =  close - loss;
        case short:
            state = state.short;
            trail = close + loss;
    }
    } else {
        state = state.init;
        trail = Double.NaN;
    }
case long:
    if (close > trail[1]) {
        state = state.long;
        trail = Max(trail[1], close - loss);
    } else {
        state = state.short;
        trail = close + loss;
    }
case short:
    if (close < trail[1]) {
        state = state.short;
        trail = Min(trail[1], close + loss);
    } else {
        state = state.long;
        trail =  close - loss;
    }
}

def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
def SellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);

plot TrailingStop = trail;
TrailingStop.SetPaintingStrategy(PaintingStrategy.POINTS);
TrailingStop.DefineColor("Buy", GetColor(0));
TrailingStop.DefineColor("Sell", GetColor(1));
TrailingStop.AssignValueColor(if state == state.long
  then TrailingStop.Color("Sell")
  else TrailingStop.Color("Buy"));

plot cross = close crosses TrailingStop;
cross.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);




#


# MACD crossover buy on crossover
#

input fastLength = 13;
input slowLength = 21;
input MACDLength = 8;
input averageType = AverageType.EXPONENTIAL;
input showBreakoutSignals = no;

def Value = MovingAverage(averageType, close, fastLength) - MovingAverage(averageType, close, slowLength);
def Avg = MovingAverage(averageType, Value, MACDLength);

def Diff = Value - Avg;
def ZeroLine = 0;

def UpSignal = if Diff crosses above ZeroLine then ZeroLine else Double.NaN;
def DownSignal = if Diff crosses below ZeroLine then ZeroLine else Double.NaN;

def Condition1 =
Value[1] < Avg[1] and
Value > Avg;

def Condition4 =

Value[1] > Avg[1] and Value < Avg;


# DMI oscilator
input DMIlength = 10;
input paintBars = yes;
input DMIIaverageType = AverageType.WILDERS;

def diPlus = DMI(DMIlength, averageType)."DI+";
def diMinus = DMI(DMIlength, averageType)."DI-";

def Osc = diPlus - diMinus;
def Hist = Osc;
def DMIZeroLine = 0;




# DMI oscilator




def condition10 = if Osc  > 0 then 1 else 0;

def condition2 = close () > TrailingStop;



def buy = condition10 > 0 and Condition1 > 0 and condition2 > 0;

def sell2 = SellSignal > 0;

def condition5 = if Osc <0 then 1 else 0;

def buy2 = Condition4 > 0 and condition5 > 0;


AddOrder(OrderType.BUY_TO_OPEN, buy, name = "MACD-DI Buy", tickcolor = Color.CYAN, arrowcolor = Color.CYAN);

AddOrder(OrderType.SELL_TO_OPEN, buy2, name = "MACD-DI Short", tickcolor = Color.GREEN, arrowcolor = Color.GREEN);


AddOrder(OrderType.SELL_TO_CLOSE, sell2, name = "SL EXIT", tickcolor = Color.WHITE, arrowcolor = Color.WHITE);

AddOrder(OrderType.BUY_TO_CLOSE, sell2, name = "SL EXIT", tickcolor = Color.RED, arrowcolor = Color.RED);

Here is the screen:

8Y6mxFs.png
 
Last edited by a moderator:
Hello group,

I'm relatively new to coding TOS.. Tried to paste the code by BenTen into the script editor and it doesn't work. Could anyone suggest how to?
Also, I tried to code a strategy into TOS using different indicators on 2 time frames. TOS staff say it is not possible:

"It's possible you could create a custom study that would only be considered true based on multiple studies if you have some good coding knowledge but we don't offer thinkscript support through chat unfortunately."

Anyone could help please....taking 2 diff indict on 2 time frames?
 
I went to edit studies, create a new study and added the code into the editor. The study does not show up in a chart. Here is a link to a Google drive with the screenshots.

A6sKxeX.jpg
 
Last edited:
@C4men - This may help you out.
Code:
# SuperTrend CCI ATR Base
# hguru | Paris | BLT
# 5.27.2019

# Paris: I dissected the ST Supertrend CCI ATR study hguru posted earlier,
# this combo study is a mashup of three major components (1) Super Trend
# Syracuse + BLT Extensions  (2) Mobius CCI ATR Trendline and (3) Combo
# Additions from Ghost. I have sectionalized the study, moved some of the
# variable/input definitions to the appropriate segment, and inserted the
# headers for any future work surrounding this study. Loaded it, and it
# works great.
#
# Paris: From an earlier request from hguru, I coordinated an MTF approach
# to this study with "extensive" collaboration from BLT. The code has been
# reorganized as well as introduced other mods to accomodate a MTF look.
#
# Due to the complexities of the info being processed, the approach taken
# does not streamline combining the MTF in a single study as found in many
# other MTF studies previously posted. Rather, we have implemented this
# MTF using the following two studies
#
# [1] SuperTrend CCI ATR Base
# [2] SuperTrend CCI ATR HigherAgg
#
# The 'base' study is used with possible settings made for the chart agg
# while the 'higher agg' study is configured for the type of settings one
# wants for those higher aggs. There are very slight differences between
# these two studies.
#
# To run through an illustration, for a 5m/15m/30m MTF setup, we have a
# 'base' set at 5m with two 'higher agg' set at 15m and 30m. For an actual
# chart setup, please refer to the attached tos.mx link.
#
# If you'd like an alternate MTF setup, say 4hour, Day, and Week, set the
# base aggregation to 4h, and two instances of the higher aggregation study,
# one to Day, and the other to Week. You get the idea.
#
# There is a workaround for the entry/exit arrows/bubbles and vertical
# lines to only display the first bar of the 'higher agg' being displayed
# on the 'lower agg'. Usually, when a condition is met on a 'higher agg'
# being displayed on the 'lower agg', an arrow, bubble or vertical is
# displayed on each bar of the 'lower agg' for the 'higher agg' period.

input agg = AggregationPeriod.FIVE_MIN;
def c = close(period = agg);
def h = high(period = agg);
def l = low(period = agg);
def pricedata = hl2(period = agg);

input pricecolor = {none, default combopricecolor, stpricecolor,  CCIATRPriceColor};

input showentrybubble = yes;
input number_entry_bubbles_tobe_displayed = 3;
input showlocationbubble = no;
input showpositionbubble = no;

input show_cloud = yes;
input show_vertLine = yes;
input show_entryarrows = yes;

DefineGlobalColor("TrendUp", CreateColor(0, 255, 255));
DefineGlobalColor("TrendDown", CreateColor(0, 102, 255));

# Super Trend Syracuse + BLT Extensions + PSAR
# Syracuse
# 10.29.2018

# This SuperTrend might be the best one as it does not 
# sit on top of a candle it gives room to make decisions

#============================= SuperTrend 2016 ===========================#
#==================== Translation for TOS by Syracusepro =================#
input Factor = 1.3;
input Pd = 60;
input Lookback = 3;

def atr_st = Average(TrueRange(h, c, l), Pd);
def Up = pricedata[Lookback] - (Factor * atr_st);
def Dn = pricedata[Lookback] + (Factor * atr_st);
def TrendUp = if c > TrendUp[1] then Max(Up, TrendUp[1]) else Up;
def TrendDown = if c < TrendDown[1] then Min(Dn, TrendDown[1]) else Dn;
def Trend = if c > TrendDown[1] then 1 else if c < TrendUp[1] then -1 else (Trend[1]);
def Trendbn = if c > TrendDown[1] then BarNumber() else if c < TrendUp[1] then BarNumber() else (Trendbn[1]);
def Trendc = if c > TrendDown[1] then c else if c < TrendUp[1] then c else (Trendc[1]);

plot Tsl = if Trend == 1 then TrendUp else TrendDown;
Tsl.AssignValueColor(if Trend == 1 then GlobalColor("TrendUp") else GlobalColor("TrendDown"));
Tsl.SetLineWeight(1);

plot entryArrow = (if Trend == 1 and Trend[1] == -1 then First(Trendbn) else Double.NaN); #Up Entry Arrow
entryArrow.SetDefaultColor(Color.WHITE);
entryArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
entryArrow.SetHiding(!show_entryarrows);

plot exitArrow = (if Trend == -1 and Trend[1] == 1 then First(Trendbn) else Double.NaN); #Down Entry Arrow
exitArrow.SetDefaultColor(Color.YELLOW);
exitArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
exitArrow.SetHiding(!show_entryarrows);

#========================== End SuperTrend 2016 ===========================#

# CCI_ATR Trendline
# Mobius | Syracusepro
# Chat room request 01.28.2016
# 10.31.2018

# CCI is a study that measures distance from the mean. This study plots
# a trend line based on that distance using ATR as the locator for the line.

input lengthCCI = 20;
input lengthATR = 4;
input AtrFactor = 0.7;

def ATRcci = Average(TrueRange(h, c, l), lengthATR) * AtrFactor;
def price = c + l + h;
def linDev = LinDev(price, lengthCCI);
def CCI = if linDev == 0
          then 0
          else (price - Average(price, lengthCCI)) / linDev / 0.015;
def MT1 = if CCI > 0
          then Max(MT1[1], pricedata - ATRcci)
          else Min(MT1[1], pricedata + ATRcci);
plot data = MT1;
data.AssignValueColor(if c < MT1 then Color.RED else Color.GREEN);#TAKEN FROM SUPERTREND AND APPLIED ACCORDING THE VARIABLES FOR GREEN, RED LINE -----#

# End Code CCI_ATR Trend

########################################################
# Combo Additions
# Ghost / Hguru
# 2.3.2019

def ComboUpTrend = data > Tsl;
def ComboDnTrend = data < Tsl;
def crossup = ComboUpTrend == 1 and ComboUpTrend[1] <> 1;
def crossdn = ComboDnTrend == 1 and ComboDnTrend[1] <> 1;

AddCloud(if show_cloud and ComboUpTrend == 1 then data
                             else Double.NaN, if show_cloud and ComboUpTrend then Tsl
                             else Double.NaN, GlobalColor("TrendUp"), GlobalColor("TrendUp"));
AddCloud(if show_cloud and ComboDnTrend == 1 then Tsl
                             else Double.NaN, if show_cloud and ComboDnTrend == 1 then data
                             else Double.NaN, GlobalColor("TrendDown"), GlobalColor("TrendDown"));

AddVerticalLine(show_vertLine and entryarrow , astext(c), Color.UPTICK, Curve.POINTS);
AddVerticalLine(show_vertLine and exitarrow, astext(c), Color.DOWNTICK, Curve.POINTS);

################################################################
#Price Color

#Combo pricecolor
AssignPriceColor(if pricecolor == pricecolor.combopricecolor
                 then if ComboUpTrend == 1
                      then Color.GREEN
                      else if ComboDnTrend == 1 then Color.RED
                 else Color.GRAY else Color.CURRENT);

#Supertrend pricecolor
AssignPriceColor(if pricecolor == pricecolor.stpricecolor
                 then if !IsNaN(entryArrow)
                      then Color.WHITE   
                      else if !IsNaN(exitArrow)   
                      then Color.YELLOW
                      else if Trend == 1
                      then Color.GREEN
                      else if Trend == -1 then Color.RED
                 else Color.CURRENT else Color.CURRENT);

#CCI ATR pricecolor
AssignPriceColor(if pricecolor == pricecolor.CCIATRPriceColor and c < MT1
                 then GlobalColor("TrendDown")
                 else if pricecolor == pricecolor.CCIATRPriceColor and c > MT1
                      then GlobalColor("TrendUp")
                      else Color.CURRENT);

#################################################################
#Bubbles

#Buy/Sell Bubbles
input buysell_bubblemoversideways = 0;
def bm = buysell_bubblemoversideways + 1;
input buysell_bubblemoverupdown = 10;

def dataCount         = CompoundValue(1, if !IsNaN(entryArrow) or !IsNaN(exitArrow)
                                         then dataCount[1] + 1
                                         else dataCount[1], 0);
def HUp    = if entryarrow then l else double.nan ;
def HDn    = if exitarrow  then h else double.nan;

AddChartBubble(showentrybubble and crossdn and HighestAll(dataCount) - dataCount <= number_entry_bubbles_tobe_displayed - 1, hdn + ticksize()*buysell_bubblemoverupdown, agg/60000 + " min\nSell @ " + astext(c), Color.MAGENTA, yes);
AddChartBubble(showentrybubble and crossup and HighestAll(dataCount) - dataCount <= number_entry_bubbles_tobe_displayed - 1, hup-ticksize()*buysell_bubblemoverupdown, agg/60000 + " min\nBuy @ " + astext(c), Color.YELLOW, no);

#Location Bubble - Supertrend
input Location_Horizontal = 3;
input Location_Vertical = 0;

def X_h = Location_Horizontal;
def Y_v = Location_Vertical;
def X_h1  = X_h + 1;

input Location_bubbledecimal = 2;
AddChartBubble(showlocationbubble and IsNaN(c[X_h]) and !IsNaN(c[X_h1]), close[X_h1] + TickSize() * Y_v,  "ST: " + Round(Tsl[X_h1], Location_bubbledecimal), if Trend[X_h1] == 1 then Color.GREEN else
Color.PINK, no);#if Trend[X_h1] == -1 then Color.MAGENTA else Color.WHITE, no);

#Position Bubble - Supertrend
input Position_bubblemoverside = 3;
def bubm = Position_bubblemoverside + 1;
input Position_bubblemoverVert   = 0;
input Position_bubbledec = 2;

AddChartBubble(showpositionbubble and IsNaN(close[Position_bubblemoverside]) and !IsNaN(close[bubm]), Tsl[bubm] + Position_bubblemoverVert * TickSize(), "ST      " + Round(Tsl[bubm], Position_bubbledec), if Tsl[bubm]
< data[bubm] then Color.MAGENTA else Color.YELLOW, if Tsl[bubm] < data[bubm] then no else yes);

#Position Bubble - CCI
AddChartBubble(showpositionbubble and IsNaN(close[Position_bubblemoverside]) and !IsNaN(close[bubm]), data[bubm] + Position_bubblemoverVert * TickSize(), "CCI      " + Round(data[bubm], Position_bubbledec), if data
[bubm] < Tsl[bubm] then Color.MAGENTA else Color.YELLOW, if data[bubm] < Tsl[bubm] then yes else no);

# END STUDY
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
249 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.
Back
Top