
The Dynamic Moving Average Crossover Trend Following and Reversal Strategy is a quantitative trading system based on the relationship between price and moving averages. This strategy determines trading signals by judging the direction of moving averages and price breakouts, with dynamic profit-taking and stop-loss mechanisms. Its core philosophy is to go long in uptrends, short in downtrends, and manage risk through precise entry and exit rules, thereby achieving better performance than simple buy-and-hold in volatile markets.
This strategy is designed based on the following core principles:
Dynamic Trend Determination Mechanism: The strategy uses the directional change of moving averages (optional SMA, EMA, or VWMA) to judge market trends. When the moving average rises above a set threshold (default 0.25%), it is determined to be an uptrend; when it falls below the same threshold, it is determined to be a downtrend.
Precise Entry Conditions:
Multi-level Exit Mechanism:
Time Filtering: The strategy integrates trading session filtering, defaulting to trading only between 9:30 and 15:15, avoiding volatility impacts during non-trading hours.
Backtest Time Range: Users can customize the start and end dates for backtesting, facilitating strategy evaluation under different market conditions.
After in-depth analysis, this strategy has the following significant advantages:
Adaptability to Market Environments: Through dynamic moving average direction judgment, the strategy can automatically adjust trading direction according to market trends, adapting to different market environments.
Fine-tuned Risk Control: The strategy has designed multi-level risk control mechanisms, including trend filtering, retracement exits, moving average crossover exits, and hard stop-losses, effectively preventing significant losses.
Adjustable Sensitivity: By adjusting the type of moving average (SMA/EMA/VWMA), calculation basis (closing price/OHLC/4, etc.), and length parameters, users can optimize the strategy’s sensitivity to market fluctuations.
Diversified Entry Opportunities: The strategy not only provides main breakthrough entry signals but also includes pullback re-entry mechanisms, increasing trading opportunities and optimizing average entry prices.
Visualized Trading Status: The code integrates trading status labels and entry/exit markers, intuitively displaying strategy execution for analysis and optimization.
Complete Alert System: Built-in trading signal alert functions support real-time monitoring and reminders, improving strategy execution efficiency.
Despite the comprehensive design, the strategy still has the following potential risks:
False Signals in Choppy Markets: In sideways, choppy markets, the moving average direction may change frequently, leading to excessive trading and losses. The solution is to increase direction confirmation thresholds or integrate other indicators to filter signals.
Parameter Sensitivity: Strategy performance highly depends on parameter settings, such as moving average length and various threshold percentages. Different trading instruments may require different parameter settings, necessitating thorough parameter optimization.
Lack of Volume Confirmation: The current strategy is mainly based on price and moving average relationships, without considering volume factors, which may generate misleading signals in low-volume environments.
Gap Risk Due to Trading Session Restrictions: The strategy is limited to trading in specific sessions, potentially unable to respond to major market changes overnight or outside trading hours, especially in price gap situations.
Lagged Response to Trend Reversals: Although there is a dynamic trend judgment mechanism, the response to sudden drastic trend reversals may lag, potentially causing larger drawdowns in rapidly reversing markets.
Based on code analysis, the strategy can be optimized in the following directions:
Integrate Momentum Indicators: Incorporate momentum indicators such as RSI and MACD into the signal confirmation system to improve trend judgment accuracy and reduce false signals. This is because pure price breakouts may sometimes lead to misjudgments, while momentum indicators can provide additional confirmation.
Add Adaptive Volatility Components: Dynamically adjust entry thresholds and stop-loss ranges based on market volatility, increasing threshold requirements in high-volatility environments to reduce trigger frequency; lowering thresholds in low-volatility environments to increase sensitivity.
Add Volume Filtering: Introduce volume confirmation mechanisms, requiring price breakouts to be accompanied by increased volume, filtering weak breakthrough signals in low-volume environments.
Position Size Optimization: Dynamically adjust position sizes based on trading performance, drawdown magnitude, and win rates, increasing positions on high-conviction signals and reducing positions in high-uncertainty situations.
Timeframe Synthesis: Combine signals from multiple timeframes, such as requiring daily and hourly trends to be consistent before trading, enhancing system robustness.
Partial Position Building and Closing Strategy: Implement mechanisms for partial entry and exit to avoid single-point entry risks while protecting profits through partial profit-taking.
The Dynamic Moving Average Crossover Trend Following and Reversal Strategy is an elegantly designed trading system that provides traders with a systematic tool to handle market volatility through dynamic trend judgment, flexible entry conditions, and multi-level risk management. Its greatest feature is combining the advantages of trend following and pullback entries, controlling risk through precise entry points while respecting the larger trend.
This strategy is particularly suitable for markets with medium to long-term volatility. Traders can optimize the strategy for different trading instruments by adjusting the type of moving average, length, and various threshold parameters. Although there are risks such as parameter sensitivity and false signals in choppy markets, the strategy’s robustness and adaptability can be further enhanced through the suggested optimization directions, such as integrating momentum indicators, volatility adjustments, and multi-timeframe confirmations.
Overall, this strategy provides traders with a structured quantitative trading framework that has the potential to achieve better risk-adjusted returns than traditional buy-and-hold under correct parameter configuration and appropriate risk management.
/*backtest
start: 2024-04-29 00:00:00
end: 2024-07-27 00:00:00
period: 2h
basePeriod: 2h
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/
//@version=6
// @ipuneetg
strategy("PG MA Crossover Buy and Sell Options Special", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
// === INPUTS ===
maType = input.string("SMA", title="Select MA Type", options=["SMA", "EMA", "VWMA"])
calcBasis = input.string("close", title="Calculation Basis", options=["close", "OHLC/4", "HLC/3", "HLCC/4"])
maLength = input.int(21, title="Moving Average Length")
reversalThresholdPercent = input.float(0.25, title="Reversal Threshold (%)", step=0.01)
percentBelowTop = input.float(1.0, title="Exit % Below Top (%)", step=0.1, minval=0.1)
shortProfitPercent = input.float(0.5, title="Short Profit Protection (%)", minval=0.1, step=0.1)
stopLossPercent = input.float(1.5, title="Stop Loss % Above Entry (for Shorts)", step=0.1, minval=0.1)
allowShorts = input.bool(true, title="Allow Short Trades?")
// === SESSION SETTINGS ===
startHour = input.int(9, title="Trade Start Hour")
startMinute = input.int(30, title="Start Minute")
endHour = input.int(15, title="Trade End Hour")
endMinute = input.int(15, title="End Minute")
tradeSession = str.tostring(startHour, "00") + str.tostring(startMinute, "00") + "-" + str.tostring(endHour, "00") + str.tostring(endMinute, "00")
sessionActive = not na(time(timeframe.period, tradeSession))
// === PRICE BASIS ===
basis = switch calcBasis
"OHLC/4" => (open + high + low + close) / 4
"HLC/3" => (high + low + close) / 3
"HLCC/4" => (high + low + close + close) / 4
=> close
// === MOVING AVERAGE ===
ma = switch maType
"SMA" => ta.sma(basis, maLength)
"EMA" => ta.ema(basis, maLength)
"VWMA" => ta.vwma(basis, maLength)
// === DYNAMIC REVERSAL DETECTION ===
var float lastReversal = na
var bool isRising = true
thresholdValue = ma * reversalThresholdPercent / 100
if na(lastReversal)
lastReversal := ma
if ma > lastReversal + thresholdValue
isRising := true
lastReversal := ma
else if ma < lastReversal - thresholdValue
isRising := false
lastReversal := ma
maColor = isRising ? color.green : color.red
// === TRADE VARIABLES ===
var float tradeHigh = na
var float tradeLow = na
var float shortEntryPrice = na
var bool inLong = false
var bool inShort = false
// === LONG & SHORT CONDITIONS ===
longEntry = sessionActive and isRising and close >= ma * (1 + reversalThresholdPercent / 100)
longReEntry = sessionActive and isRising and not inLong and close <= ma * 1.01
shortEntry = sessionActive and not isRising and close <= ma * (1 - reversalThresholdPercent / 100)
shortReEntry = sessionActive and not inShort and close >= ma * 0.998
// === EXIT CONDITIONS ===
exitLongBelowTop = close < tradeHigh * (1 - percentBelowTop / 100)
exitLongBelowMA = close < ma
exitShortAboveTop = close > tradeHigh * (1 + percentBelowTop / 100)
exitShortAboveMA = close > ma
// === EXECUTE TRADES ===
// === LONG SIDE ===
if not inLong and (longEntry or longReEntry)
strategy.entry("Long", strategy.long)
tradeHigh := close
inLong := true
if inLong
tradeHigh := math.max(tradeHigh, high)
if exitLongBelowTop or exitLongBelowMA
strategy.close("Long")
reason = exitLongBelowTop ? "Exit Long (Below Top)" : "Exit Long (Below MA)"
inLong := false
// === SHORT SIDE ===
if allowShorts
if not inShort and (shortEntry or shortReEntry)
if close >= ma * 0.996 and close <= ma * 1.002
strategy.entry("Short", strategy.short)
tradeHigh := close
tradeLow := close
shortEntryPrice := close
inShort := true
if inShort
// Update tradeLow dynamically
tradeLow := na(tradeLow) ? close : math.min(tradeLow, close)
// Calculate Stop Levels
hardStopLossPrice = shortEntryPrice * (1 + stopLossPercent / 100)
hardStopLossTriggered = high >= hardStopLossPrice
normalExitPrice1 = tradeLow * (1 + shortProfitPercent / 100)
normalExitTriggered = close > normalExitPrice1 or close > ma
// Exit Conditions
if hardStopLossTriggered
strategy.close("Short", comment="Hard Stop Loss")
inShort := false
tradeLow := na
else
if normalExitTriggered
reason = close > normalExitPrice1 ? "Exit Short (Above Profit %)" : "Exit Short (Above MA)"
strategy.close("Short", comment=reason)
inShort := false
tradeLow := na
// === PLOT MA ===
plot(ma, color=maColor, title="Dynamic Moving Average", linewidth=2)
// === TRADE STATUS BOX ===
var label tradeStatusLabel = na
var color statusColor = color.blue
var string statusText = "No Open Trade"
if inLong
statusColor := color.green
statusText := "Long Trade Open"
else if inShort
statusColor := color.red
statusText := "Short Trade Open"
if not na(tradeStatusLabel)
label.delete(tradeStatusLabel)