HTF Trend Filter - Dynamic Smoothing
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Harrocop

////////////////////////////////////////////////////////////////////////////////////////
// HTF Trend Filter - Dynamic Smoothing
// - Option to change high time frame settings
// - Option to choose from different moving average types
// - The Dynamic smoothing makes a sleek line, taking the ratio of minutes of the higher time frame to the current time frame
// - Color green with uptrend, color red with downtrend
// - options for notification in case of trend reversal
////////////////////////////////////////////////////////////////////////////////////////

//@version=5
indicator("HTF Trend Filter - Dynamic Smoothing", "HTF trend", overlay = true)

//////////////////////////////////////////////////////
//////////          Filter Trend          ////////////
//////////////////////////////////////////////////////
TREND = "Higher Time Frame Trend"
TimeFrame_Trend = input.timeframe(title='Higher Time Frame', defval='240', inline = "Trend1", group = TREND)
length = input.int(55, title="Length MA", minval=1, tooltip = "Number of bars used to measure trend on higher timeframe chart", inline = "Trend1", group = TREND)
MA_Type  = input.string(defval="EMA" , options=["EMA","DEMA","TEMA","SMA","WMA", "HMA", "McGinley"], title="MA type for HTF trend", inline = "Trend2", group = TREND)
Plot_Reversal = input.bool(true, title = "Plot Reversal?", inline = "Trend2", group = TREND)

ma(type, src, length) =>
    float result = 0
    if type == 'TMA' // Triangular Moving Average
        result := ta.sma(ta.sma(src, math.ceil(length / 2)), math.floor(length / 2) + 1)
        result
    if type == 'LSMA' // Least Squares Moving Average
        result := ta.linreg(src, length, 0)
        result
    if type == 'SMA'  // Simple Moving Average
        result := ta.sma(src, length)
        result
    if type == 'EMA'  // Exponential Moving Average
        result := ta.ema(src, length)
        result
    if type == 'DEMA'  // Double Exponential Moving Average
        e = ta.ema(src, length)
        result := 2 * e - ta.ema(e, length)
        result
    if type == 'TEMA'  // Triple Exponentiale
        e = ta.ema(src, length)
        result := 3 * (e - ta.ema(e, length)) + ta.ema(ta.ema(e, length), length)
        result
    if type == 'WMA'  // Weighted Moving Average
        result := ta.wma(src, length)
        result
    if type == 'HMA'  // Hull Moving Average
        result := ta.wma(2 * ta.wma(src, length / 2) - ta.wma(src, length), math.round(math.sqrt(length)))
        result
    if type == 'McGinley' // McGinley Dynamic Moving Average
        mg = 0.0
        mg := na(mg[1]) ? ta.ema(src, length) : mg[1] + (src - mg[1]) / (length * math.pow(src / mg[1], 4))
        result := mg
        result
    result

// Moving Average
MAtrend = ma(MA_Type, close, length)
MA_Value_HTF = request.security(syminfo.ticker, TimeFrame_Trend, MAtrend)

// Get minutes for current and higher timeframes
// Function to convert a timeframe string to its equivalent in minutes
timeframeToMinutes(tf) =>
    multiplier = 1
    if (str.endswith(tf, "D"))
        multiplier := 1440
    else if (str.endswith(tf, "W"))
        multiplier := 10080
    else if (str.endswith(tf, "M"))
        multiplier := 43200
    else if (str.endswith(tf, "H"))
        multiplier := int(str.tonumber(str.replace(tf, "H", "")))
    else
        multiplier := int(str.tonumber(str.replace(tf, "m", "")))
    multiplier

// Get minutes for current and higher timeframes
currentTFMinutes = timeframeToMinutes(timeframe.period)
higherTFMinutes = timeframeToMinutes(TimeFrame_Trend)

// Calculate the smoothing factor
dynamicSmoothing = math.round(higherTFMinutes / currentTFMinutes)
MA_Value_Smooth = ta.sma(MA_Value_HTF, dynamicSmoothing)

// Trend HTF
UP = MA_Value_Smooth > MA_Value_Smooth[1] // Use "UP" Function to use as filter in combination with other indicators
DOWN = MA_Value_Smooth < MA_Value_Smooth[1] // Use "Down" Function to use as filter in combination with other indicators

Reversal_UP = MA_Value_Smooth[1] < MA_Value_Smooth[2] and MA_Value_Smooth > MA_Value_Smooth[1] == true
Reversal_DOWN = MA_Value_Smooth[1] > MA_Value_Smooth[2] and MA_Value_Smooth < MA_Value_Smooth[1] == true

// Plot HTF Trend and Reversals
plot(MA_Value_Smooth, "HTF Trend", color = UP ? color.rgb(0, 255, 8) : color.rgb(255, 0, 0), linewidth = 2, style = plot.style_line)
plot(Plot_Reversal ? Reversal_UP ? MA_Value_Smooth : na : na, "Start of Up trend!", style = plot.style_circles, color = color.rgb(0, 255, 8), linewidth = 4)
plot(Plot_Reversal ? Reversal_DOWN ? MA_Value_Smooth : na : na, "Start of Down trend!", style = plot.style_circles, color = color.rgb(255, 0, 0), linewidth = 4)

//////////////////////////////////////////////////
///////////         Alerts        ////////////////
//////////////////////////////////////////////////
// Alert conditions for Crossover
alertcondition(Reversal_UP, title="Uptrend Started", message="Uptrend Started!")
alertcondition(Reversal_DOWN, title="Downtrend started!", message="Downtrend started!")