Gaussian Average Convergence Divergence
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © themocrew

//@version=5
indicator(title="Gaussian Average Convergence Divergence", shorttitle="GACD", overlay=false)

// ===== INDICATOR SETTINGS ===== {

// LENGTH INPUT SETTINGS
int i_length = input.int(defval=21, minval=2, title="Length 1", group="GACD Settings")
int i_length2 = input.int(defval=34, minval=2, title="Length 2", group="GACD Settings")
int i_length3 = input.int(defval=21, minval=2,title="Length 3", group="GACD Settings")

// HISTOGRAM COLOR CUSTOMIZATION SETTINGS
color i_col_grow_above = input.color(defval=#26A69A, title="Above Grow", group="Histogram", inline="Above")
color i_col_fall_above = input.color(defval=#B2DFDB, title="Fall", group="Histogram", inline="Above")
color i_col_grow_below = input.color(defval=#FFCDD2, title="Below Grow", group="Histogram", inline="Below")
color i_col_fall_below = input.color(defval=#FF5252, title="Fall", group="Histogram", inline="Below")

// SIGNAL LINE COLOR CUSTOMIZATION SETTINGS
color i_signal_line_above = input.color(defval=color.green, title="Cross Above", group="Signal Lines", inline="Line")
color i_signal_line_below = input.color(defval=color.red, title="Cross Below", group="Signal Lines", inline="Line")

// BAND COLOR CUSTOMIZATION SETTINGS
bool i_show_fill = input.bool(defval=true, title="Display Fill", group="Band")
color i_band_above = input.color(defval=color.green, title="Band Above", group="Band", inline="Band")
color i_band_below = input.color(defval=color.red, title="Band Below", group="Band", inline="Band")
int i_band_opacity = 100 - input.int(defval=100, minval=0, maxval=100, title="Opacity (%)", group="Band")

// VERTICAL LINE CUSTOMIZATION SETTINGS
bool i_vert = input.bool(defval=true, title="Display Verticle Line", group="Verticle Line")
color i_vert_above = input.color(defval=color.green, title="Cross Above", group="Verticle Line", inline="Color")
color i_vert_below = input.color(defval=color.red, title="Cross Below", group="Verticle Line", inline="Color")
string i_vert_style = input.string(defval="Dashed", title="Line Style", options=["Solid", "Dashed", "Dotted"], group="Verticle Line")
int i_vert_thickness = input.int(defval=1, minval=1, maxval=5, title="Line Thickness", group="Verticle Line")

// TREND TABLE CUSTOMIZATION SETTINGS
bool i_display_trend = input.bool(defval=true, title="Display Trend Analysis", group="Trend Analysis")
color i_table_background_color = input.color(defval=color.black, title="Background Color", group="Trend Analysis")
color i_text_color_uptrend = input.color(defval=color.green, title="Up Trend Color", group="Trend Analysis")
color i_text_color_downtrend = input.color(defval=color.red, title="Down Trend Color", group="Trend Analysis")
color i_text_color_undetermined = input.color(defval=color.white, title="Undetermined Trend Color", group="Trend Analysis")

// }

// ===== CALCULATIONS ===== {
f_G(_data,_length) =>
    var float g = 0.0

    float betaDenom = 10 * (math.log(math.sum((math.max(high, close[1]) - math.min(low, close[1])), _length) / (ta.highest(high, _length) - ta.lowest(low, _length))) / math.log(_length))
    float w = (2 * math.pi / _length)
    float beta = (1 - math.cos(w)) / (math.pow(1.414, 2.0 / betaDenom) - 1 )
    float alpha = (-beta + math.sqrt(beta * beta + 2 * beta))
    g := math.pow(alpha, 4) * _data + 4 * (1 - alpha) * nz(g[1]) - 6 * math.pow(1 - alpha,2) * nz(g[2]) + 4 * math.pow(1 - alpha,3) * nz(g[3]) - math.pow( 1 - alpha,4) * nz(g[4])
     
float fgA = f_G(close,i_length) - f_G(close,i_length2)
float fgB = f_G(fgA,i_length3)
float fgD = fgA - fgB

// }

// ===== Plotting ===== {

// HISTOGRAM
plot(fgD, style = plot.style_columns, color = (fgD>=0 ? (fgD[1] < fgD ? i_col_grow_above : i_col_fall_above) : (fgD[1] < fgD ? i_col_grow_below : i_col_fall_below)))

// SIGANL LINES
fgAplot = plot(fgA,color = fgA > fgB ? i_signal_line_above : i_signal_line_below)
fgBplot = plot(fgB,color = fgA > fgB ? i_signal_line_above : i_signal_line_below)

// BAND
fill(fgAplot, fgBplot, color=fgA > fgB ? color.new(i_band_above, i_show_fill ? i_band_opacity : 100) : color.new(i_band_below, i_show_fill ? i_band_opacity : 100))

// VERTICLE LINE
if i_vert
    if fgD > 0 and fgD[1] < 0
        line.new(bar_index, fgD, bar_index, fgD * 1.01, extend = extend.both, color = i_vert_above, style = i_vert_style == "Dashed" ? line.style_dashed : i_vert_style == "Solid" ? line.style_solid : line.style_dotted, width = i_vert_thickness)

    if fgD < 0 and fgD[1] > 0
        line.new(bar_index, fgD, bar_index, fgD * 1.01, extend = extend.both, color = i_vert_below, style = i_vert_style == "Dashed" ? line.style_dashed : i_vert_style == "Solid" ? line.style_solid : line.style_dotted, width = i_vert_thickness)

// TREND TABLE
string trendText = ""

if math.max(fgA, fgB) < 0 and fgA < fgB
    trendText := "Trend Down"
else if math.max(fgA, fgB) < 0 and fgA > fgB
    trendText := "Trend Down Slowing"
else if  (0 > fgA and 0 < fgB or 0 < fgA and 0 > fgB) and fgD > fgD[1]
    trendText := "Trend Reversing"
else if math.min(fgA, fgB) > 0 and fgA > fgB
    trendText := "Trend Up"
else if math.min(fgA, fgB) > 0 and fgA < fgB
    trendText := "Trend Up Slowing"
else if math.min(fgA, fgB) > 0 and fgD > fgD[1]
    trendText := "Trend Up Accelerating"
else if math.min(fgA, fgB) > 0 and fgA < fgB and  fgD < fgD[1]
    trendText := "Trend Up decelerating"
else 
    trendText := "Undetermined Trend"

var table trendDisplay = table.new(position=position.top_right, columns=1, rows=1, bgcolor=i_table_background_color)

if barstate.islast and i_display_trend
    table.cell(table_id=trendDisplay, column=0, row=0, text=trendText, text_color=math.max(fgA, fgB) < 0 ? i_text_color_downtrend : math.min(fgA, fgB) > 0 ? i_text_color_uptrend : i_text_color_undetermined)

// }