Step-MA Filtered Stochastic [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("Step-MA Filtered Stochastic [Loxx]", 
     shorttitle='SMAFS [Loxx]', 
     overlay=false,  
     timeframe="", 
     timeframe_gaps=true)

greencolor = #2DD204
redcolor = #D2042D 

SM02 = 'Signal'
SM03 = 'Middle Crosses'
SM04 = 'Levels Crosses'

_stepma(float sense, float size, float stepMulti, phigh, plow, pprice)=>
    float trend = 0.
    float out = 0.
    float sensitivity = sense == 0 ? 0.000001 : sense
    float stepSize =     size == 0 ? 0.000001 : size
    float sizea = sensitivity * stepSize
    
    float smax = phigh + 2.0 * sizea * stepMulti
    float smin = plow - 2.0 * sizea * stepMulti
    
    trend := nz(trend[1])
    if (pprice > nz(smax[1])) 
        trend :=  1
    if (pprice < nz(smin[1])) 
        trend := -1
        
    if (trend == 1) 
        if (smin < nz(smin[1]))
            smin := nz(smin[1])
        out := smin + sizea * stepMulti 
    if (trend == -1) 
        if (smax > nz(smax[1])) 
            smax := nz(smax[1])
        out := smax - sizea * stepMulti
    out
    
per = input.int(32, "Period", minval=1, group = "Basic Settings")

periodD = input.int(3, title="%D Smoothing", minval=1, group = "Basic Settings")

Sensitivity = input.float(4, "Sensitivity", group = "Step MA Settings")
StepSize    = input.float(5, "Step Size",  group = "Step MA Settings")
StepMultiplier = input.float(.5, "Step Multiplier", step = 0.01, group = "Step MA Settings")

lvlup = input.int(80, "Upper Level", group = "Levels Settings")
lvldn = input.int(20, "Bottom Level", group = "Levels Settings")

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

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

out = ta.stoch(close, high, low, per)
sig = ta.sma(out, periodD)

out := _stepma(Sensitivity, StepSize, StepMultiplier, out, out, out)
sig := _stepma(Sensitivity, StepSize, StepMultiplier, sig, sig, sig)

mid = 50

state = 0.
if sigtype == SM02
    if (out < sig) 
        state :=-1
    if (out > sig) 
        state := 1
else if sigtype == SM03
    if (out < mid) 
        state :=-1
    if (out > mid)
        state := 1
else if sigtype == SM04
    if (out < lvldn) 
        state := -1
    if (out > lvlup)
        state := 1
        
colorout = state == 1 ? greencolor : state == -1 ? redcolor : color.gray

plot(out, "Step Stochastic", color = colorout, linewidth = 2)
plot(lvlup, "Overbought", color = bar_index % 2 ? color.gray : na)
plot(lvldn, "Oversold", color = bar_index % 2 ? color.gray : na)
plot(mid, "Mid", color = bar_index % 2 ? color.gray : na)

barcolor(colorbars ?  colorout: na)

goLong = sigtype == SM02 ? ta.crossover(out, sig) : sigtype == SM03 ? ta.crossover(out, mid) :  ta.crossover(out, lvlup)
goShort = sigtype == SM02 ? ta.crossunder(out, sig) : sigtype == SM03 ? ta.crossunder(out, mid) : ta.crossunder(out, lvldn)

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

alertcondition(goLong, title="Long", message="Step-MA Filtered Stochastic [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title="Short", message="Step-MA Filtered Stochastic [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")
