PA-Adaptive, Stepped-MA of Composite RSI [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("PA-Adaptive, Stepped-MA of Composite RSI [Loxx]",
     shorttitle='PAASMACRSI [Loxx]', 
     overlay = false, 
     timeframe="", 
     timeframe_gaps = true)
     
import loxx/loxxexpandedsourcetypes/4
import loxx/loxxpaaspecial/1

SM02 = 'Middle Cross'
SM03 = 'Trend'

greencolor = #2DD204
redcolor = #D2042D 
bluecolor = #042dd2

_cRSI(src, period, depth, fast)=>
    alpha = 0.
    if (not fast)
        alpha := 2.0/(1.0 + period)
    else 
        alpha := 2.0/(2.0 + (period-1.0)/2.0)
    CU = 0.
    CD = 0., rsi = src
    price = src
    for k = 0 to depth 
        rsi := nz(rsi[1]) + alpha * (src - nz(rsi[1]))
        price := rsi
        if (nz(rsi[k+1]) >= nz(rsi[k]))
            CD += nz(rsi[k+1]) - nz(rsi[k])
        else 
            CU += nz(rsi[k]) - nz(rsi[k+1])
    trsi = 0.
    if (CU + CD != 0) 
        trsi := CU / (CU + CD) 
    trsi

_stepma(_sense, _size, stepMulti, phigh, plow, pprice)=>
    sensitivity = _sense, stepSize = _size, _trend = 0.
    if (_sense == 0) 
        sensitivity := 0.0001
    if (_size == 0) 
        stepSize := 0.0001
    out = 0.
    size = sensitivity * stepSize
    _smax  = phigh + 2.0 * size * stepMulti
    _smin = plow - 2.0 * size * 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 + size * stepMulti 
    if (_trend == -1) 
        if (_smax > nz(_smax[1])) 
            _smax := nz(_smax[1])
        out := _smax - size * stepMulti 
    [out, _trend]
    
smthtype = input.string("Kaufman", "Fast Heiken-Ashi Better Smoothing", options = ["AMA", "T3", "Kaufman"], group= "Source Settings")
srcin = input.string("Close", "Fast 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)"])

fregcycles = input.float(1.5, title = "PA Cycles", group=  "Phase Accumulation Cycle Settings")
fregfilter = input.float(1.0, title = "PA Filter", group=  "Phase Accumulation Cycle Settings")

rsidepth = input.int(2, "RSI Depth", group = "Basic Settings")

sense = input.float(4, "Sensitivity", group = "Basic Settings")
stsize = input.float(5, "Step Size", group = "Basic Settings")
stepmult = input.float(0.5, "Step Multiplier", group = "Basic Settings")
quick = input.bool(true, "Rapid Composite RSI?")

signalMode = input.string(SM03, 'Signal Type', options=[SM03, SM02], group = "Signal Settings")
showsignals = input.bool(true, "Show signals?", group = "UI Options")
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 = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, close)
haopen = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, open)
hahigh = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, high)
halow = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, low)
hamedian = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, hl2)
hatypical = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, hlc3)
haweighted = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, hlcc4)
haaverage = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, ohlc4)

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

int flen = math.floor(loxxpaaspecial.paa(src, fregcycles, fregfilter))
flen := flen < 1 ? 1 : flen
rsi = math.abs(_cRSI(src, flen, rsidepth, quick) * 100)

[val, trend] = _stepma(sense, stsize, stepmult, rsi, rsi, rsi)
mid = 50.

colorout = signalMode == SM02 ? (val > mid ? greencolor : redcolor) : (trend == 1 ? greencolor : trend == -1 ? redcolor : color.gray)

plot(val, color = colorout, linewidth = 2)
plot(mid, "Middle", color =  bar_index % 2 ? color.gray : na)

barcolor(colorbars ? colorout : na)

goLong = signalMode == SM02 ? ta.crossover(val, mid) : trend == 1 and trend[1] == -1
goShort = signalMode == SM02 ? ta.crossunder(val, mid) : trend == -1 and trend[1] == 1

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="PA-Adaptive, Stepped-MA of Composite RSI [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title="Short", message="PA-Adaptive, Stepped-MA of Composite RSI [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")

//forcing UI to leave space for signal prints
hline(-10, color = color.new(color.black, 100))
hline(110, color = color.new(color.black, 100))

