PA-Adaptive MACD w/ Variety Levels [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 MACD w/ Variety Levels [Loxx]",
     shorttitle='PAMACDDZ [Loxx]', 
     overlay = false, 
     timeframe="", 
     timeframe_gaps = true)
     
import loxx/loxxexpandedsourcetypes/3
import loxx/loxxmas/1
import loxx/loxxpaaspecial/1

SM02 = 'Zero-Line Cross'
SM03 = 'Signal Crossover'
SM04 = 'Levels Crossover'

RMA(x, t) =>
    EMA1 = x
    EMA1 := na(EMA1[1]) ? x : (x - nz(EMA1[1])) * (1/t) + nz(EMA1[1])
    EMA1
    
EMA(x, t) =>
    EMA1 = x
    EMA1 := na(EMA1[1]) ? x : (x - nz(EMA1[1])) * (2 / (t + 1)) + nz(EMA1[1])
    EMA1
 
variant(type, src, len) =>
    sig = 0.0
    if type == "SMA"
        sig := ta.sma(src, len) 
    else if type == "EMA"
        sig := EMA(src, len) 
    else if type == "WMA"
        sig := ta.wma(src, len)   
    else if type == "RMA"
        sig := RMA(src, len)  
    sig
    
greencolor = #2DD204
redcolor = #D2042D
lightgreencolor = #96E881 
lightredcolor =  #DF4F6C

smthtype = input.string("Kaufman", "Heikin-Ashi Better Caculation Type", options = ["AMA", "T3", "Kaufman"], group = "Basic Settings")
srcin = input.string("Close", "Source", group= "Basic 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)"])

matype = input.string("EMA", "Signal Type", options = ["EMA", "WMA", "RMA", "SMA"], group = "Basic Settings")

sigtype = input.string("EMA", "Signal Type", options = ["EMA", "WMA", "RMA", "SMA"], group = "Signal Settings")
signalMode = input.string(SM03, 'Signal Type', options=[SM02, SM03, SM04], group = "Signal Settings")
sigper = input.int(9, "Signal Period", group = "Signal Settings")

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

sregcycles = input.float(3.0, title = "Slow PA Cycles", group=  "Phase Accumulation Cycle Settings")
sregfilter = input.float(1.0, title = "Slow PA Filter", group=  "Phase Accumulation Cycle Settings")

sigregcycles = input.float(1., title = "Signal PA Cycles", group=  "Phase Accumulation Cycle Settings")
sigregfilter = input.float(1.0, title = "Signal PA Filter", group=  "Phase Accumulation Cycle Settings")

levelstype = input.string("Floating", "Levels type", options = ["Floating", "Quantile"], group = "Levels Settings")
FlPeriod = input.int(35, "Levels Period", group = "Levels Settings") 
FlUp  = input.float(90 , "Up Level", group = "Levels Settings")
FlDn = input.float(10 , "Down Level", group = "Levels Settings")


colorbars = input.bool(false, "Color bars?", group = "UI Options")
showsignals = input.bool(false, "Show signals?", 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(close, fregcycles, fregfilter))
flen := flen < 1 ? 1 : flen

int slen = math.floor(loxxpaaspecial.paa(close, sregcycles, sregfilter))
slen := slen < 1 ? 1 : slen

int siglen = math.floor(loxxpaaspecial.paa(close, sigregcycles, sigregfilter))
siglen := siglen < 1 ? 1 : siglen

fma = variant(matype, src, flen)
sloma = variant(matype, src, slen)
macd = fma - sloma
signal = variant(sigtype, macd, siglen)

flhi = 0., mid = 0., fllo = 0., 
if levelstype == "Floating"
    min = ta.lowest(macd, FlPeriod)
    max = ta.highest(macd, FlPeriod)
    rng = max-min
    flhi := min + FlUp * rng / 100.0
    mid := min + 0.5 * rng
    fllo := min + FlDn * rng / 100.0
else
    flhi := ta.percentile_linear_interpolation(macd, FlPeriod, FlUp) 
    mid := ta.percentile_linear_interpolation(macd, FlPeriod, (FlUp+FlDn)/2.0)
    fllo := ta.percentile_linear_interpolation(macd, FlPeriod, FlDn)

colorout = 
     signalMode == SM03 ? (macd > signal ? greencolor : redcolor) : 
     signalMode == SM02 ? (macd > 0 ? greencolor : redcolor) : 
     (macd > flhi ? greencolor : macd < fllo ? redcolor : color.gray)

plot(flhi, color = bar_index % 2 ? greencolor : na)
plot(mid, color = bar_index % 2 ? color.gray : na)
plot(fllo, color = bar_index % 2 ? redcolor : na)

plot(macd, color = colorout, linewidth = 2)
plot(signal, color = color.white, linewidth = 1)

plot(0, color = bar_index % 2 ? color.gray : na)

barcolor(colorbars ? colorout : na)

goLong = signalMode == SM03 ? ta.crossover(macd, signal) : signalMode == SM02 ? ta.crossover(macd, 0) : ta.crossover(macd, flhi)
goShort = signalMode == SM03 ? ta.crossunder(macd, signal) : signalMode == SM02 ? ta.crossunder(macd, 0) : ta.crossunder(macd, fllo)

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 MACD w/ Variety Levels [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title="Short", message="PA-Adaptive MACD w/ Variety Levels [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")


