Weighted Deviation Bands [Loxx]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © loxx

//@version=5
indicator("Weighted Deviation Bands [Loxx]",  
     overlay = true, 
     timeframe="", 
     timeframe_gaps = true)

greencolor = #2DD204
redcolor = #D2042D 
bluecolor = #042dd2
import loxx/loxxexpandedsourcetypes/4

devnWeighted(float value, simple int perin)=>
    float valueSum = value
    float valueWeightSum = perin * value
    var float weightSum = perin
    int period = perin
    if (bar_index >= perin) 
        valueSum := nz(valueSum[1]) + value - nz(value[perin])
        valueWeightSum := nz(valueWeightSum[1]) - nz(valueSum[1]) + value * perin
    else 
        period := bar_index + 1
        weightSum := period
        valueWeightSum := period * value
        valueSum := value
       
        for int k = 1 to period - 1
            float weight = period - k
            weightSum += weight
            valueWeightSum += nz(value[k]) * weight
            valueSum += nz(value[k])

    float mean = valueWeightSum / weightSum

    float sums = 0.
    int weight = period
    for k = 0 to period - 1
        sums += weight * (nz(value[k]) - mean) * (nz(value[k]) - mean)
    
    float deviation = math.sqrt(sums / weightSum)

    [mean, deviation]

smthtype = input.string("Kaufman", "Heikin-Ashi Better Caculation Type", options = ["AMA", "T3", "Kaufman"], group = "Source Settings")
srcin = input.string("Close", "Source", group= "Source Settings", 
     options = 
     ["Close", "Open", "High", "Low", "Median", "Typical", "Weighted", "Average", "Average Median Body", "Trend Biased", "Trend Biased (Extreme)", 
     "HA Close", "HA Open", "HA High", "HA Low", "HA Median", "HA Typical", "HA Weighted", "HA Average", "HA Average Median Body", "HA Trend Biased", "HA Trend Biased (Extreme)",
     "HAB Close", "HAB Open", "HAB High", "HAB Low", "HAB Median", "HAB Typical", "HAB Weighted", "HAB Average", "HAB Average Median Body", "HAB Trend Biased", "HAB Trend Biased (Extreme)"])

inpPeriod     = input.int(30, "Period", group = "Basic Settings", minval = 1)
inpMultiplier = input.int(1, "Multiplier", group = "Basic Settings", minval = 1)

colorbars = input.bool(true, "Color bars", group = "UI Options")

kfl=input.float(0.666, title="* Kaufman's Adaptive MA (KAMA) Only - Fast End", group = "Moving Average Inputs")
ksl=input.float(0.0645, title="* Kaufman's Adaptive MA (KAMA) Only - Slow End", group = "Moving Average Inputs")
amafl = input.int(2, title="* Adaptive Moving Average (AMA) Only - Fast", group = "Moving Average Inputs")
amasl = input.int(30, title="* Adaptive Moving Average (AMA) Only - Slow", group = "Moving Average Inputs")

haclose  =  ohlc4
haopen   = float(na)
haopen  := na(haopen[1]) ? (open + close) / 2 : (nz(haopen[1]) + nz(haclose[1])) / 2
hahigh   =math.max(high, math.max(haopen, haclose))
halow    = math.min(low,  math.min(haopen, haclose))
hamedian = (hahigh + halow) / 2
hatypical = (hahigh + halow + haclose) / 3
haweighted =  (hahigh + halow + haclose + haclose)/4 
haaverage =  (haopen + hahigh + halow + haclose)/4

src = switch srcin
	"Close" => loxxexpandedsourcetypes.rclose()
	"Open" => loxxexpandedsourcetypes.ropen()
	"High" => loxxexpandedsourcetypes.rhigh()
	"Low" => loxxexpandedsourcetypes.rlow()
	"Median" => loxxexpandedsourcetypes.rmedian()
	"Typical" => loxxexpandedsourcetypes.rtypical()
	"Weighted" => loxxexpandedsourcetypes.rweighted()
	"Average" => loxxexpandedsourcetypes.raverage()
    "Average Median Body" => loxxexpandedsourcetypes.ravemedbody()
	"Trend Biased" => loxxexpandedsourcetypes.rtrendb()
	"Trend Biased (Extreme)" => loxxexpandedsourcetypes.rtrendbext()
	"HA Close" => loxxexpandedsourcetypes.haclose(haclose)
	"HA Open" => loxxexpandedsourcetypes.haopen(haopen)
	"HA High" => loxxexpandedsourcetypes.hahigh(hahigh)
	"HA Low" => loxxexpandedsourcetypes.halow(halow)
	"HA Median" => loxxexpandedsourcetypes.hamedian(hamedian)
	"HA Typical" => loxxexpandedsourcetypes.hatypical(hatypical)
	"HA Weighted" => loxxexpandedsourcetypes.haweighted(haweighted)
	"HA Average" => loxxexpandedsourcetypes.haaverage(haaverage)
    "HA Average Median Body" => loxxexpandedsourcetypes.haavemedbody(haclose, haopen)
	"HA Trend Biased" => loxxexpandedsourcetypes.hatrendb(haclose, haopen, hahigh, halow)
	"HA Trend Biased (Extreme)" => loxxexpandedsourcetypes.hatrendbext(haclose, haopen, hahigh, halow)
	"HAB Close" => loxxexpandedsourcetypes.habclose(smthtype, amafl, amasl, kfl, ksl)
	"HAB Open" => loxxexpandedsourcetypes.habopen(smthtype, amafl, amasl, kfl, ksl)
	"HAB High" => loxxexpandedsourcetypes.habhigh(smthtype, amafl, amasl, kfl, ksl)
	"HAB Low" => loxxexpandedsourcetypes.hablow(smthtype, amafl, amasl, kfl, ksl)
	"HAB Median" => loxxexpandedsourcetypes.habmedian(smthtype, amafl, amasl, kfl, ksl)
	"HAB Typical" => loxxexpandedsourcetypes.habtypical(smthtype, amafl, amasl, kfl, ksl)
	"HAB Weighted" => loxxexpandedsourcetypes.habweighted(smthtype, amafl, amasl, kfl, ksl)
	"HAB Average" => loxxexpandedsourcetypes.habaverage(smthtype, amafl, amasl, kfl, ksl)
    "HAB Average Median Body" => loxxexpandedsourcetypes.habavemedbody(smthtype, amafl, amasl, kfl, ksl)
	"HAB Trend Biased" => loxxexpandedsourcetypes.habtrendb(smthtype, amafl, amasl, kfl, ksl)
	"HAB Trend Biased (Extreme)" => loxxexpandedsourcetypes.habtrendbext(smthtype, amafl, amasl, kfl, ksl)
	=> haclose


[mean, deviation] = devnWeighted(src, inpPeriod)

bandup = mean + deviation * inpMultiplier
banddn = mean - deviation * inpMultiplier

plot(bandup, "Upper", color = greencolor, linewidth = 2)
plot(banddn, "Lower", color = redcolor, linewidth = 2)
plot(mean, "Mean", color = color.gray, linewidth = 2)

sig = mean[1]
colorout = mean > sig ? greencolor : redcolor

barcolor(colorbars ? colorout : na )