Bollinger bands and Keltner bands
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Rain5369

//@version=5
indicator(title='Bollinger bands and ATR bands', shorttitle='BB', overlay=true, timeframe= '', timeframe_gaps = false )

length = input.int(20, title='length', minval=1)
source = input(close, title='Source')
Vol = ta.vwma(source, length) 
basis = input.string(title='Basis', defval='sma', options=['sma', 'ema', 'wma', 'vwma', 'Rma', 'alma', 'hull ma'])


maType(source) =>
    switch basis
        'sma' => ta.sma(source, length)
        'ema' => ta.ema(source, length)
        'wma' => ta.wma(source, length)
        'vwma' => ta.vwma(source, length)
        'Rma' => ta.rma(source, length)
        'alma' => ta.alma(source,length, 0.85, 6)
        'hull ma' => ta.hma(source,length)

pivot = plot(maType(source), color=color.new(color.white, 0), title='mean line', linewidth=2)
dev = ta.stdev(source, length)
alen = input.int(14, minval=1, title='ATR', group='ATR')

// ATR lines
ATop1 = (maType(source)) + 1 * ta.atr(alen)
ABot1 = (maType(source)) - 1 * ta.atr(alen)
ATop2 = (maType(source)) + 2 * ta.atr(alen)
ABot2 = (maType(source)) - 2 * ta.atr(alen)
ATop3 = (maType(source)) + 3 * ta.atr(alen)
ABot3 = (maType(source)) - 3 * ta.atr(alen)

//Bolliner lines
Top1 = (maType(source)) + 3 * dev
Top2 = (maType(source)) + 2.6 * dev
Top3 = (maType(source)) + 2.2 * dev
Top4 = (maType(source)) + 2 * dev
Top5 = (maType(source)) + 0.1 * dev

Bot1 = (maType(source)) - 3 * dev
Bot2 = (maType(source)) - 2.6 * dev
Bot3 = (maType(source)) - 2.2 * dev
Bot4 = (maType(source)) - 2 * dev
Bot5 = (maType(source)) - 0.1 * dev


f_weighted_sd_from_arrays(_a_src, _a_weight, _n) =>  //{
    float _mean = na
    float _variance = na
    float _dev = na
    float _mse = na
    float _rmse = na
    float _sqerror_sum = na
    float _sum_weight = na
    float[] _a_xw = array.new_float(_n)
    int _nonzero_n = 0
    if array.size(_a_src) >= _n
        _sum_weight := 0
        _sqerror_sum := 0
        for _i = 0 to _n - 1 by 1
            array.set(_a_xw, _i, array.get(_a_src, _i) * array.get(_a_weight, _i))
            _sum_weight := _sum_weight + array.get(_a_weight, _i)
            _nonzero_n := array.get(_a_weight, _i) != 0 ? _nonzero_n + 1 : _nonzero_n
            _nonzero_n
        _mean := array.sum(_a_xw) / _sum_weight
        for _j = 0 to _n - 1 by 1
            _sqerror_sum := _sqerror_sum + math.pow(_mean - array.get(_a_src, _j), 2) * array.get(_a_weight, _j)
            _sqerror_sum
        _variance := _sqerror_sum / ((_nonzero_n - 1) * _sum_weight / _nonzero_n)
        _dev := math.sqrt(_variance)
        _mse := _sqerror_sum / _sum_weight
        _rmse := math.sqrt(_mse)
        _rmse
    [_mean, _variance, _dev, _mse, _rmse]
//}

// -----------------------------------------------------------------------------
// From arrays : 
// -----------------------------------------------------------------------------
var float[] a_src = array.new_float()
var float[] a_weight = array.new_float()

if barstate.isfirst
    for i = 1 to length by 1
        array.unshift(a_weight, i)

array.unshift(a_src, close)

if array.size(a_src) > length
    array.pop(a_src)

[a_m, a_v, a_d, a_mse, a_rmse] = f_weighted_sd_from_arrays(a_src, a_weight, length)

// ATR lines

//ATR color options
Theme = input.string(title='Theme', options=['Default', 'All White', 'All Black'], defval='All White', group='ATR')
colour1 = color.new(#9700FF, 35)
colour2 = color.new(#00FF2A, 35)
colour3 = color.new(#F0FF00, 35)
colour4 = color.new(#FFFFFF, 35)
colour5 = color.new(#000000, 35)

c1 = Theme == 'Default' ? colour1 : Theme == 'All White' ? colour4 : Theme == 'All Black' ? colour5 : na
c2 = Theme == 'Default' ? colour2 : Theme == 'All White' ? colour4 : Theme == 'All Black' ? colour5 : na
c3 = Theme == 'Default' ? colour3 : Theme == 'All White' ? colour4 : Theme == 'All Black' ? colour5 : na


// ATR plots
plot(ATop1, color=c1, title='Middle higher ATR', display=display.none)
plot(ABot1, color=c1, title='Middle lower ATR', display=display.none)
plot(ATop2, color=c2, title='Innear higher ATR', display=display.none)
plot(ABot2, color=c2, title='Innear lower ATR', display=display.none)
plot(ATop3, color=c3, title='Top ATR', display=display.none)
plot(ABot3, color=c3, title='Bottom ATR', display=display.none)

// bollinger plots
l1 = plot(Top1, color=color.new(color.blue, 0), editable=false, display=display.none, title='+ 3 dev')
l2 = plot(Top2, color=color.new(color.blue, 0), editable=false, display=display.none, title='+ 2.8 dev')
l3 = plot(Top3, color=color.new(color.blue, 0), editable=false, display=display.none, title='+ 2.2 dev')
l4 = plot(Top4, color=color.new(color.blue, 0), editable=false, display=display.none, title='+ 2 dev')  //2dev
l5 = plot(Top5, color=color.new(color.blue, 0), editable=false, display=display.none, title='+ 0.2 dev')

l6 = plot(Bot5, color=color.new(color.blue, 0), editable=false, display=display.none, title='- 0.2 dev')
l7 = plot(Bot4, color=color.new(color.blue, 0), editable=false, display=display.none, title='- 2 dev')  //2dev
l8 = plot(Bot3, color=color.new(color.blue, 0), editable=false, display=display.none, title='- 2.2 dev')
l9 = plot(Bot2, color=color.new(color.blue, 0), editable=false, display=display.none, title='- 2.4 dev')
l10 = plot(Bot1, color=color.new(color.blue, 0), editable=false, display=display.none, title='- 3 dev')


aupper5 = plot(Vol + a_d * 2, color=color.new(color.orange, 0), display=display.none, editable=false, title='exp + 2 dev')
alower5 = plot(Vol - a_d * 2, color=color.new(color.orange, 0), display=display.none, editable=false, title='exp - 2 dev')


// Bollinger fill plots 

fill(l1, l2, color=color.new(#FFFFFF20, 85), editable=false)
fill(l2, l3, color=color.new(#FFFFFF20, 85), editable=false)
fill(l3, l4, color=color.new(#FFFFFF20, 85), editable=false)


fill(l7, l8, color=color.new(#FFFFFF20, 85), editable=false)
fill(l8, l9, color=color.new(#FFFFFF20, 85), editable=false)
fill(l9, l10, color=color.new(#FFFFFF20, 85), editable=false)


fill(aupper5, l1, color=color.new(#CE000D25, 80), title='weighted cloud - Resistance')
fill(alower5, l10, color=color.new(#8BBBB225, 80), title='weighted cloud - Support')
