Clutter-Filtered, D-Lag Reducer, Spec. Ops FIR Filter [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("Clutter-Filtered, D-Lag Reducer, Spec. Ops FIR Filter [Loxx]",
     shorttitle = "CFDLLRFF [Loxx]",
     overlay = true, 
     timeframe="", 
     timeframe_gaps = true)

import loxx/loxxexpandedsourcetypes/4

greencolor = #2DD204
redcolor = #D2042D 

duelElementLagReducer(float[] coeff, int LagReductionFactor)=>
    if LagReductionFactor > 0
        per = array.size(coeff)
        for i = per - 1 to 0
            if i >= LagReductionFactor
                array.set(coeff, i, 2 * array.get(coeff, i) - array.get(coeff, i - LagReductionFactor))
            else
                array.set(coeff, i, 2 * array.get(coeff, i))
    coeff

directFormFIR(float src, int per, float[] coeff)=>
	float sum = 0.0
	for n = 0 to per - 1
		sum += nz(src[n]) * array.get(coeff, n)
    sum

clutterFilt(float src, float threshold)=>
    bool out = math.abs(ta.roc(src, 1)) > threshold
    out
    
var array<float> coeff = array.new<float>(40, 0)
array.set(coeff, 0, 0.2682078129301)
array.set(coeff, 1, 0.240689662817)
array.set(coeff, 2, 0.2034776029464)
array.set(coeff, 3, 0.1630112541839)
array.set(coeff, 4, 0.1238604113978)
array.set(coeff, 5, 0.08882117730373)
array.set(coeff, 6, 0.0592575366455)
array.set(coeff, 7, 0.0355091376143)
array.set(coeff, 8, 0.01726488214552)
array.set(coeff, 9, 0.003859198612914)
array.set(coeff, 10, -0.005516867700847)
array.set(coeff, 11, -0.01167964519718)
array.set(coeff, 12, -0.01537516433377)
array.set(coeff, 13, -0.01724253310596)
array.set(coeff, 14, -0.01780402378186)
array.set(coeff, 15, -0.01747064024502)
array.set(coeff, 16, -0.01655561037259)
array.set(coeff, 17, -0.01529076983704)
array.set(coeff, 18, -0.01384290192686)
array.set(coeff, 19, -0.01232850220073)
array.set(coeff, 20, -0.0108262356619)
array.set(coeff, 21, -0.009387057661213)
array.set(coeff, 22, -0.008042117218492)
array.set(coeff, 23, -0.006808722524782)
array.set(coeff, 24, -0.005694738789271)
array.set(coeff, 25, -0.004701770313144)
array.set(coeff, 26, -0.003827379758726)
array.set(coeff, 27, -0.003066597695855)
array.set(coeff, 28, -0.002412921398684)
array.set(coeff, 29, -0.001858955235279)
array.set(coeff, 30, -0.001396806658866)
array.set(coeff, 31, -0.001018320955267)
array.set(coeff, 32, -0.0007152136335629)
array.set(coeff, 33, -0.0004791407494877)
array.set(coeff, 34, -0.0003017336191226)
array.set(coeff, 35, -0.0001746144517018)
array.set(coeff, 36, -0.00008940260506336)
array.set(coeff, 37, -0.00003771672382874)
array.set(coeff, 38, -0.00001117532554157)
array.set(coeff, 39, -0.000001396915692344)

smthtype = input.string("Kaufman", "Heiken-Ashi Better Smoothing", options = ["AMA", "T3", "Kaufman"], group=  "Source Settings")
srcoption = input.string("HAB Median", "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)"])

lagr = input.int(0, "Lag Reduction Factor", group = "Basic Settings")
per = 39
sth = input.float(0.1, "Threshold", group = "Basic Settings", step = 0.001)

colorbars = input.bool(true, "Color bars?", group = "UI Options")
showSigs = input.bool(true, "Show signals?", group= "UI Options")
showdeadzones = input.bool(false, "Show dead zones?", 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)

float src = switch srcoption
	"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

out = src
color colorout = na
goLong = false
goShort = false

duelElementLagReducer(coeff, lagr)
out := directFormFIR(src, per, coeff)
sig = nz(out[1])

filtTrend = clutterFilt(out, sth)

state = filtTrend ? (out > sig ? 1 : out < sig ? -1 : 0) : 0

pregoLong = state == 1
pregoShort =state == -1

contsw = 0
contsw := nz(contsw[1])
contsw := pregoLong ? 1 : pregoShort ? -1 : nz(contsw[1])

goLong := pregoLong and nz(contsw[1]) == -1
goShort := pregoShort and nz(contsw[1]) == 1 

colorout := filtTrend ? (state == 1 ? greencolor : state == -1 ? redcolor : showdeadzones ? color.gray : colorout[1]) : showdeadzones ? color.gray : colorout[1]

plot(out, "CFDLLRFF MA", color = colorout, linewidth = 3)

barcolor(colorbars ? colorout : na)

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

alertcondition(goLong, title = "Long", message = "Clutter-Filtered, D-Lag Reducer, Spec. Ops FIR Filter [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title = "Short", message = "Clutter-Filtered, D-Lag Reducer, Spec. Ops FIR Filter [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")

