Average Variation Bands Oscillator
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RicardoSantos

//@version=5
indicator('Average Variation Bands Oscillator', 'AVBo', false, timeframe='')

// Inputs:
float src = input.source(close, 'Source Series.')
int ma_length = input.int(100, 'Moving Average Length:')
int dev_length = input.int(100, 'Deviation Moving Average Length:')
bool use_cum_average = input.bool(false, 'Use Cumulative Average?')
float dev1 = input.float(1, 'Band Deviations:', inline='1')
float dev2 = input.float(2, '', inline='1')
float dev3 = input.float(3, '', inline='1')
color col_up = input.color(#f0643c, 'Colors: ', '', '2')
color col_lo = input.color(#3c64f0, '', '', '2')

//
float ma = ta.ema(src, ma_length)

float high_dev = math.max(0.0, high - ma)
float low_dev  = ma - math.min(ma, low)
float high_range = use_cum_average ? ta.cum(high_dev) / (bar_index - 1) : ta.ema(high_dev, dev_length)
float low_range  = use_cum_average ? ta.cum(low_dev ) / (bar_index - 1) : ta.ema(low_dev , dev_length)

float upper1 = ma + high_range * dev1
float upper2 = ma + high_range * dev2
float upper3 = ma + high_range * dev3
float lower1 = ma - low_range  * dev1
float lower2 = ma - low_range  * dev2
float lower3 = ma - low_range  * dev3

perc (src, upper, lower) => math.max(0.0, math.min(1.0, (src - lower) / (upper - lower))) * 100.0

float osc1 = perc(src, upper1, lower1)
float osc2 = perc(src, upper2, lower2)
float osc3 = perc(src, upper3, lower3)

//
col (p) => color.from_gradient(p, 0.0, 100.0, col_up, col_lo)

plot(series=osc3, title='', color=col(osc3))
plot(series=osc2, title='', color=col(osc2))
plot(series=osc1, title='', color=col(osc1))

hline(100)
hline(080)
hline(050)
hline(020)
hline(000)
