+ Bollinger Bands Width
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ClassicScott

// Here is my rendition of Bollinger Bands Width. If you are unfamiliar, Bollinger Bands Width is a measure of the distance between the top and
// bottom bands of Bollinger Bands. Bollinger Bands themselves being a measure of market volatility, BB Width is a simpler, cleaner way of
// determining the amount of volatility in the market. Myself, I found the original, basic version of BB Width a bit too basic, and I thought
// that by adding to it it might make for an improvement for traders over the original.

// Simple things that I've done are adding a signal line; adding a 'baseline' using Donchian Channels (such as that which is in my Average Candle
// Bodies Range indicator); adding bar and background coloring; and adding alerts for increasing volatility, and baseline and signal line crosses.
// It really ends up making for a much improved version of the basic indicator.

// A note on how I created the baseline:
// First, what do I mean by 'baseline?' I think of it as an area of the indicator where if the BB Width is below you will not want to enter into
// any trades, and if the BB Width is above then you are free to enter trades based on your system. It's basically a volatility measure of the
// volatility indicator. Waddah Attar Explosion is a popular indicator that implements something similar. The baseline is calculated thus:
// make a Donchian Channel of the BB Width, and then use the basis as the baseline while not plotting the actual highs and lows of the Donchian
// Channel. Now, the basis of a Donchian Channel is the average of the highs and the lows. If we did that here we would have a baseline much too
// high, however, by making the basis adjustable with a divisor input it no longer must be plotted in the center of the channel, but may be moved
// much lower (unless you set the divisor to 2, but you wouldn't do that). This divisor is essentially a sensitivity adjustment for the indicator.
// Of course you don't have to use the baseline. You could ignore it and only use the signal line, or just use the rising and falling of the
// BB Width by itself as your volatility measure.


// *** A note on colors in the style tab
// I truly do not understand why TradingView has every single color grouped together under (nearly) every single adjustable element of the indicator.
// It makes no sense to me because only certain colors apply to certain aspects of it. I'm going to help you out here by giving you a cheat sheet
// so you can make color changes more easily.
// Colors 0 and 1 apply to the BB Width plot.
// Colors 2 and 3 apply to the signal line.
// Colors 4 and 5 apply to the background coloring.
// Colors 6 and 7 apply to advancing and declining volatility (bar color for crosses)
// Colors 2, 3, and 8 apply to bar colors


//@version=5
indicator(title='+ Bollinger Bands Width', shorttitle='+ BBW', overlay=false)


//BBW INPUTS\\
src = input(close, title='Source', group='Bollinger Bands Width Inputs')
length = input.int(8, minval=1, title='Period', group='Bollinger Bands Width Inputs')

////BOLLINGER BANDS WIDTH CALCULATIONS
basis = ta.sma(src, length)
dev = 2 * ta.stdev(src, length)
upper = basis + dev
lower = basis - dev
bbw = (upper - lower) / basis


////OTHER INPUTS & OPTIONS\\\\

//SIGNAL LINE INPUTS
signal_type = input.string(defval='HMA', options=['EMA', 'HMA', 'RMA', 'SMA', 'VWMA', 'WMA'], title='Signal Type', group='Signal Line Inputs')
signal_period = input.int(defval=13, title='Period', group='Signal Line Inputs')

//BASELINE INPUTS
vol_period_type = input.string(defval='RexDog Self-Adjusting', options=['RexDog Self-Adjusting', 'User Selected'], title='Baseline Period Type', group='Baseline Inputs', tooltip='RexDog Self-Adjusting is based on the RexDog Average by xkavalis. It is an average of six different averages, thus it is dynamic, or self-adjusting, and can not be changed by the user. If you want to be able to choose an averaging period yourself select User Selected.')
vol_period = input.int(defval=21, title='Period', group='Baseline Inputs')
divisor = input.float(defval=3.5, title='Divisor',minval=0.1, maxval=10, step=0.1, group='Baseline Inputs')

//DOES BOLLINGER BANDS WIDTH HAVE TO BE RISING?
bbw_vol = input.bool(defval=false, title='Require Rising Bollinger Bands Width', group='Bollinger Bands Width Volatility', tooltip='For signal line and baseline options. Require that Bollinger Bands Width be rising to highlight increasing volatility.')

//BAR COLOR AND BACKGROUND COLOR FOR BASIC BOLLINGER BANDS WIDTH OPTIONS
barcolor_bbw = input.bool(defval=true, title='Color Bars', group='Bollinger Bands Width Basic Options')
bg_bbw = input.bool(defval=true, title='Color Background', group='Bollinger Bands Width Basic Options')

//BAR COLOR AND BACKGROUND COLOR SIGNAL LINE OPTIONS
barcolor_signal = input.bool(defval=false, title='Color Bars', group='Signal Line Options', tooltip='Colors bars depending on BB Width being above or below signal line.')
bg_signal = input.bool(defval=false, title='Color Background', group='Signal Line Options', tooltip='Similar to above tooltip.')
xover_signal = input.bool(false, 'Volatility Advance', group='Signal Line Options', tooltip='Colors the bar when BB Width crosses above the signal line, indiicating strong volatility.')
xunder_signal = input.bool(false, 'Volatility Decline', group='Signal Line Options', tooltip='Colors the bar when BB Width crosses below the signal line, indicating weakening volatility.')

//BAR COLOR AND BACKGROUND COLOR BASELINE OPTIONS
barcolor_bline = input.bool(defval=false, title='Color Bars', group='Baseline Options', tooltip='See above tooltips in Signal Line Options, and transpose to Baseline.')
bg_bline = input.bool(defval=false, title='Color Background', group='Baseline Options', tooltip='See above tooltip.')
xover_bline = input.bool(false, 'Volatility Advance', group='Baseline Options', tooltip='Colors the bar when BB Width crosses above the baseline, indicating strong volatility.')
xunder_bline = input.bool(false, 'Volatility Decline', group='Baseline Options', tooltip='Colors the bar when BB Width crosses below the baseline, indicating little volatility.')


/////////////////////////////////////////////////////////////////////////////////////


////SIGNAL LINE CHOICES
signal(type, src, signal_period) =>
    float result = 0
    if type == 'EMA'
        result := ta.ema(bbw, signal_period)
    if type == 'HMA'
        result := ta.hma(bbw, signal_period)
    if type == 'RMA'
        result := ta.rma(bbw, signal_period)
    if type == 'SMA'
        result := ta.sma(bbw, signal_period)
    if type == 'WMA'
        result := ta.wma(bbw, signal_period)
    if type == 'VWMA'
        result:= ta.vwma(bbw, signal_period)
    result

signal_line = signal(signal_type, bbw, signal_period)


/////////////////////////////////////////////////////////////////////////////////////


////DONCHIAN CHANNEL CALCULATION TO DETERMINE VOLATILITY PERCENT
highest_baseline = vol_period_type == 'RexDog Self-Adjusting' ? (ta.highest(bbw, 5) + ta.highest(bbw, 9) + ta.highest(bbw, 24) + ta.highest(bbw, 50) + ta.highest(bbw, 100) + ta.highest(bbw, 200)) / 6 : ta.highest(bbw, vol_period)
lowest_baseline = vol_period_type == 'RexDog Self-Adjusting' ? (ta.lowest(bbw, 5) + ta.lowest(bbw, 9) + ta.lowest(bbw, 24) + ta.lowest(bbw, 50) + ta.lowest(bbw, 100) + ta.lowest(bbw, 200)) / 6 : ta.lowest(bbw, vol_period)

baseline = (highest_baseline + lowest_baseline) / divisor


/////////////////////////////////////////////////////////////////////////////////////


//EXPANSION & CONTRACTION OF BOLLINGER BANDS (RISING/FALLING BOLLINGER BANDS WIDTH)


//BBW COLOR
bbw_color = if bbw > bbw[1]
    color.new(#ff9800, 0)
else if bbw < bbw[1]
    color.new(#2962ff, 0)

//SIGNAL LINE COLOR
signal_color = if signal_line > signal_line[1]
    color.new(#00bcd4, 0)
else if signal_line < signal_line[1]
    color.new(#e91e63, 0)


////PLOTS
plot(bbw, title='Bollinger Bands Width', color=bbw_color, style=plot.style_columns)
plot(signal_line, title='Signal Line', color=signal_color, linewidth=1, style=plot.style_line)
plot(baseline, title='Baseline', color=color.new(color.white, 50), style=plot.style_area)


/////////////////////////////////////////////////////////////////////////////////////


//BOLLINGER BANDS WIDTH & SIGNAL LINE RISING VARIABLES
rising_bbw = bbw_vol and bbw > bbw[1]
falling_bbw = bbw < bbw[1]


/////////////////////////////////////////////////////////////////////////////////////
////BACKGROUND CONDITIONS AND COLORING 

above_bline = bg_bline and bbw > baseline
below_bline = bg_bline and bbw < baseline

above_signal = bg_signal and bbw > signal_line
below_signal = bg_signal and bbw < signal_line

//BASIC
Background_Basic = if bg_bbw and bbw > bbw[1]
    color.new(#00bcd4, 50)
else if bg_bbw and falling_bbw
    color.new(#e91e63, 100)

//ABOVE BASELINE
AboveBaseline = if rising_bbw and above_bline
    color.new(#00bcd4, 50)
else if rising_bbw and below_bline
    color.new(#e91e63, 100)
else if not bbw_vol and above_bline
    color.new(#00bcd4, 50)
else if not bbw_vol and below_bline
    color.new(#e91e63, 100)
else if bg_bline and falling_bbw
    color.new(#e91e63, 100)

//ABOVE SIGNAL LINE
AboveSignalLine =if rising_bbw and above_signal
    color.new(#00bcd4, 50)
else if below_signal
    color.new(#e91e63, 100)
else if not bbw_vol and above_signal
    color.new(#00bcd4, 50)
else if not bbw_vol and below_signal
    color.new(#e91e63, 100)
else if bg_signal and falling_bbw
    color.new(#e91e63, 100)

bgcolor(Background_Basic, title='Background | Basic BB Width Rising & Falling')
bgcolor(AboveBaseline, title='Background | BB Width Above Baseline ')
bgcolor(AboveSignalLine, title='Background | BB Width Above Signal Line')


/////////////////////////////////////////////////////////////////////////////////////
////BAR COLOR CONDITIONS AND COLORING FOR CROSSING ABOVE AND BELOW BASELINE AND SIGNAL LINE

barcolor_xover_bline = xover_bline and ta.crossover(bbw, baseline)
barcolor_xunder_bline = xunder_bline and ta.crossunder(bbw, baseline)
barcolor_xover_signal = xover_signal and ta.crossover(bbw, signal_line)
barcolor_xunder_signal = xunder_signal and ta.crossunder(bbw, signal_line)

//ABOVE BASELINE
BarColorBaselineCross = if barcolor_xover_bline
    color.new(#ffeb3b, 0)
else if barcolor_xunder_bline
    color.new(#673ab7, 0)

//ABOVE SIGNAL LINE
BarColorSignalLineCross = if barcolor_xover_signal
    color.new(#ffeb3b, 0)
else if barcolor_xunder_signal
    color.new(#673ab7, 0)


barcolor(BarColorBaselineCross, title='Bar Color | BB Width Baseline Cross')
barcolor(BarColorSignalLineCross, title='Bar Color | BB Width Signal Line Cross')


/////////////////////////////////////////////////////////////////////////////////////
////BAR COLOR CONDITIONS AND COLORING FOR BB WIDTH

barcolor_above_bline = barcolor_bline and bbw > baseline
barcolor_below_bline = barcolor_bline and bbw < baseline
barcolor_above_signal = barcolor_signal and bbw > signal_line
barcolor_below_signal = barcolor_signal and bbw < signal_line

//BASIC
BarColor_Basic = if barcolor_bbw and bbw > bbw[1]
    color.new(#00bcd4, 0)
else if barcolor_bbw and bbw < bbw[1]
    color.new(#e91e63, 0)

//ABOVE BASELINE
BarColorBaseline = if rising_bbw and barcolor_above_bline
    color.new(#00bcd4, 0)
else if barcolor_below_bline
    color.new(#e91e63, 0)
else if not bbw_vol and barcolor_above_bline
    color.new(#00bcd4, 0)
else if barcolor_above_bline and falling_bbw
    color.new(color.gray, 0)

//ABOVE SIGNAL LINE
BarColorSignalLine = if rising_bbw and barcolor_above_signal
    color.new(#00bcd4, 0)
else if barcolor_below_signal
    color.new(#e91e63, 0)
else if not bbw_vol and barcolor_above_signal
    color.new(#00bcd4, 0)
else if barcolor_above_signal and falling_bbw
    color.new(color.gray, 0)



barcolor(BarColor_Basic, title='Bar Color | Basic BB Width Rising & Falling')
barcolor(BarColorBaseline, title='Bar Color | BB Width Above Baseline')
barcolor(BarColorSignalLine, title='Bar Color | BB Width Above Signal Line')


/////////////////////////////////////////////////////////////////////////////////////


hline(0, title='Zero Line', linestyle=hline.style_dotted)


////ALERT CONDITIONS
alertcondition(ta.crossover(bbw, signal_line), title='Bollinger Bands Width Signal Line Crossover', message='Bollinger Bands Width has crossed over the signal line.')
alertcondition(ta.crossover(bbw, baseline), title='Bollinger Bands Width Baseline Crossover', message='Bollinger Bands Width has crossed over the baseline.')
alertcondition(ta.cross(bbw, signal_line), title='Bollinger Bands Width Signal Line Cross', message='Bollinger Bands Width has crossed the signal line.')
alertcondition(ta.cross(bbw, baseline), title='Bollinger Bands Width Baseline Cross', message='Bollinger Bands Width has crossed the baseline.')
alertcondition(bbw > bbw[1], title='Bollinger Bands Width Advancing', message='Bollinger Bands Width is advancing (Bollinger Bands expanding).')
alertcondition(bbw < bbw[1], title='Bollinger Bands Width Baseline Declining', message='Bollinger Bands Width is declining (Bollinger Bands contracting).')