Bollinger Bands With User Selectable MA
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//@version=5
indicator('Bollinger Bands with User Selectable MA', 
     shorttitle='BBands - User Selectable MA', 
     overlay=true, 
     timeframe="", 
     timeframe_gaps=true)

//INPUT
lsmaoffset = input.int(title='Least Squares MA Only - LS Offset', defval=0, group='Special MA Settings', inline='02')
almaoffset = input.float(title='ALMA Offset', defval=0.85, step=0.01, group='Special MA Settings', inline='03')
almasigma = input.float(title='Sigma', defval=6, group='Special MA Settings', inline='03')
a1 = input.float(title='Tillson T3 Volume Factor', defval=0.7, group='Special MA Settings', inline='5', step=0.001)

f_ehma(_Source, _length) =>
    _return = ta.ema(2 * ta.ema(_Source, _length / 2) - ta.ema(_Source, _length), math.round(math.sqrt(_length)))
    _return

f_tema(_Source, _length) =>
    _out = 3 * (ta.ema(_Source, _length) - ta.ema(ta.ema(_Source, _length), _length)) + ta.ema(ta.ema(ta.ema(_Source, _length), _length), _length)
    _out

f_t3(_source, _length, _a1) =>
    _output = (-_a1 * _a1 * _a1) * (ta.ema(ta.ema(ta.ema(ta.ema(ta.ema(ta.ema(_source, _length), _length), _length), _length), _length), _length)) + (3 * _a1 * _a1 + 3 * _a1 * _a1 * _a1) * (ta.ema(ta.ema(ta.ema(ta.ema(ta.ema(_source, _length), _length), _length), _length), _length)) + (-6 * _a1 * _a1 - 3 * _a1 - 3 * _a1 * _a1 * _a1) * (ta.ema(ta.ema(ta.ema(ta.ema(_source, _length), _length), _length), _length)) + (1 + 3 * _a1 + _a1 * _a1 * _a1 + 3 * _a1 * _a1) * (ta.ema(ta.ema(ta.ema(_source, _length), _length), _length))
    _output

donchian(_length) =>
    math.avg(ta.lowest(_length), ta.highest(_length))

MA(source, length, type) =>
     type == 'SMA' ? ta.sma(source, length) : 
     type == 'Donchian' ? donchian(length) : 
     type == 'EMA' ? ta.ema(source, length) : 
     type == 'SMMA (RMA)' ? ta.rma(source, length) : 
     type == 'WMA' ? ta.wma(source, length) : 
     type == 'VWMA' ? ta.vwma(source, length) : 
     type == 'HMA' ? ta.hma(source, length) : 
     type == 'EHMA' ? f_ehma(source, length) : 
     type == 'TEMA' ? f_tema(source, length) : 
     type == 'ALMA' ? ta.alma(source, length, almaoffset, almasigma) : 
     type == 'Tillson T3' ? f_t3(source, length, a1) : 
     type == 'LSMA' ? ta.linreg(source, length, lsmaoffset) : 
     na

BB_type = input.string('SMA', 'Basis', inline='1', 
     options=['SMMA (RMA)', 
     'SMA', 
     'Donchian', 
     'Tillson T3', 
     'EMA', 
     'VWMA', 
     'WMA', 
     'EHMA', 
     'ALMA', 
     'LSMA', 
     'HMA', 
     'TEMA'], 
     group='Bollinger Band Calculation Settings')

BBSource = input.source(close, '', group='Bollinger Band Calculation Settings', inline='1')
BBPeriod = input.int(20, '', minval=1, step=1, group='Bollinger Band Calculation Settings', inline='1')

stdevMultiple = input.float(2, '# of Standard Deviations', minval=1, step=0.1, group='Bollinger Band Calculation Settings', inline='3')
realoffset = input.int(0, 'Basic Plot Offset', minval=-500, maxval=500, group='Bollinger Band Calculation Settings', inline='4')

//MORE OPTIONS
colorbasis = input.bool(defval=true, title='Modify Basis Color with trend?', group='Color Settings', inline='10')
color basiscolor = input.color(color.new(color.orange, 0), '', group='Color Settings', inline='10')
colorbands = input.bool(defval=true, title='Fill Bands Color with trend?', group='Color Settings', inline='11')
filltransp = input.int(95, 'Rainbow Fill Transparency', minval=0, maxval=100, group='Color Settings', inline='4')
color regularbands = input.color(color.rgb(33, 150, 243, 95), '', group='Color Settings', inline='11')
color upband = input.color(color.new(color.red, 0), '', group='Color Settings', inline='11')
color dnband = input.color(color.new(color.green, 0), '', group='Color Settings', inline='11')
colorcandles = input.bool(defval=true, title='Alternate Colors for Band Touch?', group='Color Settings', inline='12')
color coloroverheated = input.color(color.new(color.yellow, 0), '', group='Color Settings', inline='12')
color coloroversold = input.color(color.new(color.fuchsia, 0), '', group='Color Settings', inline='12')

//BASIS 
realbasis = MA(BBSource, BBPeriod, BB_type)

//PLOT 
var grad = array.new_color(na)
if barstate.isfirst
    array.push(grad, color.gray)
    array.push(grad, #ff00ff)
    array.push(grad, #ff00f7)
    array.push(grad, #ff00ef)
    array.push(grad, #ff00e8)
    array.push(grad, #ff00e0)
    array.push(grad, #ff00d8)
    array.push(grad, #ff00d1)
    array.push(grad, #ff00ca)
    array.push(grad, #ff00c2)
    array.push(grad, #ff00bb)
    array.push(grad, #ff00b4)
    array.push(grad, #ff00ae)
    array.push(grad, #ff00a7)
    array.push(grad, #ff00a1)
    array.push(grad, #ff009a)
    array.push(grad, #ff0094)
    array.push(grad, #ff008e)
    array.push(grad, #ff0088)
    array.push(grad, #ff0383)
    array.push(grad, #ff147d)
    array.push(grad, #ff1f78)
    array.push(grad, #ff2773)
    array.push(grad, #ff2e6e)
    array.push(grad, #ff356a)
    array.push(grad, #ff3b65)
    array.push(grad, #ff4061)
    array.push(grad, #ff455d)
    array.push(grad, #ff4959)
    array.push(grad, #ff4e55)
    array.push(grad, #ff5252)
    array.push(grad, #ff5a4e)
    array.push(grad, #ff6349)
    array.push(grad, #ff6b44)
    array.push(grad, #ff743f)
    array.push(grad, #ff7d3a)
    array.push(grad, #ff8634)
    array.push(grad, #ff8f2e)
    array.push(grad, #ff9827)
    array.push(grad, #ffa120)
    array.push(grad, #ffab17)
    array.push(grad, #ffb40b)
    array.push(grad, #ffbe00)
    array.push(grad, #ffc700)
    array.push(grad, #ffd000)
    array.push(grad, #ffda00)
    array.push(grad, #ffe300)
    array.push(grad, #ffec00)
    array.push(grad, #fff600)
    array.push(grad, #ffff00)
    array.push(grad, #ffff00)
    array.push(grad, #eefd1d)
    array.push(grad, #ddfb2d)
    array.push(grad, #ccf83a)
    array.push(grad, #bcf546)
    array.push(grad, #adf150)
    array.push(grad, #9eee59)
    array.push(grad, #8fea62)
    array.push(grad, #81e66a)
    array.push(grad, #74e172)
    array.push(grad, #66dc79)
    array.push(grad, #5ad87f)
    array.push(grad, #4dd385)
    array.push(grad, #41cd8a)
    array.push(grad, #36c88f)
    array.push(grad, #2cc393)
    array.push(grad, #24bd96)
    array.push(grad, #1fb798)
    array.push(grad, #1eb299)
    array.push(grad, #21ac9a)
    array.push(grad, #26a69a)
    array.push(grad, #26a99d)
    array.push(grad, #26aca0)
    array.push(grad, #26afa3)
    array.push(grad, #26b1a6)
    array.push(grad, #25b4aa)
    array.push(grad, #25b7ad)
    array.push(grad, #25bab0)
    array.push(grad, #24bdb3)
    array.push(grad, #24c0b6)
    array.push(grad, #24c3ba)
    array.push(grad, #23c6bd)
    array.push(grad, #23c9c0)
    array.push(grad, #22ccc4)
    array.push(grad, #21cfc7)
    array.push(grad, #20d2ca)
    array.push(grad, #20d5ce)
    array.push(grad, #1fd8d1)
    array.push(grad, #1edbd4)
    array.push(grad, #1cded8)
    array.push(grad, #1be1db)
    array.push(grad, #1ae4df)
    array.push(grad, #18e7e2)
    array.push(grad, #17eae6)
    array.push(grad, #15ede9)
    array.push(grad, #12f0ed)
    array.push(grad, #10f3f0)
    array.push(grad, #0df6f4)
    array.push(grad, #09f9f8)
    array.push(grad, #04fcfb)
    array.push(grad, #00ffff)

rsival = math.round(ta.rsi(realbasis, BBPeriod))
gradcolor = array.get(grad, rsival)
basecolor = colorbasis ? gradcolor : basiscolor

p0 = plot(realbasis, title='Bollinger Bands MA Line', color=basecolor, linewidth=1, offset=realoffset)

//Standard Deviation
stdDeviation = stdevMultiple * ta.stdev(BBSource, BBPeriod)

upperBand = if BB_type == 'Donchian'
    ta.highest(BBPeriod)
else
    realbasis + stdDeviation

lowerBand = if BB_type == 'Donchian'
    ta.lowest(BBPeriod)
else
    realbasis - stdDeviation

//bands plots
p1 = plot(upperBand, title='Upper Band', color=colorbands ? basecolor : upband, linewidth=1, offset=realoffset)
p2 = plot(lowerBand, title='Lower Band', color=colorbands ? basecolor : dnband, linewidth=1, offset=realoffset)
bollingerfill = color.new(gradcolor, filltransp)
bollingercolor = colorbands ? bollingerfill : regularbands
fill(p1, p2, color=bollingercolor, title='Bollinger Bands Fill')

//Color Candles
down = open > close
up = close > open
overheated = not down and high > upperBand
oversold = not up and low < lowerBand
iff_1 = oversold ? coloroversold : na
touchcolor = overheated ? coloroverheated : iff_1
candlecolors2 = colorcandles ? touchcolor : na
barcolor(candlecolors2, title='Band Touches')

//Alerts
alertcondition(overheated != 0, 'High Band Touch', 'High Band Touch')
alertcondition(oversold != 0, 'Low Band Touch', 'Low Band Touch')