STD-Filterd, R-squared Adaptive T3 w/ Dynamic Zones [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("STD-Filterd, R-squared Adaptive T3 w/ Dynamic Zones [Loxx]",
     shorttitle='STDFRSAT3DZ [Loxx]', 
     overlay = true, 
     timeframe="", 
     timeframe_gaps = true)

import loxx/loxxexpandedsourcetypes/4
import loxx/loxxdynamiczone/3

greencolor = #2DD204  
redcolor = #D2042D 

SM02 = 'Slope'
SM03 = 'Middle Crossover'
SM04 = 'Levels Crossover'
SM05 = 'Close'

_t3rSqrdAdapt(float src, float period, bool original, bool trendFollow, bool adapt, float factor)=>
    alpha = original ? 
         2.0 / (1.0 + period) : 
         2.0 / (2.0 + (period - 1.0) / 2.0)
    
    len = 0., SumX = 0., SumX2 = 0.
    SumY = 0., SumY2 = 0., SumXY = 0.
    
    if (len != period)
        len := period, SumX := 0
        for k = 0 to period - 1 
            SumX += k + 1
        SumX2 := 0
        for k = 0 to period - 1 
            SumX2 += (k + 1) * (k + 1)
   
    for k = 0 to period - 1 
        tprice = nz(src[k])
        SumY += tprice
        SumY2 += math.pow(tprice, 2)
        SumXY += (k + 1) * tprice
        
    Q1 = SumXY - SumX * SumY / period
    Q2 = SumX2 - SumX * SumX / period
    Q3 = SumY2 - SumY * SumY / period
    hot = factor
    if adapt
        hot := Q2 * Q3 != 0 ? 
                 trendFollow ? 
                     math.max(1.0 - (Q1 * Q1 / (Q2 * Q3)), 0.01) : 
                     math.max((Q1 * Q1 / (Q2 * Q3)), 0.01) : 0.
    t31 = src, t32 = src, t33 = src
    t34 = src, t35 = src, t36 = src
    price = 0.
    
    t31 := nz(t31[1]) + alpha * (src - nz(t31[1]))
    t32 := nz(t32[1]) + alpha * (t31 - nz(t32[1]))

    price := (1.0 + hot) * t31 - hot * t32
    t33 := nz(t33[1]) + alpha * (price - nz(t33[1]))
    t34 := nz(t34[1]) + alpha * (t33 - nz(t34[1]))

    price := (1.0 + hot) * t33 - hot * t34
    t35 := nz(t35[1]) + alpha * (price - nz(t35[1]))
    t36 := nz(t36[1]) + alpha * (t35 - nz(t36[1]))
    out = ((1.0 + hot) * t35 - hot * t36)
    out

_filt(src, len, filter)=>
    price = src
    filtdev = filter * ta.stdev(src, len)
    price := math.abs(price - price[1]) < filtdev ? price[1] : price
    price

smthtype = input.string("Kaufman", "Heiken-Ashi Better Smoothing", options = ["AMA", "T3", "Kaufman"], group=  "Source Settings")

srcoption = input.string("Close", "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)"])

per = input.int(25, "Period", group = "T3 Settings")
t3hot = input.float(0.7, "T3 Factor (non-adaptive only)", step = 0.01, maxval = 1, minval = 0, group = "T3 Settings")

orig = input.bool(false, "Original?", group = "T3 Settings")
fllwtrnd = input.bool(true, "Trend follow? (adaptive only)", group = "T3 Settings")
adapt = input.bool(true, "Make it Adaptive?", group = "T3 Settings")

filterop = input.string("Both", "Filter Options", options = ["Price", "T3 Filter", "Both"], group=  "Filter Settings")
filter = input.float(0, "Filter Devaitions", minval = 0, group= "Filter Settings")
filterperiod = input.int(1, "Filter Period", minval = 0, group= "Filter Settings")

dzper = input.int(35, "Dynamic Zone Period", group = "Levels Settings")
buyprob  = input.float(0.1, "Dynamic Zone Buy Probability Level", group = "Levels Settings", maxval = 0.999, minval = 0.01, step = 0.01)
sellprob = input.float(0.1, "Dynamic Zone Sell Probability Level", group = "Levels Settings", maxval = 0.999, minval = 0.01, step = 0.01)

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

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

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
	
price = filterop == "Both" or filterop == "Price" and filter > 0 ? _filt(src, filterperiod, filter) : src

t3in = _t3rSqrdAdapt(price, per, orig, fllwtrnd, adapt, t3hot) 
t3 = filterop == "Both" or filterop == "T3 Filter" and filter > 0 ? _filt(t3in, filterperiod, filter) : t3in
sig = nz(t3[1])

bli = loxxdynamiczone.dZone("buy", t3, buyprob,  dzper)
sli = loxxdynamiczone.dZone("sell", t3, sellprob,  dzper)
zli = loxxdynamiczone.dZone("sell", t3, 0.5,  dzper)

state = 0.
if sigtype == SM02
    if (t3 < sig) 
        state :=-1
    if (t3 > sig) 
        state := 1
else if sigtype == SM03
    if (t3 < zli) 
        state :=-1
    if (t3 > zli)
        state := 1
else if sigtype == SM04
    if (t3 < bli) 
        state :=-1
    if (t3 > sli)
        state := 1
else if sigtype == SM05
    if (t3 < close) 
        state :=1
    if (t3 > close)
        state :=-1
        
top = plot(bli, "Top level", color = color.new(greencolor, 50), linewidth = 1)
bot = plot(sli, "Bottom level", color = color.new(redcolor, 50), linewidth = 1)
plot(zli, "Mid level", color = color.new(color.white, 10), linewidth = 1)

var color colorout = na

colorout := state == -1 ? redcolor : state == 1 ? greencolor : nz(colorout[1])

plot(t3, "T3", color = colorout, linewidth = 3)
barcolor(colorbars ? colorout : na)

goLong_pre = sigtype == SM02 ? ta.crossover(t3, sig) : sigtype == SM03 ? ta.crossover(t3, zli) : sigtype == SM04 ? ta.crossover(t3, sli) : ta.crossover(close, t3)
goShort_pre = sigtype == SM02 ? ta.crossunder(t3, sig) : sigtype == SM03 ? ta.crossunder(t3, zli)  : sigtype == SM04 ? ta.crossunder(t3, bli) : ta.crossunder(close, t3)

contSwitch = 0
contSwitch := nz(contSwitch[1])
contSwitch := goLong_pre ? 1 : goShort_pre ? -1 : contSwitch

goLong = goLong_pre and ta.change(contSwitch)
goShort = goShort_pre and ta.change(contSwitch)

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="STD-Filterd, R-squared Adaptive T3 w/ Dynamic Zones [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title="Short", message="STD-Filterd, R-squared Adaptive T3 w/ Dynamic Zones [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")


