One-Sided Gaussian Support & Resistance Rate [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("One-Sided Gaussian Support & Resistance Rate [Loxx]", 
     shorttitle="OSGSRR [Loxx]", 
     overlay = false, 
     timeframe="", 
     timeframe_gaps = true)

greencolor = #2DD204
redcolor = #D2042D 

SM02 = 'Slope'
SM03 = 'Middle Crosses'

//ehlers 2-pole super smoother
_twopoless(float src, int len)=>
    a1 = 0., b1 = 0.
    coef1 = 0., coef2 = 0., coef3 = 0.
    filt = 0., trig = 0.
    a1 := math.exp(-1.414 * math.pi / len)
    b1 := 2 * a1 * math.cos(1.414 * math.pi / len)
    coef2 := b1
    coef3 := -a1 * a1
    coef1 := 1 - coef2 - coef3
    filt := coef1 * src + coef2 * nz(filt[1]) + coef3 * nz(filt[2])
    filt := bar_index < 3 ? src : filt
    filt
    
_gaussian(size, x)=>
    out = (math.exp(-x * x * 9 / ((size + 1) * (size + 1))))
    out

//calc fibonacci numbers 0, 1, 1, 2, 3, 5, 8, 13, 21 ... etc
_fiblevels(len)=>
    arr_levels = array.new_float(len, 0.)
    t1 = 0, t2 = 1
    nxt = t1 + t2
    for i = 0 to len - 1 
        array.set(arr_levels, i, nxt)
        t1 := t2
        t2 := nxt
        nxt := t1 + t2
    arr_levels
    
//calc weights given fibo numbers and how many fibos chosen
_gaussout(levels)=>
    perin = array.size(levels)
    arr_gauss = matrix.new<float>(perin, perin, 0.)
    for k = 0 to array.size(levels) - 1 
        sum = 0.
        for i = 0 to perin - 1 
            if (i >= array.get(levels, k)) 
                break
            matrix.set(arr_gauss, i, k, _gaussian(array.get(levels, k), i))
            sum += matrix.get(arr_gauss, i, k)
        for i = 0 to perin - 1
            if (i >= array.get(levels, k)) 
                break
            temp = matrix.get(arr_gauss, i, k) / sum
            matrix.set(arr_gauss, i, k, temp)
    arr_gauss   

//calc moving average applying fibo numbers
_smthMA(level, src, per)=>
    sum = 0.
    lvltemp = _fiblevels(per)
    gtemp = _gaussout(lvltemp)
    for i = 0 to matrix.rows(gtemp) - 1
        sum += matrix.get(gtemp, i, level) * nz(src)
    sum

smthper = input.int(3, "Guassian Level Depth", maxval = 100, group=  "Basic Settings")
extrasmthper = input.int(5, "Extra Smoothing Period", group=  "Basic Settings")
SRPeriod = input.int(40, "Support/Resistance Period", group=  "Basic Settings")

sigtype = input.string(SM03, "Signal type", options = [SM02, SM03], group = "Signal Settings")

colorbars = input.bool(true, "Color bars?", group = "UI Options")
showsignals = input.bool(true, "Show signals?", group = "UI Options")

lmax = smthper + 1

hsmth = _twopoless(high, extrasmthper)
lsmth = _twopoless(low, extrasmthper)
hl2smth = _twopoless(hl2, extrasmthper)

workh = _smthMA(smthper, hsmth, lmax)
workl = _smthMA(smthper, lsmth, lmax)

smin = ta.lowest(workl, SRPeriod)
smax = ta.highest(workh, SRPeriod)

Rate = 0.
if (smin != smax) 
    Rate := (_smthMA(smthper, hl2smth, lmax) - smin) / (smax - smin)

sig = Rate[1]
mid = .5
state = 0.
if sigtype == SM02
    if (Rate < sig) 
        state :=-1
    if (Rate > sig) 
        state := 1
else if sigtype == SM03
    if (Rate < mid) 
        state :=-1
    if (Rate > mid)
        state := 1

colorout = state == -1 ? redcolor : state == 1 ? greencolor : color.gray

plot(Rate, "OS Gaussian SR Rate", color = colorout, linewidth = 3)
plot(mid, "Middle", color = bar_index % 2 ? color.gray : na)

barcolor(colorbars ? colorout : na)

goLong = sigtype == SM02 ? ta.crossover(Rate, sig) :   ta.crossover(Rate, mid)  
goShort = sigtype == SM02 ? ta.crossunder(Rate, sig) : ta.crossunder(Rate, mid) 

plotshape(goLong and showsignals, title = "Long", color = greencolor, textcolor = greencolor, text = "L", style = shape.triangleup, location = location.bottom, size = size.auto)
plotshape(goShort and showsignals, title = "Short", color = redcolor, textcolor = redcolor, text = "S", style = shape.triangledown, location = location.top, size = size.auto)

alertcondition(goLong, title="Long", message="One-Sided Gaussian Support & Resistance Rate [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title="Short", message="One-Sided Gaussian Support & Resistance Rate [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")




