The double moving average crossover strategy is a trend-following strategy that uses the crossover of two moving averages of different periods as trading signals. It enters long or short positions when the fast MA crosses above or below the slow MA and determines trend direction after the crossover. It can capture intermediate-term trends while reducing unnecessary trading frequency from excessive fluctuations.
The strategy employs two moving averages: a fast MA with a shorter period (e.g. 15 periods) to capture short-term price moves, and a slow MA with a longer period (e.g. 21 periods) to identify major trend direction. Trading signals are generated from the crossover between the two MAs: the fast MA crossing above the slow MA gives buy signals, while the fast MA crossing below gives sell signals.
By tuning the MA period combinations, the strategy can adjust the timeframe of trends to capture. Shorter MA combos target short-term oscillations while longer MA combos filter out noise and focus on longer-term trends only.
The strategy also incorporates risk management modules including take profit, stop loss and trailing stop loss. These help limit the max profit/loss of individual trades and contain overall risk.
The double MA strategy has the following edges:
There are also some risks to consider:
These weaknesses can be alleviated via optimizations like filtering signals, trailing stop loss etc.
The strategy can be enhanced in aspects like:
Significant lift in win rate, risk-adjusted returns is expected from these augmentations.
Overall, the dual moving average crossover strategy offers simplicity, flexibility and controllable risks. Its ease of implementation and optimization makes it an ideal initial quant strategy. With recurrent testing and tuning, it has the credentials to evolve into a robust system over time.
/*backtest start: 2022-12-10 00:00:00 end: 2023-06-16 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=3 strategy(title = "Silent Trader Strategy", shorttitle = "Silent Trader", overlay = true, pyramiding = 0, default_qty_type = strategy.cash, default_qty_value = 1000, commission_value = 0.0675, initial_capital = 1000, currency = currency.USD, calc_on_order_fills = true, calc_on_every_tick = true) maFastSource = input(defval = ohlc4, title = "Fast MA Source") maFastLength = input(defval = 15, title = "Fast MA Period", minval = 1) maSlowSource = input(defval = ohlc4, title = "Slow MA Source") maSlowLength = input(defval = 21, title = "Slow MA Period", minval = 1) tradeInvert = input(defval = false, title = "Invert Trade Direction?") inpTakeProfit = input(defval = 100, title = "Take Profit percentage(0.1%)", minval = 0) inpStopLoss = input(defval = 100, title = "Stop Loss", minval = 0) inpTrailStop = input(defval = 0, title = "Trailing Stop Loss", minval = 0) inpTrailOffset = input(defval = 0, title = "Trailing Stop Loss Offset", minval = 0) useTakeProfit = inpTakeProfit >= 1 ? inpTakeProfit : na useStopLoss = inpStopLoss >= 1 ? inpStopLoss : na useTrailStop = inpTrailStop >= 1 ? inpTrailStop : na useTrailOffset = inpTrailOffset >= 1 ? inpTrailOffset : na useTimeLimit = input(defval = true, title = "Use Start Time Limiter?") startYear = input(defval = 2018, title = "Start From Year", minval = 0, step = 1) startMonth = input(defval = 05, title = "Start From Month", minval = 0,step = 1) startDay = input(defval = 01, title = "Start From Day", minval = 0,step = 1) startHour = input(defval = 00, title = "Start From Hour", minval = 0,step = 1) startMinute = input(defval = 00, title = "Start From Minute", minval = 0,step = 1) startTimeOk() => inputTime = timestamp(syminfo.timezone, startYear, startMonth, startDay, startHour, startMinute) timeOk = time > inputTime ? true : false r = (useTimeLimit and timeOk) or not useTimeLimit maFast = ema(maFastSource, maFastLength) maSlow = sma(maSlowSource, maSlowLength) fast = plot(maFast, title = "Fast MA", color = #26A69A, linewidth = 1, style = line, transp = 50) slow = plot(maSlow, title = "Slow MA", color = #EF5350, linewidth = 1, style = line, transp = 50) aboveBelow = maFast >= maSlow ? true : false tradeDirection = tradeInvert ? aboveBelow ? false : true : aboveBelow ? true : false if( startTimeOk() ) enterLong = not tradeDirection[1] and tradeDirection exitLong = tradeDirection[1] and not tradeDirection strategy.entry( id = "Long", long = true, when = enterLong ) //strategy.close( id = "Long", when = exitLong ) enterShort = tradeDirection[1] and not tradeDirection exitShort = not tradeDirection[1] and tradeDirection strategy.entry( id = "Short", long = false, when = enterShort ) //strategy.close( id = "Short", when = exitShort ) strategy.exit("Exit Long", from_entry = "Long", profit = close * useTakeProfit / 1000 / syminfo.mintick, loss = close * useStopLoss / 1000 / syminfo.mintick, trail_points = close * useTrailStop / 1000 / syminfo.mintick, trail_offset = close * useTrailOffset / 1000 / syminfo.mintick) strategy.exit("Exit Short", from_entry = "Short", profit = close * useTakeProfit / 1000 / syminfo.mintick, loss = close * useStopLoss / 1000 / syminfo.mintick, trail_points = close * useTrailStop / 1000 / syminfo.mintick, trail_offset = close * useTrailOffset / 1000 / syminfo.mintick)