Battle of the Bands Indicator for ThinkorSwim

horserider

Well-known member
VIP
Just reviewing some old charts and ran across this one. BB,ATR and IV bands. Has some labels also. If anyone can make us of it here you go.

Code:
# Battle of the Bands
# Implied Volatility Bands
# ATR Bands
# Bollinger Bands
# Mobius
# Added ATR label. Added conditional color for labels. Altered bands on lower aggs. to 100% IV spread from mean. Altered coding structure to be more efficient.
# V02.10.17.2013

# Hide Study Name and Inputs ###########################
plot X = Double.NaN;                                   #
X.SetDefaultColor(CreateColor ( 0, 0, 0 ));            #
########################################################

declare hide_on_daily;

input n = 21;
input IvDailyBands = no;
input IvHourBands = no;
input IV15minBands = yes;
input AtrBands = no;
input BollingerBands = yes;
input DisplayLabels = yes;

def o = open;
def h = high;
def l = low;
def c = close;
def period = AggregationPeriod.DAY;
def hd = high(period = period);
def ld = low(period = period);
def cd = close(period = period);
def DaysMean = hl2(period = period);
def HoursMean = hl2(period = AggregationPeriod.HOUR);
def IVd = imp_Volatility(period = period);
def IV = if isNaN(IVd) then IV[1] else IVd;
def hIV = Highest(IV, 252);
def lIV = Lowest(IV, 252);
def IVpercentile = (IV - lIV) / (hIV - lIV);
AddLabel(DisplayLabels, "IV " + AsPercent(IV) +
                         "  IV Percentile: " + AsPercent(IVpercentile)
                       , if IsAscending(IV)
                         then Color.GREEN
                         else if IsDescending(IV)
                         then Color.RED
                         else Color.WHITE);
def ATR = Average(TrueRange(h, c, l), n);
def ATRd = Average(TrueRange(hd, cd, ld), n);
def SDatr = StDev(ATRd, 252);
def hATR = Highest(SDatr, 252);
def lATR = Lowest(SDatr, 252);
def ATRpercentile = (SDatr - lATR) / (hATR - lATR);
def DaysIV = IV / Sqrt(252);
def DaysIVSD = StDev(DaysIV, n);
def DaysIVValue = Round((DaysMean * DaysIV) / TickSize(), 0) * TickSize();
AddLabel(DisplayLabels, Concat("Days IV " + AsPercent(DaysIV), " Value $" + DaysIVValue),
                    if IsAscending(DaysIV)
                    then Color.GREEN
                    else if IsDescending(DaysIV)
                    then Color.RED
                    else Color.WHITE);
def HoursIV = IV / Sqrt(5796);
def HoursIVSD = StDev(HoursIV, n);
def HoursIVValue = Round((HoursMean * HoursIV) / TickSize(), 0) * TickSize();
AddLabel(DisplayLabels, Concat("Hours IV " + AsPercent(HoursIV), " Value $" + HoursIVValue),
                    if IsAscending(HoursIV)
                    then Color.GREEN
                    else if IsDescending(HoursIV)
                    then Color.RED
                    else Color.WHITE);
def IV15min = IV / Sqrt(23184);
def IV15minSD = StDev(IV15min, n);
def IV15mValue = Round((c * IV15min) / TickSize(), 0) * TickSize();
AddLabel(DisplayLabels, Concat("15min IV " + AsPercent(IV15min), " Value $" + IV15mValue),
                     if IsAscending(IV15min)
                     then Color.GREEN
                     else if IsDescending(IV15min)
                     then Color.RED
                     else Color.WHITE);

plot DaysIVhigh = DaysMean + ((DaysIVValue) / 2);
DaysIVhigh.SetDefaultColor(Color.ORANGE);
DaysIVhigh.SetHiding(!IvDailyBands);
DaysIVhigh.SetPaintingStrategy(PaintingStrategy.DASHES);
plot DaysIVlow = DaysMean - ((DaysIVValue) / 2);
DaysIVlow.SetDefaultColor(Color.ORANGE);
DaysIVlow.SetHiding(!IvDailyBands);
DaysIVlow.SetPaintingStrategy(PaintingStrategy.DASHES);
plot HoursIVhigh = Average(HoursMean + HoursIVValue, n);
HoursIVhigh.SetDefaultColor(Color.CYAN);
HoursIVhigh.SetHiding(!IvHourBands);
plot HoursIVlow = Average(HoursMean - HoursIVValue, n);
HoursIVlow.SetDefaultColor(Color.CYAN);
HoursIVlow.SetHiding(!IvHourBands);
plot IV15minhigh = Inertia(c + (c * IV15minSD), n);
IV15minhigh.SetDefaultColor(Color.YELLOW);
IV15minhigh.SetHiding(!IV15minBands);
plot IV15minlow = Inertia(c - (c * IV15minSD), n);
IV15minlow.SetDefaultColor(Color.YELLOW);
IV15minlow.SetHiding(!IV15minBands);
plot ATRup = Inertia(c + ATR, n);
ATRup.SetHiding(!AtrBands);
plot ATRdn = Inertia(c - ATR, n);
ATRdn.SetHiding(!AtrBands);

def SD = StDev(close, n);
def Avg = Average(close, n);

plot SDup = Avg + (2 * SD);
SDup.SetDefaultColor(Color.GREEN);
SDup.SetHiding(!BollingerBands);
plot SDdn = Avg + (-2 * SD);
SDdn.SetDefaultColor(Color.GREEN);
SDdn.SetHiding(!BollingerBands);

#AssignPriceColor(if (SDup < IV15minhigh) or
#                     (SDdn > IV15minlow)
#                  then Color.PLUM
#                  else Color.CURRENT);
AddLabel(DisplayLabels, "ATR Chart Agg. = $" + (Round(ATR / TickSize(), 0) * TickSize()) +
                        "  ATR Daily $" + (Round(ATRd / TickSize(), 0) * TickSize()) +
                        "  ATR Percentile: " + AsPercent(ATRpercentile),
                                  if ATR > ATR[1]
                                  then Color.GREEN
                                  else if ATR < ATR[1]
                                  then Color.RED
                                  else Color.WHITE);

# End Code Battle of the Bands
 
Can any make this in ThinkScript?
I am trying to make ATR Bands and I found some code but it isn't in ThinkScript. The parameters are below and here is an article that got my attention on the indicator https://www.incrediblecharts.com/indicators/atr_average_true_range_bands.php
  • Average True Range is calculated in accordance with J. Welles Wilder's formula.
  • The bands are calculated by adding/subtracting a multiple of Average True Range to the daily closing price.
  • For the HighLow option, the multiple of ATR is added to the daily Low, and subtracted from the daily High.
  • A ratchet mechanism ensures that the lower band only moves up in an up-trend and the upper band only moves down in a down-trend.
  • Plots are projected one day forward (e.g. the stop caculated from today's closing price is plotted for tomorrow)
Code:
//---- input parameters
extern int       TimeFrame = 0;
extern int       Length    = 21;
extern int       MA_Type   = 0;
extern int       Shift     = 0;
extern int       Price     = 0;
extern double    TimesATR  = 4.0;
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle ( 0, DRAW_LINE, STYLE_DOT );
   SetIndexBuffer( 0, ExtMapBuffer1 );
   SetIndexStyle ( 1, DRAW_LINE, STYLE_DOT );
   SetIndexBuffer( 1, ExtMapBuffer2 );
   SetIndexStyle ( 2, DRAW_LINE, STYLE_DOT );
   SetIndexBuffer( 2, ExtMapBuffer3 );
  
   SetIndexLabel ( 0, Length + " KChanUp" );
   SetIndexLabel ( 1, Length + " KChanMid");
   SetIndexLabel ( 2, Length + " KChanLow");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
  
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars = IndicatorCounted();
   int    limit        = Bars - counted_bars;
   int    i = 0;
  
//----Check for possible errors
   if ( counted_bars < 0 ) return ( -1 );
      
//----Last counted bar will be recounted
   if ( counted_bars > 0 ) counted_bars-- ;
  
   double MA = 0;   
   double ATR =0; iATR ( NULL, TimeFrame, Length, i );
  
//---Main calculation Loop
   for (i = 0; i < limit; i++ )
      
       {
         MA  = iMA ( NULL, TimeFrame, Length, Shift, MA_Type, Price, i );
         ATR = iATR( NULL, TimeFrame, Length, i );
              
         ExtMapBuffer1[i] = MA + ATR * TimesATR ;
        
         ExtMapBuffer2[i] = MA;
                                  
         ExtMapBuffer3[i] = MA - ATR * TimesATR ;
       }                         

  
   return(0);
  }
//+------------------------------------------------------------------+
 

dasdasf

New member
I was scrolling through the site the other day and found this cool indicator and tested it out today. I was hoping someone could help create some type of watchlist signal for the Daily IV bands so anyone who would like to use the indicator wouldn't have to sift through stocks to find their trade.file:///D:/Battle%20of%20the%20bands.PNG

The code:
# Battle of the Bands
# Implied Volatility Bands
# ATR Bands
# Bollinger Bands
# Mobius
# Added ATR label. Added conditional color for labels. Altered bands on lower aggs. to 100% IV spread from mean. Altered coding structure to be more efficient.
# V02.10.17.2013

declare hide_on_daily;

input n = 21;
input IvDailyBands = no;
input IvHourBands = no;
input IV15minBands = yes;
input AtrBands = no;
input BollingerBands = yes;
input DisplayLabels = yes;

def o = open;
def h = high;
def l = low;
def c = close;
def period = AggregationPeriod.DAY;
def hd = high(period = period);
def ld = low(period = period);
def cd = close(period = period);
def DaysMean = hl2(period = period);
def HoursMean = hl2(period = AggregationPeriod.HOUR);
def IVd = imp_Volatility(period = period);
def IV = if isNaN(IVd) then IV[1] else IVd;
def hIV = Highest(IV, 252);
def lIV = Lowest(IV, 252);
def IVpercentile = (IV - lIV) / (hIV - lIV);
AddLabel(DisplayLabels, "IV " + AsPercent(IV) +
" IV Percentile: " + AsPercent(IVpercentile)
, if IsAscending(IV)
then Color.GREEN
else if IsDescending(IV)
then Color.RED
else Color.WHITE);
def ATR = Average(TrueRange(h, c, l), n);
def ATRd = Average(TrueRange(hd, cd, ld), n);
def SDatr = StDev(ATRd, 252);
def hATR = Highest(SDatr, 252);
def lATR = Lowest(SDatr, 252);
def ATRpercentile = (SDatr - lATR) / (hATR - lATR);
def DaysIV = IV / Sqrt(252);
def DaysIVSD = StDev(DaysIV, n);
def DaysIVValue = Round((DaysMean * DaysIV) / TickSize(), 0) * TickSize();
AddLabel(DisplayLabels, Concat("Days IV " + AsPercent(DaysIV), " Value $" + DaysIVValue),
if IsAscending(DaysIV)
then Color.GREEN
else if IsDescending(DaysIV)
then Color.RED
else Color.WHITE);
def HoursIV = IV / Sqrt(5796);
def HoursIVSD = StDev(HoursIV, n);
def HoursIVValue = Round((HoursMean * HoursIV) / TickSize(), 0) * TickSize();
AddLabel(DisplayLabels, Concat("Hours IV " + AsPercent(HoursIV), " Value $" + HoursIVValue),
if IsAscending(HoursIV)
then Color.GREEN
else if IsDescending(HoursIV)
then Color.RED
else Color.WHITE);
def IV15min = IV / Sqrt(23184);
def IV15minSD = StDev(IV15min, n);
def IV15mValue = Round((c * IV15min) / TickSize(), 0) * TickSize();
AddLabel(DisplayLabels, Concat("15min IV " + AsPercent(IV15min), " Value $" + IV15mValue),
if IsAscending(IV15min)
then Color.GREEN
else if IsDescending(IV15min)
then Color.RED
else Color.WHITE);

plot DaysIVhigh = DaysMean + ((DaysIVValue) / 2);
DaysIVhigh.SetDefaultColor(Color.ORANGE);
DaysIVhigh.SetHiding(!IvDailyBands);
DaysIVhigh.SetPaintingStrategy(PaintingStrategy.DASHES);
plot DaysIVlow = DaysMean - ((DaysIVValue) / 2);
DaysIVlow.SetDefaultColor(Color.ORANGE);
DaysIVlow.SetHiding(!IvDailyBands);
DaysIVlow.SetPaintingStrategy(PaintingStrategy.DASHES);
plot HoursIVhigh = Average(HoursMean + HoursIVValue, n);
HoursIVhigh.SetDefaultColor(Color.CYAN);
HoursIVhigh.SetHiding(!IvHourBands);
plot HoursIVlow = Average(HoursMean - HoursIVValue, n);
HoursIVlow.SetDefaultColor(Color.CYAN);
HoursIVlow.SetHiding(!IvHourBands);
plot IV15minhigh = Inertia(c + (c * IV15minSD), n);
IV15minhigh.SetDefaultColor(Color.YELLOW);
IV15minhigh.SetHiding(!IV15minBands);
plot IV15minlow = Inertia(c - (c * IV15minSD), n);
IV15minlow.SetDefaultColor(Color.YELLOW);
IV15minlow.SetHiding(!IV15minBands);
plot ATRup = Inertia(c + ATR, n);
ATRup.SetHiding(!AtrBands);
plot ATRdn = Inertia(c - ATR, n);
ATRdn.SetHiding(!AtrBands);

def SD = StDev(close, n);
def Avg = Average(close, n);

plot SDup = Avg + (2 * SD);
SDup.SetDefaultColor(Color.GREEN);
SDup.SetHiding(!BollingerBands);
plot SDdn = Avg + (-2 * SD);
SDdn.SetDefaultColor(Color.GREEN);
SDdn.SetHiding(!BollingerBands);

#AssignPriceColor(if (SDup < IV15minhigh) or
# (SDdn > IV15minlow)
# then Color.PLUM
# else Color.CURRENT);
AddLabel(DisplayLabels, "ATR Chart Agg. = $" + (Round(ATR / TickSize(), 0) * TickSize()) +
" ATR Daily $" + (Round(ATRd / TickSize(), 0) * TickSize()) +
" ATR Percentile: " + AsPercent(ATRpercentile),
if ATR > ATR[1]
then Color.GREEN
else if ATR < ATR[1]
then Color.RED
else Color.WHITE);

# End Code Battle of the Bands
 

Joshua

Well-known member
VIP
The scan itself can only use one aggregation. It would have to be set to daily data as a work around. It will most likely pump out a huge number of symbols for you to sort through regardless. Here it is though. You can easily edit the last line to just check for one or the other. I haven't tested it that much either I just tried to scrape out the necessary code.

Code:
input n = 21;
input IvDailyBands = Yes;
input DisplayLabels = yes;
def o = open;
def h = high;
def l = low;
def c = close;
def hd = high();
def ld = low();
def cd = close();
def DaysMean = hl2();
def IVd = imp_Volatility();
def IV = if isNaN(IVd) then IV[1] else IVd;
def hIV = Highest(IV, 252);
def lIV = Lowest(IV, 252);
def IVpercentile = (IV - lIV) / (hIV - lIV);
def ATR = Average(TrueRange(h, c, l), n);
def ATRd = Average(TrueRange(hd, cd, ld), n);
def SDatr = StDev(ATRd, 252);
def hATR = Highest(SDatr, 252);
def lATR = Lowest(SDatr, 252);
def ATRpercentile = (SDatr - lATR) / (hATR - lATR);
def DaysIV = IV / Sqrt(252);
def DaysIVSD = StDev(DaysIV, n);
def DaysIVValue = Round((DaysMean * DaysIV) / TickSize(), 0) * TickSize();
def DaysIVhigh = DaysMean + ((DaysIVValue) / 2);
def DaysIVlow = DaysMean - ((DaysIVValue) / 2);
plot Scan = high > DaysIVhigh or Low < DaysIVlow;
 

conmayne

Member
VIP
A code from mobius. I use the Daily IV plot ranges on intraday. I want to code a scan for price that has crossed the "daysivlow" but not the "daysivhigh" on the day.



# Battle of the Bands
# Implied Volatility Bands
# ATR Bands
# Bollinger Bands
# Mobius
# Added ATR label. Added conditional color for labels. Altered bands on lower aggs. to 100% IV spread from mean. Altered coding structure to be more efficient.
# V02.10.17.2013

declare hide_on_daily;

input n = 21;
input IvDailyBands = no;
input IvHourBands = no;
input IV15minBands = yes;
input AtrBands = no;
input BollingerBands = yes;
input DisplayLabels = yes;

def o = open;
def h = high;
def l = low;
def c = close;
def period = AggregationPeriod.DAY;
def hd = high(period = period);
def ld = low(period = period);
def cd = close(period = period);
def DaysMean = hl2(period = period);
def HoursMean = hl2(period = AggregationPeriod.HOUR);
def IVd = imp_Volatility(period = period);
def IV = if isNaN(IVd) then IV[1] else IVd;
def hIV = Highest(IV, 252);
def lIV = Lowest(IV, 252);
def IVpercentile = (IV - lIV) / (hIV - lIV);
AddLabel(DisplayLabels, "IV " + AsPercent(IV) +
" IV Percentile: " + AsPercent(IVpercentile)
, if IsAscending(IV)
then Color.GREEN
else if IsDescending(IV)
then Color.RED
else Color.WHITE);
def ATR = Average(TrueRange(h, c, l), n);
def ATRd = Average(TrueRange(hd, cd, ld), n);
def SDatr = StDev(ATRd, 252);
def hATR = Highest(SDatr, 252);
def lATR = Lowest(SDatr, 252);
def ATRpercentile = (SDatr - lATR) / (hATR - lATR);
def DaysIV = IV / Sqrt(252);
def DaysIVSD = StDev(DaysIV, n);
def DaysIVValue = Round((DaysMean * DaysIV) / TickSize(), 0) * TickSize();
AddLabel(DisplayLabels, Concat("Days IV " + AsPercent(DaysIV), " Value $" + DaysIVValue),
if IsAscending(DaysIV)
then Color.GREEN
else if IsDescending(DaysIV)
then Color.RED
else Color.WHITE);
def HoursIV = IV / Sqrt(5796);
def HoursIVSD = StDev(HoursIV, n);
def HoursIVValue = Round((HoursMean * HoursIV) / TickSize(), 0) * TickSize();
AddLabel(DisplayLabels, Concat("Hours IV " + AsPercent(HoursIV), " Value $" + HoursIVValue),
if IsAscending(HoursIV)
then Color.GREEN
else if IsDescending(HoursIV)
then Color.RED
else Color.WHITE);
def IV15min = IV / Sqrt(23184);
def IV15minSD = StDev(IV15min, n);
def IV15mValue = Round((c * IV15min) / TickSize(), 0) * TickSize();
AddLabel(DisplayLabels, Concat("15min IV " + AsPercent(IV15min), " Value $" + IV15mValue),
if IsAscending(IV15min)
then Color.GREEN
else if IsDescending(IV15min)
then Color.RED
else Color.WHITE);

plot DaysIVhigh = DaysMean + ((DaysIVValue) / 2);
DaysIVhigh.SetDefaultColor(Color.ORANGE);
DaysIVhigh.SetHiding(!IvDailyBands);
DaysIVhigh.SetPaintingStrategy(PaintingStrategy.DASHES);
plot DaysIVlow = DaysMean - ((DaysIVValue) / 2);
DaysIVlow.SetDefaultColor(Color.ORANGE);
DaysIVlow.SetHiding(!IvDailyBands);
DaysIVlow.SetPaintingStrategy(PaintingStrategy.DASHES);
plot HoursIVhigh = Average(HoursMean + HoursIVValue, n);
HoursIVhigh.SetDefaultColor(Color.CYAN);
HoursIVhigh.SetHiding(!IvHourBands);
plot HoursIVlow = Average(HoursMean - HoursIVValue, n);
HoursIVlow.SetDefaultColor(Color.CYAN);
HoursIVlow.SetHiding(!IvHourBands);
plot IV15minhigh = Inertia(c + (c * IV15minSD), n);
IV15minhigh.SetDefaultColor(Color.YELLOW);
IV15minhigh.SetHiding(!IV15minBands);
plot IV15minlow = Inertia(c - (c * IV15minSD), n);
IV15minlow.SetDefaultColor(Color.YELLOW);
IV15minlow.SetHiding(!IV15minBands);
plot ATRup = Inertia(c + ATR, n);
ATRup.SetHiding(!AtrBands);
plot ATRdn = Inertia(c - ATR, n);
ATRdn.SetHiding(!AtrBands);

def SD = StDev(close, n);
def Avg = Average(close, n);

plot SDup = Avg + (2 * SD);
SDup.SetDefaultColor(Color.GREEN);
SDup.SetHiding(!BollingerBands);
plot SDdn = Avg + (-2 * SD);
SDdn.SetDefaultColor(Color.GREEN);
SDdn.SetHiding(!BollingerBands);

#AssignPriceColor(if (SDup < IV15minhigh) or
# (SDdn > IV15minlow)
# then Color.PLUM
# else Color.CURRENT);
AddLabel(DisplayLabels, "ATR Chart Agg. = $" + (Round(ATR / TickSize(), 0) * TickSize()) +
" ATR Daily $" + (Round(ATRd / TickSize(), 0) * TickSize()) +
" ATR Percentile: " + AsPercent(ATRpercentile),
if ATR > ATR[1]
then Color.GREEN
else if ATR < ATR[1]
then Color.RED
else Color.WHITE);

# End Code Battle of the Bands

The scan itself can only use one aggregation. It would have to be set to daily data as a work around. It will most likely pump out a huge number of symbols for you to sort through regardless. Here it is though. You can easily edit the last line to just check for one or the other. I haven't tested it that much either I just tried to scrape out the necessary code.
how would I code for price that has crossed the "daysivlow" but not the "daysivhigh" on the day. and vice versa.
 

Joshua

Well-known member
VIP
Change

Plot Scan = high > DaysIVhigh or Low < DaysIVlow;

to only

plot Scan = high > DaysIVhigh;

Or

Plot Scan = Low < DaysIVlow;
 

conmayne

Member
VIP
Change

Plot Scan = high > DaysIVhigh or Low < DaysIVlow;

to only

plot Scan = high > DaysIVhigh;

Or

Plot Scan = Low < DaysIVlow;
what i've noticed is sometimes price gaps up touching both ranges. Is there a way in thinkscript to code for close =< daysivlow and also has not touched daysivhigh yet.
 

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.
Top