SuperTrend with Chebyshev Filter
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © peacefulLizard50262

//@version=5
indicator("Chebyshev Trend", overlay = true, max_labels_count = 500)
// Custom cosh function
cosh(float x) =>
    (math.exp(x) + math.exp(-x)) / 2

// Custom acosh function
acosh(float x) =>
    x < 1 ? na : math.log(x + math.sqrt(x * x - 1))

// Custom sinh function
sinh(float x) =>
    (math.exp(x) - math.exp(-x)) / 2

// Custom asinh function
asinh(float x) =>
    math.log(x + math.sqrt(x * x + 1))

// Custom inverse tangent function
atan(float x) =>
    math.pi / 2 - math.atan(1 / x)

// Chebyshev Type I Moving Average
chebyshevI(float src, float len, float ripple) =>
    a = 0.
    b = 0.
    g = 0.
    chebyshev = 0.
    
    a := cosh(1 / len * acosh(1 / (1 - ripple)))
    b := sinh(1 / len * asinh(1 / ripple))
    g := (a - b) / (a + b)
    chebyshev := (1 - g) * src + g * nz(chebyshev[1])
    chebyshev

// Chebyshev Type II Moving Average
chebyshevII(float src, float len, float ripple) =>
    a = 0.
    b = 0.
    g = 0.
    chebyshev = 0.
    
    a := cosh(1 / len * acosh(1 / ripple))
    b := sinh(1 / len * asinh(ripple))
    g := (a - b) / (a + b)
    chebyshev := (1 - g) * src + g * nz(chebyshev[1], src)
    chebyshev

chebyshev(float src, float length, float ripple, bool style) =>
    style ?
     chebyshevI(src, length, ripple) :
     chebyshevII(src, length, ripple)

source = input.source(hl2, "Source")
up_color = input.color(color.new(color.green, 20), "Up Color")
down_color = input.color(color.new(color.red, 20), "Down Color")
text_color = input.color(color.black, "Text Color")
mean_length = input.float(64, "Mean Length", 5, 1000, 0.5)
mean_ripple = input.float(0.2, "Mean Ripple", 0.01, 0.99, 0.01)
style = input.bool(false, "True Chebyshev I | False : Chebyshev II")
atr_style = input.bool(false, "True: |Open-Close|  False: High-Low")
atr_length = input.float(64, "ATR Length", 6, 1000, 0.5)
atr_ripple = input.float(0.05, "Mean Ripple", 0.01, 0.99, 0.01)
multiplier = input.float(1.5, "Multiplier", 0.125, 10, 0.125)
alerts = input.bool(false, "Alerts")
labels = input.bool(false, "Labels")

atr = chebyshev(atr_style ? high - low : math.abs(open - close), atr_length, atr_ripple, style)
mean = chebyshevI(source, mean_length, mean_ripple)

var float offset = 0.0
var bool state = na
var float newOffset = 0.0

crossover = ta.crossover(source, offset)
position = source > offset
crossunder = ta.crossunder(source, offset)

prevOffset = nz(offset[1])

if crossover[2] and position[1] and position or (position and position[1] and position[2]) 
    newOffset := mean - atr * multiplier
    offset := newOffset < nz(prevOffset) or close[1] > nz(prevOffset) ? newOffset : nz(prevOffset)
    state := true

if crossunder[2] and not position[1] and not position or (not position and not position[1] and not position[2]) 
    newOffset := mean + atr * multiplier
    offset := newOffset > nz(prevOffset) or close[1] < nz(prevOffset) ? newOffset : nz(prevOffset)
    state := false

cross = ta.cross(close, offset)

down_trend = not state and not state[1]
up_trend = state and state[1]

colour = up_trend ? up_color : down_trend ? down_color : color.new(color.white, 100) 

if up_trend and not up_trend[1] and labels
    label.new(bar_index, offset, "Up Trend \n" + str.tostring(close), color = up_color, style = label.style_label_up, textcolor = text_color)
    alert("Up Trend at " + str.tostring(close))
else
    alert("Up Trend at " + str.tostring(close))

if down_trend and not down_trend[1] and labels
    label.new(bar_index, offset, "Down Trend \n" + str.tostring(close), color = down_color, style = label.style_label_down, textcolor = text_color)
    alert("Down Trend at " + str.tostring(close))
else
    alert("Down Trend at " + str.tostring(close))
    
plot(offset, "Chebyshev Trend", colour, style = plot.style_linebr)

plotshape(cross, "Trend Is Getting Ready To Change", shape.xcross, location.belowbar, color = close > offset ? up_color : down_color)