STD-Filtered Jurik Volty Adaptive TEMA [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-Filtered Jurik Volty Adaptive TEMA [Loxx]", 
     overlay = true, 
     timeframe="", 
     timeframe_gaps = true)

import loxx/loxxexpandedsourcetypes/4

greencolor = #2DD204
redcolor = #D2042D 

specema(src, per) =>
    float ema = src
    ema := na(ema[1]) ? src : (src - nz(ema[1])) * (2 / (per + 1)) + nz(ema[1])
    ema

tema(src, len) =>
    float ema1 = specema(src, len)
    float ema2 = specema(ema1, len)
    float ema3 = specema(ema2, len)
    float out = 3 * (ema1 - ema2) + ema3
    out 

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

volty(float src, int len) =>
    int avgLen = 65
    float volty = 0.0
    float voltya = 0.0
    float bsmax = src 
    float bsmin = src 
    float vsum = 0
    float len1 = math.max(math.log(math.sqrt(0.5 * (len-1))) / math.log(2.0) + 2.0, 0)
    float pow1 = math.max(len1 - 2.0, 0.5)
    float del1 = src - nz(bsmax[1])
    float del2 = src - nz(bsmin[1])
    volty := bar_index > 9 ?  math.abs(del1) > math.abs(del2) ? math.abs(del1) : math.abs(del2) : voltya
    vsum := nz(vsum[1]) + 0.1 * (volty - nz(volty[10]))
    avg = ta.sma(vsum, avgLen)
    float avolty = avg 
    float dVolty = avolty > 0 ? voltya / avolty : 0
    if dVolty > math.pow(len1, 1.0/pow1)
        dVolty := math.pow(len1, 1.0/pow1)
    if dVolty < 1                     
        dVolty := 1.0
    float pow2 = math.pow(dVolty, pow1)
    float len2 = math.sqrt(0.5*(len-1)) * len1
    float Kv   = math.pow(len2/(len2+1), math.sqrt(pow2))
    if del1 > 0  
        bsmax := src
    else 
        bsmax := src - Kv * del1
    if del2 < 0
        bsmin := src
    else 
        bsmin := src - Kv * del2
    float temp = vsum != 0 ? avolty / vsum : 1
    temp

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

len = input.int(27, "EMA Length", group = "Basic Settings")

filterop = input.string("Both", "Filter Options", options = ["Price", "Jurik Volty Adaptive TEMA", "Both", "None"], group=  "Filter Settings")
filter = input.float(1, "Filter Devaitions", minval = 0, group= "Filter Settings")
filterperiod = input.int(10, "Filter Period", minval = 0, group= "Filter Settings")

colorbars = input.bool(true, title='Color bars', group = "UI Options")
showSigs = input.bool(true, title='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")
t3hot = input.float(.7, "* T3 Only - T3 Hot", group = "Moving Average Inputs")
t3swt = input.string("T3 New", "* T3 Only - T3 Type", options = ["T3 New", "T3 Original"], group = "Moving Average Inputs")

haclose  =  ohlc4
haopen   = float(na)
haopen  := na(haopen[1]) ? (open + close) / 2 : (nz(haopen[1]) + nz(haclose[1])) / 2
hahigh   =math.max(high, math.max(haopen, haclose))
halow    = math.min(low,  math.min(haopen, haclose))
hamedian = (hahigh + halow) / 2
hatypical = (hahigh + halow + haclose) / 3
haweighted =  (hahigh + halow + haclose + haclose)/4 
haaverage =  (haopen + hahigh + halow + haclose)/4

sourceout(smthtype, srcin)=>
	src = switch srcin
		"Close" => close
		"Open" => open
		"High" => high
		"Low" => low
		"Median" => hl2
		"Typical" => hlc3
		"Weighted" => hlcc4
		"Average" => ohlc4
		"Average Median Body" => (open + close)/2
		"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)
		=> close

src = sourceout(smthtype, srcin)
src := filterop == "Both" or filterop == "Price" and filter > 0 ? stdFilter(src, filterperiod, filter) : src

out = tema(src, len * volty(src, len))

out := filterop == "Both" or filterop == "Jurik Volty Adaptive TEMA" and filter > 0 ? stdFilter(out, filterperiod, filter) : out
sig = out[1]

state = out > sig ? 1 : out < sig ? -1 : 0
pregoLong = out > sig and (nz(out[1]) < nz(sig[1]) or nz(out[1]) == nz(sig[1]))
pregoShort = out < sig and (nz(out[1]) > nz(sig[1]) or nz(out[1]) == nz(sig[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 

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

plot(out, "Jurik Volty Adaptive TEMA", 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 = "STD-Filtered Jurik Volty Adaptive TEMA [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title = "Short", message = "STD-Filtered Jurik Volty Adaptive TEMA [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")