The Triple Dynamic Moving Average Trend Tracking strategy uses multiple time frame dynamic smoothed moving averages to identify market trends and achieve trend consistency filtering across different time frames, thereby improving the reliability of trading signals.
The strategy employs 3 dynamic smoothed moving averages with different parameter settings. The first moving average calculates the trend direction of current period prices, the second moving average calculates the trend direction of higher time frame prices, and the third moving average calculates the trend direction of even higher time frame prices. A buy signal is generated when the first moving average crosses above the second moving average, and the third moving average is also in an upward trend, which verifies the reliability of the buy signal. The entire strategy achieves trend consistency across multiple time frames through inter-timeframe trend filtering, ensuring the reliability of trading signals.
The dynamic smoothing feature is used to automatically calculate and apply appropriate smoothing factors between different time frames, so that the higher time frame moving averages present smooth trendlines instead of jagged zigzag lines on the lower time frame charts. This dynamic smoothing allows the strategy to determine the overall trend direction on higher time frames while executing trades on lower time frames for efficient trend tracking.
The biggest advantage of this strategy lies in its inter-timeframe trend filtering mechanism. By calculating the average trend directions of prices across different time periods and requiring consistency among them, it can effectively filter out short-term price fluctuations that interfere with trading signals, ensuring that each trade is placed along the major trend, thereby significantly improving profitability.
Another advantage is the application of dynamic smoothing. This allows the strategy to identify both the overall trend on higher time frames and specific trading points on lower time frames simultaneously. The strategy can determine the major trend direction on higher time frames while executing specific trades on lower time frames. Such application of multiple time frames helps to capitalize on market opportunities while controlling trading risks.
The main risk of this strategy is the relatively few trading signals. The strict trend filtering conditions reduce the number of trading opportunities, which may not suit some investors pursuing high-frequency trading. The strictness of filtering conditions can be reduced to obtain more trading opportunities.
In addition, careful testing and optimization is needed for parameter settings, especially the moving average periods, which require different optimum values across different markets. The optimal parameter combinations can be found through backtesting.
Future optimization directions may also consider incorporating more technical indicators for signal filtering or increasing machine learning algorithms for automatic parameter optimization. These are all effective methods to improve strategy performance.
In conclusion, this is a very practical trend tracking strategy. The inter-timeframe trend filtering provides good directional guidance to support each trading decision, effectively reducing trading risks. The addition of dynamic smoothing also enables efficient implementation of this multi-timeframe approach. The entire strategy framework is reasonable and efficient, worthy of learning and application.
/*backtest start: 2024-01-23 00:00:00 end: 2024-02-22 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © Harrocop //@version=5 strategy(title = "Triple MA HTF strategy - Dynamic Smoothing", shorttitle = "Triple MA strategy", overlay=true, pyramiding=5, initial_capital = 10000, calc_on_order_fills=false, slippage = 0, commission_type=strategy.commission.percent, commission_value=0.05) ////////////////////////////////////////////////////// ////////// Risk Management //////////// ////////////////////////////////////////////////////// RISKM = "-------------------- Risk Management --------------------" InitialBalance = input.float(defval = 10000, title = "Initial Balance", minval = 1, maxval = 1000000, step = 1000, tooltip = "starting capital", group = RISKM) LeverageEquity = input.bool(defval = true, title = "qty based on equity %", tooltip = "true turns on MarginFactor based on equity, false gives fixed qty for positionsize", group = RISKM) MarginFactor = input.float(0, minval = - 0.9, maxval = 100, step = 0.1, tooltip = "Margin Factor, meaning that 0.5 will add 50% extra capital to determine ordersize quantity, 0.0 means 100% of equity is used to decide quantity of instrument", inline = "qty", group = RISKM) QtyNr = input.float(defval = 3.5, title = "Quantity Contracts", minval = 0, maxval = 1000000, step = 0.01, tooltip = "Margin Factor, meaning that 0.5 will add 50% extra capital to determine ordersize quantity, 0.0 means 100% of equity is used to decide quantity of instrument", inline = "qty", group = RISKM) EquityCurrent = InitialBalance + strategy.netprofit[1] QtyEquity = EquityCurrent * (1 + MarginFactor) / close[1] QtyTrade = LeverageEquity ? QtyEquity : QtyNr ///////////////////////////////////////////////////// ////////// MA Filter Trend //////////// ///////////////////////////////////////////////////// TREND = "-------------------- Moving Average 1 --------------------" Plot_MA = input.bool(true, title = "Plot MA trend?", inline = "Trend1", group = TREND) TimeFrame_Trend = input.timeframe(title='Higher Time Frame', defval='15', inline = "Trend1", group = TREND) length = input.int(21, title="Length MA", minval=1, tooltip = "Number of bars used to measure trend on higher timeframe chart", inline = "Trend2", group = TREND) MA_Type = input.string(defval="McGinley" , options=["EMA","DEMA","TEMA","SMA","WMA", "HMA", "McGinley"], title="MA type:", 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.tickerid, 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 ///////////////////////////////////////////////////// ////////// Second MA Filter Trend /////////// ///////////////////////////////////////////////////// TREND2 = "-------------------- Moving Average 2 --------------------" Plot_MA2 = input.bool(true, title = "Plot Second MA trend?", inline = "Trend3", group = TREND2) TimeFrame_Trend2 = input.timeframe(title='HTF', defval='60', inline = "Trend3", group = TREND2) length2 = input.int(21, title="Length Second MA", minval=1, tooltip = "Number of bars used to measure trend on higher timeframe chart", inline = "Trend4", group = TREND2) MA_Type2 = input.string(defval="McGinley" , options=["EMA","DEMA","TEMA","SMA","WMA", "HMA", "McGinley"], title="MA type:", inline = "Trend4", group = TREND2) // Second Moving Average MAtrend2 = ma(MA_Type2, close, length2) MA_Value_HTF2 = request.security(syminfo.tickerid, TimeFrame_Trend2, MAtrend2) // Get minutes for current and higher timeframes higherTFMinutes2 = timeframeToMinutes(TimeFrame_Trend2) // Calculate the smoothing factor for the second moving average dynamicSmoothing2 = math.round(higherTFMinutes2 / currentTFMinutes) MA_Value_Smooth2 = ta.sma(MA_Value_HTF2, dynamicSmoothing2) // Trend HTF for the second moving average UP2 = MA_Value_Smooth2 > MA_Value_Smooth2[1] DOWN2 = MA_Value_Smooth2 < MA_Value_Smooth2[1] ///////////////////////////////////////////////////// ////////// Third MA Filter Trend /////////// ///////////////////////////////////////////////////// TREND3 = "-------------------- Moving Average 3 --------------------" Plot_MA3 = input.bool(true, title = "Plot third MA trend?", inline = "Trend5", group = TREND3) TimeFrame_Trend3 = input.timeframe(title='HTF', defval='240', inline = "Trend5", group = TREND3) length3 = input.int(50, title="Length third MA", minval=1, tooltip = "Number of bars used to measure trend on higher timeframe chart", inline = "Trend6", group = TREND3) MA_Type3 = input.string(defval="McGinley" , options=["EMA","DEMA","TEMA","SMA","WMA", "HMA", "McGinley"], title="MA type:", inline = "Trend6", group = TREND3) // Second Moving Average MAtrend3 = ma(MA_Type3, close, length3) MA_Value_HTF3 = request.security(syminfo.tickerid, TimeFrame_Trend3, MAtrend3) // Get minutes for current and higher timeframes higherTFMinutes3 = timeframeToMinutes(TimeFrame_Trend3) // Calculate the smoothing factor for the second moving average dynamicSmoothing3 = math.round(higherTFMinutes3 / currentTFMinutes) MA_Value_Smooth3 = ta.sma(MA_Value_HTF3, dynamicSmoothing3) // Trend HTF for the second moving average UP3 = MA_Value_Smooth3 > MA_Value_Smooth3[1] DOWN3 = MA_Value_Smooth3 < MA_Value_Smooth3[1] ///////////////////////////////////////////////////// ////////// Entry Settings //////////// ///////////////////////////////////////////////////// BuySignal = ta.crossover(MA_Value_HTF, MA_Value_HTF2) and UP3 == true SellSignal = ta.crossunder(MA_Value_HTF, MA_Value_HTF2) and DOWN3 == true ExitBuy = ta.crossunder(MA_Value_HTF, MA_Value_HTF2) ExitSell = ta.crossover(MA_Value_HTF, MA_Value_HTF2) ///////////////////////////////////////////////// /////////// Strategy //////////////// /////////// Entry & Exit //////////////// /////////// logic //////////////// ///////////////////////////////////////////////// // Long if BuySignal strategy.entry("Long", strategy.long, qty = QtyTrade) if (strategy.position_size > 0 and ExitBuy == true) strategy.close(id = "Long", comment = "Close Long") // Short if SellSignal strategy.entry("Short", strategy.short, qty = QtyTrade) if (strategy.position_size < 0 and ExitSell == true) strategy.close(id = "Short", comment = "Close Short") ///////////////////////////////////////////////////// ////////// Visuals Chart //////////// ///////////////////////////////////////////////////// // Plot Moving Average HTF p1 = plot(Plot_MA ? MA_Value_Smooth : na, "HTF Trend", color = UP ? color.rgb(238, 255, 0) : color.rgb(175, 173, 38), linewidth = 1, style = plot.style_line) p2 = plot(Plot_MA2 ? MA_Value_Smooth2 : na, "HTF Trend", color = UP2 ? color.rgb(0, 132, 255) : color.rgb(0, 17, 255), linewidth = 1, style = plot.style_line) plot(Plot_MA3 ? MA_Value_Smooth3 : na, "HTF Trend", color = UP3 ? color.rgb(0, 255, 8) : color.rgb(255, 0, 0), linewidth = 2, style = plot.style_line) fill(p1, p2, color = color.rgb(255, 208, 0, 90), title="Fill")