Corrected QWMA (Quadratic Weighted Moving Average) [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('Corrected QWMA (Quadratic Weighted Moving Average) [Loxx]', 
     shorttitle = "CQWMA [Loxx]", 
     overlay = true, 
     timeframe="", 
     timeframe_gaps = true)

greencolor = #2DD204
redcolor = #D2042D 

_iQwma(src, period, speed)=>
    workQwma = src
    sumw = math.pow(period, speed)
    sum = sumw * src
    for k = 0 to period - 1  
        weight = math.pow(period - k, speed)
        sumw += weight
        sum += weight * workQwma[k]
    out = sum / sumw
    out

price = input.source(close, "Source", group = "Basic Settings")
MaPeriod = input.int(25, "MA Period", group = "Basic Settings")
MaSpeed = input.int(2, "MA Speed", group = "Basic Settings")
CorrectionPeriod = input.int(0, "Correction Period", group = "Basic Settings")

FlPeriod = input.int(25, "Floating Levels Period", group = "Floating Levels Settings")
FlUp = input.int(90, "Floating Levels % Up", group = "Floating Levels Settings")
FlDown = input.int(10, "Floating Levels % Down", group = "Floating Levels Settings")

colorOn = input.string("Middle", "Coloring Type", options = ["Middle", "Level", "QWMA"], group = "UI Options")
colorbars = input.bool(false, "Color bars?", group = "UI Options")
showfloat = input.bool(true, "Show Floating Levels?", group = "UI Options")
showfill = input.bool(true, "Fil Floating Levels?", group = "UI Options")
showSigs = input.bool(false, "Show signals?", group= "UI Options")

qwma = 0.

deviationsPeriod = (CorrectionPeriod > 0) ? CorrectionPeriod : (CorrectionPeriod < 0) ? 0 : MaPeriod

work = _iQwma(price, MaPeriod, MaSpeed)
v1 = math.pow(ta.stdev(price, deviationsPeriod), 2)

v2 =  math.pow(nz(nz(qwma[1])) - work, 2) 
c = (v2 < v1 or v2 == 0) ? 0 : 1 - v1 / v2
qwma := nz(qwma[1]) + c * (work - nz(qwma[1]))

min = ta.lowest(qwma, FlPeriod)
max = ta.highest(qwma, FlPeriod)
rng = max - min

fup = min + FlUp * rng / 100.0
fdn = min + FlDown * rng / 100.0
mid = (fup + fdn) * 0.5

val = qwma



qwmac = 0.
qwmac := switch colorOn
    "Middle" => (qwma > fup) ? 1 : (qwma < fdn) ? 2 : (qwma == nz(qwma[1])) ? nz(qwmac[1]) : 0 
    "Level" => (qwma > mid) ? 1 : (qwma < mid) ? 2 : (qwma == nz(qwma[1])) ? nz(qwmac[1]) : 0 
    "QWMA" => (qwma < work) ? 1 : (qwma > work) ? 2 :  (qwma == nz(qwma[1])) ? nz(qwmac[1]) : 0 
    => (qwma > nz(qwma[1])) ? 1 : (qwma < nz(qwma[1])) ? 2 : (qwma == nz(qwma[1])) ? nz(qwmac[1]) : 0 


colorout = qwmac == 1 ? greencolor : qwmac == 2 ? redcolor : color.gray
top = plot(showfloat ? fup : na, "Top float", color = color.new(greencolor, 50), linewidth = 1)
bot = plot(showfloat ? fdn : na, "bottom float", color = color.new(redcolor, 50), linewidth = 1)
midpl = plot(showfloat ? mid : na, "Mid Float", color = color.new(color.white, 10), linewidth = 1)

goLong = qwmac == 1 and qwmac[1] !=1
goShort = qwmac == 2 and qwmac[1] !=2

fill(top, midpl, title = "Top fill color", color = showfill ? color.new(greencolor, 95) : na)
fill(bot, midpl,title = "Bottom fill color",  color = showfill ?  color.new(redcolor, 95) : na)

plot(val,"QWMA", color = colorout, linewidth = 3)

barcolor(colorbars ? colorout: na)

plotshape(showSigs and goLong, title = "Long", color = color.yellow, textcolor = color.yellow, text = "L", style = shape.triangleup, location = location.belowbar, size = size.small)
plotshape(showSigs and goShort, title = "Short", color = color.fuchsia, textcolor = color.fuchsia, text = "S", style = shape.triangledown, location = location.abovebar, size = size.small)

alertcondition(goLong, title="Long", message='Corrected QWMA (Quadratic Weighted Moving Average) [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}')
alertcondition(goShort, title="Short", message='Corrected QWMA (Quadratic Weighted Moving Average)  [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}')






