The Dual Moving Average Trend Tracking strategy is a quantitative trading strategy that tracks stock price trends. This strategy uses a dual exponential moving average system to determine the direction of price trends and combines the ADX indicator to judge the strength of the trend, capturing price trends over the medium to long term.
This strategy is mainly based on the dual exponential moving average system to determine the direction of the price trend. The strategy uses fast and slow two EMAs with different parameters, the fast EMA1 reacts to price changes more quickly, and the slow EMA2 responds to price changes more slowly. When the fast line crosses above the slow line, it is a buy signal indicating the price has started to rise; when the fast line crosses below the slow line, it is a sell signal indicating the price has started to fall.
In addition, the strategy also introduces the ADX indicator to judge the strength of the trend. ADX calculates price fluctuations to judge the strength of the trend. When ADX rises, it means the trend is strengthening; when ADX falls, it means the trend is weakening. The strategy sets trading filter conditions through the ADX indicator, only issuing trading signals when the trend strength is relatively strong.
Specifically, the strategy’s signal generation rules are:
This can effectively filter out invalid signals with weaker trend strength, further improving the stability of the trading system.
This strategy has the following main advantages:
Captures medium to long term price trends: The dual EMA system can effectively determine medium to long term price trends and avoid interference from short-term market noise.
Filters false breakouts: By judging trend strength through the ADX indicator, it avoids unnecessary losses caused by false breakouts around trend turning points.
Large parameter optimization space: Fast and slow line parameters, ADX parameters and more have room for optimization that can yield better trading outcomes through parameter combinations.
High adaptability: This strategy is suitable for most stocks and time frames, and has been verified in various markets.
Easy to implement: This strategy only requires simple moving average indicators, consumes few resources, is easy to program, and has low practical application costs.
This strategy also has some risks, mainly concentrated in the following areas:
Trend reversal risk: Any trend strategy cannot perfectly determine trend reversal points, and is bound to suffer greater losses when the real trend actually reverses.
Over optimization risk: Optimizing parameters to the extreme can also lead to overfitting of the strategy to historical data, which will reduce the stability and practical effect of the strategy.
Black swan event risk: Major unexpected events will break the original price trend model, causing the moving average indicator to fail, requiring manual intervention or stop loss settings to control losses.
To address the above risks, we can optimize from the following aspects:
Introduce additional indicators to determine price turning points. For example, introduce trading volume, which will amplify when price turning points appear.
Properly relax the ADX parameters to ensure opportunities can be captured in the early stages of a trend. MACD and other auxiliary judgment indicators can also be introduced.
Conduct multi-group training and testing of parameter combinations, and select combinations with good stability and practical effect. This avoids over-optimization risks of single parameter groups.
There are also some directions in which this strategy can be optimized:
Introduce stop loss mechanisms: Set moving stop loss or percentage stop loss, which can actively stop losses when trends reverse to avoid excessive losses.
Combine trading volume indicators: For example trading volume, which can avoid wrong signals when trading volume expands at price turning points.
Parameter self-adaptive optimization: Allow indicator parameters to adjust adaptively according to real-time market changes, rather than fixed static parameters, which can greatly improve the stability of strategies.
Introduce machine learning: Use machine learning algorithms to analyze large amounts of historical data to determine parameters for the moving averages and ADX, and even predict future price movements. This is one direction for the evolution of moving average strategies.
Cross-cycle optimization: Different trading cycle parameters can be set differently, and the optimal configuration under each cycle can be tested.
In general, the Dual Moving Average Trend Tracking strategy is a mature and stable strategy idea. This strategy captures medium to long term price trends through the dual EMA system, and has the ADX indicator to filter signals, which can effectively capture stock price trends and avoid interference from short-term market noise. At the same time, this strategy also has certain risks, requiring optimization of parameter combinations and stop loss methods, and can even introduce more auxiliary indicators and machine learning algorithms to enhance strategy stability. In summary, the Dual Moving Average Trend Tracking strategy has good balance, and is a quantitative strategy idea suitable for medium to long term investors.
/*backtest start: 2022-12-14 00:00:00 end: 2023-11-10 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=3 strategy("Kitaec Strategy4", shorttitle = "Kitaec str4", overlay = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, pyramiding = 0) //Settings needlong = input(true, defval = true, title = "Long") needshort = input(true, defval = true, title = "Short") capital = input(100, defval = 100, minval = 1, maxval = 10000, title = "Lot") len = input(14, defval=14, minval=1, maxval=1000, title="Smoothing") len2 = input(14, defval=14, minval=1, maxval=1000, title="Smoothing2") len3=input(550) src = close ema1=ema(src, len) ema2=ema(ema1, len2) d=ema1-ema2 zlema=ema1+d ema21=ema(src, (len/3)*2) ema22=ema(ema21, (len2/3)*2) d2=ema21-ema22 zlema2=ema21+d2 ema31=ema(src, len3) ema32=ema(ema21, len3) d3=ema31-ema32 zlema3=ema31+d2 fromyear = input(1900, defval = 1900, minval = 1900, maxval = 2100, title = "From Year") toyear = input(2100, defval = 2100, minval = 1900, maxval = 2100, title = "To Year") frommonth = input(01, defval = 01, minval = 01, maxval = 12, title = "From Month") tomonth = input(12, defval = 12, minval = 01, maxval = 12, title = "To Month") fromday = input(01, defval = 01, minval = 01, maxval = 31, title = "From day") today = input(31, defval = 31, minval = 01, maxval = 31, title = "To day") //MAs //ma1 = security(tickerid, "60", vwma(src, len)[1]) //ma2 = security(tickerid, "120", vwma(src, len)[1]) //plot(ma1, linewidth = 2, color = blue, title = "MA") //plot(ma2, linewidth = 2, color = red, title = "MA2") // ADX lenadx = 14 lensig = 14 limadx = 18 up = change(high) down = -change(low) trur = rma(tr, lenadx) plus = fixnan(100 * rma(up > down and up > 0 ? up : 0, lenadx) / trur) minus = fixnan(100 * rma(down > up and down > 0 ? down : 0, lenadx) / trur) sum = plus + minus adx = 100 * rma(abs(plus - minus) / (sum == 0 ? 1 : sum), lensig) adx2 = ema(adx, 14) adx2i = ema(adx2,14) dadx2 = adx2 - adx2i zladx2 = adx2 + dadx2 plus2 = ema(plus, 14) plus2i = ema (plus2, 14) dplus2 = plus2 - plus2i zlplus2 = plus2 + dplus2 minus2 = ema(minus, 14) minus2i = ema (minus2, 14) dminus2 = minus2 - minus2i zlminus2 = minus2 + dminus2 vwma = vwma(close, 150) vwma2 = ema(vwma, 9) vwma2i = ema(vwma2, 9) dvwma2 = vwma2 - vwma2i zlvwma2 = vwma2 + dvwma2 rmax=rma(src, len) rmax2=rma(rmax, len2) rmd=rmax-rmax2 zlrmax=rmax+rmd rmaxz=rma(src, (len/3)*2) rmaxz2=rma(rmaxz, (len2/3)*2) rmzd=rmaxz-rmaxz2 zlrmaxz=rmaxz+rmzd rmaxcol2=zlrmaxz[1] > zlema2[1] ? red:lime rmaxcol= zlrmax[1] > zlema[1] ? red:lime rmazlema3=rma(zlema3, 100) plot(rmazlema3, color=gray, linewidth=2) plot(zlema, color=green) plot(zlema2, color=yellow) plot(zlema3, color=teal, linewidth=2) plot(ema2, color=na) plot(rmax, color=rmaxcol2, linewidth=3) plot(zlrmax, color=rmaxcol, linewidth=3) //Trading size = strategy.position_size lot = 0.0 lot := size != size[1] ? strategy.equity / close * capital / 100 : lot[1] if zlrmax[1] < zlema[1] strategy.entry("Buy", strategy.long, needlong ? lot : 0, when = (time > timestamp(fromyear, frommonth, fromday, 00, 00) and time < timestamp(toyear, tomonth, today, 23, 59))) if zlrmax[1] > zlema[1] strategy.entry("Sell", strategy.short, needshort ? lot : 0, when = (time > timestamp(fromyear, frommonth, fromday, 00, 00) and time < timestamp(toyear, tomonth, today, 23, 59)))