Nyquist Moving Average (NMA) MACD [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("Nyquist Moving Average (NMA) MACD [Loxx]",
     shorttitle= "NMAMACD [Loxx]", 
     overlay = false, 
     timeframe="", 
     timeframe_gaps = true)

import loxx/loxxexpandedsourcetypes/3

greencolor = #2DD204
redcolor = #D2042D

SM02 = 'Signal'
SM03 = 'Middle Crossover'

variant(type, src, len) =>
    sig = 0.0
    if type == "SMA"
        sig := ta.sma(src, len) 
    else if type == "EMA"
        sig := ta.ema(src, len) 
    else if type == "WMA"
        sig := ta.wma(src, len)   
    else if type == "RMA"
        sig := ta.rma(src, len)  
    else if type == "VWMA"
        sig := ta.rma(src, len)  
    sig

_nma(type, src, nper, smper)=>
    smperout = smper
    float lambda = nper / smper
    if(lambda < 2.0) 
        lambda := 2.0
        smperout := math.ceil(nper / 2.0)
    alpha = lambda * (nper - 1.0) / (nper - lambda)
    sample = variant(type, src, nper)
    gamma = variant(type, sample, smperout)
    nma = (alpha + 1.0) * sample - alpha * gamma
    nma


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)"])

NMA_Fast = input.int(12, "Fast Nyquist Period", group = "Basic Settings", tooltip = "must be at least twice of sample length")
NMA_Fast_sample = input.int(6, "Fast Sample  Period", group = "Basic Settings")
ftype = input.string("SMA", "Fast MACD MA Type", options = ["EMA", "WMA", "RMA", "SMA", "VWMA"], group = "Basic Settings")

NMA_Slow = input.int(26, "Slow Nyquist Period", group = "Basic Settings", tooltip = "must be at least twice of sample length")
NMA_Slow_sample = input.int(13, "Slow Sample  Period", group = "Basic Settings")
stype = input.string("SMA", "Slow MACD MA Type", options = ["EMA", "WMA", "RMA", "SMA", "VWMA"], group = "Basic Settings")

SignalSMA = input.int(9, "Signal Period", group = "Signal Settings")
Magnifier = input.float(1.5, "Signal Magnifier", group = "Signal Settings")

sigtype = input.string(SM03, "Signal type", options = [SM02, SM03], group = "Signal 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
	
alpha = 2.0 / (SignalSMA + 1.0)
alpha_1 = 1.0 - alpha
	
macd = _nma(ftype, src, NMA_Fast, NMA_Fast_sample) - _nma(stype, src, NMA_Slow, NMA_Slow_sample)

sig = 0.
sig := alpha * macd + alpha_1 * nz(sig[1])
histo  = (macd - sig) * Magnifier

state = 0.
mid = 0.
if sigtype == SM02
    if (macd < sig) 
        state :=-1
    if (macd > sig) 
        state := 1
else if sigtype == SM03
    if (macd < mid) 
        state :=-1
    if (macd  > mid)
        state := 1

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

plot(macd, color = colorout, linewidth = 3)
plot(sig, color = color.white)

plot(histo, style = plot.style_histogram, color = color.new(color.white, 60))

plot(mid, "Middle", color =  bar_index % 2 ? color.white : na)

barcolor(colorbars ? colorout : na)

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

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

alertcondition(goLong, title="Long", message="Nyquist Moving Average (NMA) MACD [Loxx] Long\nSymbol: {{ticker}}\nsrc: {{close}}")
alertcondition(goShort, title="Short", message="Nyquist Moving Average (NMA) MACD [Loxx]: Short\nSymbol: {{ticker}}\nsrc: {{close}}")



