AIR Supertrend (Average Interpercentile Range)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

//  ╭━━╮╱╱╱╱╱╱╭╮╱╱╱╭━┳╮
//  ┃╭╮┣━┳━╮╭┳┫╰┳━╮┃━┫╰╮
//  ┃╭╮┃┻┫╋╰┫╭┫╋┃╋╰╋━┃┃┃
//  ╰━━┻━┻━━┻╯╰━┻━━┻━┻┻╯ @ Woody_Bearbash

//@version=5

indicator('Average Interpercentile Range AIR Supertrend','AIR Supertrend', overlay=true, format=format.price)

// Moving Averages Types
var string SMA      = 'Simple Moving Average'
var string EMA      = 'Exponential Moving Average'
var string WMA      = 'Weighted Moving Average'
var string VWMA     = 'Volume Weighted Moving average'
var string ALMA     = 'Arnaud Legoux Moving Average'
var string JURIK    = 'Jurik Moving Average'
var string T3       = 'Tillson T3 Moving Average'
var string RSIMA    = 'RSI Moving Average'
var string MEDIAN   = 'Median'
var string SS    	= 'Super Smoother Moving Average'
var string HANN   	= 'Ehlers Hann Moving Average'

var M1 = 'Urban'
var M2 = 'Night'
var M3 = 'Earth'
var M4 = 'Classic'
var M5 = 'Wood'
var M6 = 'Pop'

src                 = input.source(hl2, title = 'Source', inline = '1')
period              = input.int(title = 'Length', defval = 28, inline = '1')
multiplier          = input.float(title = 'Multiplier', step = 0.1, defval = 3.3, inline = '1')

var string GRP_RF   = '══════ Range mix ══════'
atrActive           = input.bool(true, 'ATR,', inline='42', group=GRP_RF)
atrMult             = input.float(0.5, 'Mult', step=0.1, inline='42', group=GRP_RF)
atr_move            = input.string(T3, 'MA', options=[SMA, EMA, WMA, VWMA, ALMA, JURIK, T3, RSIMA, MEDIAN, SS, HANN], group=GRP_RF, inline='42') 

airActive           = input.bool(true, 'AIR,', inline='44', group=GRP_RF)
airMult             = input.float(0.7, 'Mult', step=0.1, inline='44', group=GRP_RF)
air_move            = input.string(T3, 'MA', options=[SMA, EMA, WMA, VWMA, ALMA, JURIK, T3, RSIMA, MEDIAN, SS, HANN], group=GRP_RF, inline='44') 
spacer              = input.int(16, '%', inline='44', group=GRP_RF)

var string GRP_MA   = 'Global MA Settings'
inputAlmaOffset_T   = input.float(defval = 0.86, title = "Alma Offset", step = 0.01, inline = '1a', group = GRP_MA)
inputAlmaSigma_T    = input.int(defval = 3, title = "... Sigma", inline = '1a', group = GRP_MA)

phase_T             = input.int(defval = 2, title = "Jurik Phase", step = 1, inline = '1j', group = GRP_MA)
power_T             = input.float(defval = 0.9, title = "... Power", step = 0.1, inline = '1j', group = GRP_MA)

fac_t3_T            = input.float(0.3, step = 0.1, title = 'Tillson T3 Volume Factor', inline = '1t', group = GRP_MA)

var string GRP_UI   = '══════ UI ══════'

the_m           = input.string(M4, "theme", options = [M1, M2, M3, M4, M5, M6], inline ='ez', group=GRP_UI)

i_bullColor_t   = input.color(#e5cc42, 'Up', inline='COLOR'  , group=GRP_UI)
i_bearColor_t   = input.color(#5ea4ff, 'Down', inline='COLOR', group=GRP_UI)

i_bullColor_a   = input.color(#ffcc80, "Up", inline='COLORa'  , group=GRP_UI)
i_bearColor_a   = input.color(#ba68c8, "Down", inline='COLORa', group=GRP_UI)

i_bullColor_m   = input.color(#81c784, 'Up', inline='COLORb'  , group=GRP_UI)
i_bearColor_m   = input.color(#5ea4ff, 'Down', inline='COLORb', group=GRP_UI)

i_bullColor_c   = input.color(#48e71d, "Up", inline='COLORc'  , group=GRP_UI)
i_bearColor_c   = input.color(#ff0303, "Down", inline='COLORc', group=GRP_UI)

i_bullColor_s   = input.color(#81c784, 'Up', inline='COLORs'  , group=GRP_UI)
i_bearColor_s   = input.color(#ffa726, 'Down', inline='COLORs', group=GRP_UI)

i_bullColor_p   = input.color(#a9c346, "Up", inline='COLORcp'  , group=GRP_UI)
i_bearColor_p   = input.color(#aa9eed, "Down", inline='COLORcp', group=GRP_UI) 

up_ = the_m == M1 ? i_bullColor_t : the_m == M2 ? i_bullColor_a : the_m == M3 ? i_bullColor_m : the_m == M4 ? i_bullColor_c : the_m == M5 ? i_bullColor_s : the_m == M6 ? i_bullColor_p : na
dn_ = the_m == M1 ? i_bearColor_t : the_m == M2 ? i_bearColor_a : the_m == M3 ? i_bearColor_m : the_m == M4 ? i_bearColor_c : the_m == M5 ? i_bearColor_s : the_m == M6 ? i_bearColor_p : na

bkgrnd              = input.bool(title = 'Fill, fade', defval = true, inline='f', group = GRP_UI)
fader               = input.int(85, '', inline = 'f', group = GRP_UI)

bar_it              = input.bool(true, 'Color candles, fade', inline = 'f1', group = GRP_UI)
fader_c             = input.int(39, '', inline = 'f1', group = GRP_UI)

// ===========================================================================================================
//          Functions
// ===========================================================================================================

// @function Jurik Moving Average - TradingView: Moving Averages
Jurik(src, simple int len, jurik_phase, jurik_power) =>
    phaseRatio_l = jurik_phase < -100 ? 0.5 : jurik_phase > 100 ? 2.5 : jurik_phase / 100 + 1.5
    beta_l = 0.45 * (len - 1) / (0.45 * (len - 1) + 2)
    alpha_l = math.pow(beta_l, jurik_power)
    jma_l = 0.0
    e0_l = 0.0
    e0_l := (1 - alpha_l) * src + alpha_l * nz(e0_l[1])
    e1_l = 0.0
    e1_l := (src - e0_l) * (1 - beta_l) + beta_l * nz(e1_l[1])
    e2_l = 0.0
    e2_l := (e0_l + phaseRatio_l * e1_l - nz(jma_l[1])) * math.pow(1 - alpha_l, 2) + math.pow(alpha_l, 2) * nz(e2_l[1])
    jma_l := e2_l + nz(jma_l[1])

// @function T3 MA from Tilson3Average © KioseffTrading
t(src, x, a1_t3) =>
    y1 = ta.ema(src,x)
    y2 = ta.ema(y1, x)
    y3 = ta.ema(y2, x)
    y4 = ta.ema(y3, x)
    y5 = ta.ema(y4, x)
    y6 = ta.ema(y5, x)
    v = -a1_t3 * math.pow(a1_t3,2)
    v2 = 3 * math.pow(a1_t3,2) + 3 * math.pow(a1_t3,3)
    v3 = -6 * math.pow(a1_t3, 2) - 3 * a1_t3 - 3 * math.pow(a1_t3, 3)
    v4 = 1 + 3 * a1_t3 + a1_t3 * math.pow(a1_t3, 2) + 3 * math.pow(a1_t3, 2)
    v1 = v * y6 + v2 * y5 + v3 * y4 + v4 * y3
    v1

// Super Smoother Function 
ss(Series, Period) =>  // Super Smoother Function
    var PI = 2.0 * math.asin(1.0)
    var SQRT2 = math.sqrt(2.0)
    lambda = PI * SQRT2 / Period
    a1 = math.exp(-lambda)
    coeff2 = 2.0 * a1 * math.cos(lambda)
    coeff3 = -math.pow(a1, 2.0)
    coeff1 = 1.0 - coeff2 - coeff3
    filt1 = 0.0
    filt1 := coeff1 * (Series + nz(Series[1])) * 0.5 + coeff2 * nz(filt1[1]) + coeff3 * nz(filt1[2])
    filt1

// Hann Window Smoothing – Credits to @cheatcountry
doHannWindow(float _series, float _hannWindowLength) =>
    sum = 0.0, coef = 0.0
    for i = 1 to _hannWindowLength
        cosine = 1 - math.cos(2 * math.pi * i / (_hannWindowLength + 1))
        sum := sum + (cosine * nz(_series[i - 1]))
        coef := coef + cosine
    h = coef != 0 ? sum / coef : 0

// Choose MA type
MA_Calc(_data, _len, MAOption) =>
    value = 
		  MAOption == SMA ? ta.sma(_data, _len) : 
		  MAOption == EMA ? ta.ema(_data, _len) :
		  MAOption == WMA ? ta.wma(_data, _len) : 
		  MAOption == VWMA ? ta.vwma(_data, _len) : 
		  MAOption == ALMA ? ta.alma(_data, _len, inputAlmaOffset_T, inputAlmaSigma_T) :
		  MAOption == JURIK ? Jurik(_data, _len, phase_T, power_T) : 
		  MAOption == T3 ? t(_data, _len, fac_t3_T) :
		  MAOption == RSIMA ? ta.rma(_data, _len) :
		  MAOption == MEDIAN ? ta.median(_data, _len) :
		  MAOption == SS ? ss(_data, _len) :
		  MAOption == HANN ? doHannWindow(_data, _len) :
      na

ipr_array(len, dnny, uppy) =>
    float[]   hiArray   =   array.new_float (0)
    float[]   loArray   =   array.new_float (0)
    float[]   cmArray   =   array.new_float (0)

    for i = 0 to len - 1
        array.push  (hiArray, high[i])
        array.push  (loArray, low[i])
        array.push  (cmArray, hlcc4[i])

    hlArray     =   array.concat (hiArray, loArray)
    hlcmArray   =   array.concat (hlArray, cmArray)
    
    q1          =   array.percentile_linear_interpolation (hlcmArray, dnny)
    q3          =   array.percentile_linear_interpolation (hlcmArray, uppy)

    iqr = (q3 - q1) / 2

// =================================================================================================
//                                  Calculations
// =================================================================================================

atrFactor   = atrActive ? atrMult * MA_Calc(ta.tr(true), period, atr_move)                             : 0
airFactor   = airActive ? airMult * MA_Calc(ipr_array(period, spacer, 100 - spacer), period, air_move) : 0

blender = nz(atrFactor) + nz(airFactor)

ipr_supertrend(source, len, multi) =>
    up = source - multi * blender
    up1 = nz(up[1], up)
    up := close[1] > up1 ? math.max(up, up1) : up
    dn = source + multi * blender
    dn1 = nz(dn[1], dn)
    dn := close[1] < dn1 ? math.min(dn, dn1) : dn
    trend = 1
    trend := nz(trend[1], trend)
    trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend
    [up, dn, trend]

[upper, lower, supertrend] = ipr_supertrend(src, period, multiplier) 

// =================================================================================================
//                                  Plots
// =================================================================================================

upPlot          = plot(supertrend == 1 ? upper : na, title='Uptrend', style=plot.style_linebr, linewidth=2, color=color.new(up_, 0))
buySignal       = supertrend == 1 and supertrend[1] == -1
dnPlot          = plot(supertrend == 1 ? na : lower, title='Downtrend', style=plot.style_linebr, linewidth=2, color=color.new(dn_, 0))
sellSignal      = supertrend == -1 and supertrend[1] == 1

plotshape(buySignal ? upper : na, title='Uptrend Begins', location=location.absolute, style=shape.circle, size=size.tiny, color=color.new(up_, 0))
plotshape(sellSignal ? lower : na, title='Downtrend Begins', location=location.absolute, style=shape.circle, size=size.tiny, color=color.new(dn_, 0))

midPlot         = plot(ohlc4, title = '', style = plot.style_circles, display = display.none)
fill(midPlot, upPlot, title = 'Uptrend Fill', color = bkgrnd ? color.new(up_, fader) : na)
fill(midPlot, dnPlot, title = 'Downtrend Fill', color = bkgrnd ? color.new(dn_, fader) : na)

color_b         = supertrend == 1 ? up_ : dn_
barcolor(bar_it ? color.new(color_b, fader_c) : na)

// =================================================================================================
//                                  Alerts
// =================================================================================================

alertcondition(buySignal, title='.Supertrend Buy 🟢', message='Supertrend Buy 🟢')
alertcondition(sellSignal, title='.Supertrend Sell 🔴', message='Supertrend Sell 🔴')
changeCond      = supertrend != supertrend[1]
alertcondition(changeCond, title='Supertrend Direction Change 🟢/🔴', message='Supertrend has changed direction 🟢/🔴')

// (  __)(  ( \(    \
//  ) _) /    / ) D (
// (____)\_)__)(____/

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

