Dual Moving Average Crossover Trend-Following Strategy with Advanced Risk Management System

SMA CROSSOVER TRAILING STOP LOSS risk management POSITION SIZING Risk-Reward Ratio TAKE PROFIT STOP LOSS
Created on: 2025-06-12 13:18:26 Modified on: 2025-06-12 13:18:26
Copy: 1 Number of hits: 302
avatar of ianzeng123 ianzeng123
2
Follow
319
Followers

 Dual Moving Average Crossover Trend-Following Strategy with Advanced Risk Management System  Dual Moving Average Crossover Trend-Following Strategy with Advanced Risk Management System

Strategy Overview

The Dual Moving Average Crossover Trend-Following Strategy is a quantitative trading system that combines technical analysis with comprehensive risk management. The core of this strategy utilizes the crossover signals between a Fast Simple Moving Average (Fast SMA) and a Slow Simple Moving Average (Slow SMA) to identify market trend changes, while implementing multiple risk control mechanisms to ensure capital preservation. The strategy is implemented on the Pine Script platform and is applicable to trend-following trading across various instruments.

Strategy Principles

This strategy bases trading decisions on the interaction between two simple moving averages:

  1. Signal Generation Mechanism:

    • Long Entry: When the Fast SMA (default 24 periods) crosses above the Slow SMA (default 48 periods)
    • Short Entry: When the Fast SMA crosses below the Slow SMA
    • Exit Signal: When an opposite crossover signal occurs
  2. Execution Timing Control: All trading decisions are executed at the close of the candle, avoiding look-ahead bias and ensuring the reliability and authenticity of backtest results.

  3. Money Management System:

    • Per-Trade Risk Control: By default, maximum risk is limited to 2.0% of total account equity per trade
    • Automatic Position Sizing: Dynamically adjusted based on stop-loss distance and risk amount, ensuring predefined risk limits are not exceeded
  4. Multi-Level Risk Control:

    • Fixed Stop Loss: Immediately sets a fixed percentage stop loss (default 0.8%) upon entry, limiting single-trade losses
    • Take Profit Target: Automatically calculated based on risk-reward ratio (default 2.0), for example, a 0.8% stop loss with a 2.0 risk-reward ratio results in a 1.6% profit target
    • Advanced Trailing Stop Loss:
      • Activation Condition: Activated when profit reaches a preset percentage (default 1.0%)
      • Trailing Mechanism: Once activated, the stop price trails the highest price (for long positions) or lowest price (for short positions), maintaining a specified distance (default 0.5%)
      • Safety Guarantee: Ensures the trailing stop never falls below the initial stop loss level, protecting capital while allowing profits to continue growing

This strategy captures trends through moving average crossovers and employs comprehensive risk management measures to ensure trading safety and sustainability.

Strategy Advantages

  1. Robust Trend Identification Mechanism:

    • The dual moving average crossover system, as a classic trend-following indicator, has historically validated effectiveness and stability
    • By adjusting fast and slow moving average periods, it can adapt to different market environments and timeframe trend characteristics
  2. Precise Money Management:

    • Dynamic risk allocation based on account equity ensures that each trade’s risk remains within a controllable range
    • Position size automatically adjusts according to actual stop loss distance, avoiding excessive leverage or undersized position issues
    • The system includes built-in safety check mechanisms to prevent calculation errors in extreme situations
  3. Multi-Level Risk Protection:

    • Fixed stop loss provides basic protection, limiting maximum loss magnitude
    • Profit target setting based on risk-reward ratio ensures average gains exceed average losses
    • Advanced trailing stop loss mechanism protects realized profits while not affecting potential returns from trend continuation
  4. Trade Execution Timing Control:

    • All trading decisions are strictly based on candle closing prices, avoiding look-ahead bias
    • Uses the process_orders_on_close=true parameter to ensure order processing complies with real trading environments
    • Trading logic is calculated based on the previous candle’s signals, avoiding the use of future data
  5. Adaptive Trailing Stop Loss System:

    • Trailing stop loss is only activated after the trade reaches a preset profit level, avoiding premature triggering
    • Stop loss levels automatically adjust with price movements, locking in partial profits while allowing trends to continue developing
    • Built-in protection mechanisms ensure trailing stops never fall below initial stop loss levels, providing continuous risk protection

Strategy Risks

  1. Trend Identification Lag:

    • Moving averages are inherently lagging indicators and may not respond quickly enough at trend reversal points
    • In oscillating markets, they may produce frequent false signals, leading to “whipsaw” effects
    • Mitigation: Consider adding additional filtering conditions, such as volatility indicators or trend strength confirmation
  2. Fixed Parameter Adaptability Issues:

    • The default SMA periods (24 and 48) may have varying effectiveness in different markets and timeframes
    • Fixed percentage settings for stop loss and profit targets may not be suitable for all volatility environments
    • Mitigation: Recommend adjusting parameters based on the specific characteristics and historical volatility of the trading instrument, or introducing adaptive parameter mechanisms
  3. Trailing Stop Loss Activation Timing:

    • Setting the profit level to activate trailing stops (default 1.0%) too high may cause missed opportunities to lock in profits
    • Setting it too low may trigger too early, limiting potential profits
    • Mitigation: Set trailing stop parameters based on the Average True Range (ATR) ratio of the target instrument, making it more adaptive
  4. Money Management Risks:

    • For extremely low-volatility instruments, fixed percentage stop losses may result in oversized positions
    • In extreme market conditions (such as gaps or flash crashes), execution may not occur at preset stop loss prices
    • Mitigation: Consider setting maximum position limits, or dynamically adjusting risk parameters based on volatility indicators (such as ATR)
  5. Technical Implementation Limitations:

    • Alternative logic when stop loss percentage is set to zero or negative may lead to unexpected risks
    • The strategy does not account for trading fees and slippage effects on actual performance
    • Mitigation: Improve error handling logic, add more safety checks, and incorporate trading costs in backtesting

Strategy Optimization Directions

  1. Signal Generation Mechanism Optimization:

    • Introduce adaptive moving average periods: Dynamically adjust fast and slow moving average periods based on market volatility, improving adaptability to different market environments
    • Add auxiliary confirmation indicators: Combine with Relative Strength Index (RSI), Stochastic, or MACD indicators to filter low-quality signals
    • Consider price structure analysis: Integrate support/resistance, price pattern recognition, and other factors to improve signal quality
  2. Risk Management System Enhancement:

    • Volatility-adaptive stop loss: Dynamically set stop loss distances based on volatility indicators like ATR, rather than fixed percentages
    • Multi-stage trailing stop loss strategy: Implement multiple levels of trailing stops, gradually tightening the trailing distance as profits increase
    • Maximum drawdown control: Add risk adjustment mechanisms based on account maximum drawdown ratio, automatically reducing risk in adverse market environments
  3. Entry Optimization:

    • Trend strength filtering: Execute trade signals only when trend strength reaches a certain threshold
    • Volatility window screening: Execute trades in appropriate volatility environments, avoiding excessively volatile or insufficiently volatile markets
    • Optimal execution price: Research optimal entry timing and price levels after signal generation
  4. Backtesting and Evaluation Framework:

    • Multi-timeframe consistency: Verify strategy consistency and robustness across different timeframes
    • Sensitivity analysis: Comprehensively test the impact of parameter changes on strategy performance, finding the most stable parameter combinations
    • Monte Carlo simulation: Evaluate strategy probability distribution and robustness through randomized trading results
  5. Technical Implementation Improvements:

    • Improve error handling: Enhance edge case processing to ensure strategy stability in various market environments
    • Add performance metric monitoring: Real-time tracking of key performance indicators such as Sharpe ratio and maximum drawdown
    • Strategy state visualization: Improve graphical interface to intuitively display strategy status, positions, and risk levels

Conclusion

The Dual Moving Average Crossover Trend-Following Strategy is a complete trading system that combines classic technical analysis methods with modern risk management concepts. Its core strengths lie in its clear trend identification mechanism and multi-level risk control system, particularly its refined money management and advanced trailing stop loss mechanism, which provide the strategy with good risk-adjusted return potential.

However, the strategy also faces challenges such as the inherent lag of moving averages and parameter adaptability issues. By introducing adaptive parameters, enhancing signal filtering mechanisms, and improving the risk management system, strategy performance can be further enhanced.

Overall, this is a well-structured, logically clear quantitative strategy framework suitable as a foundation for medium to long-term trend-following systems, particularly applicable to markets with distinct trend characteristics. For traders, understanding and mastering its risk management philosophy is more important than simply copying strategy parameters, which is the most valuable aspect of this strategy.

Strategy source code
/*backtest
start: 2025-06-04 00:00:00
end: 2025-06-11 00:00:00
period: 5m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
strategy(title="Dual SMA Crossover Strategy", overlay=true, calc_on_every_tick=false, process_orders_on_close=true)

// --- Inputs ---
// SMA Lengths
fast_length = input.int(24, title="Fast SMA Length", minval=1)
slow_length = input.int(48, title="Slow SMA Length", minval=1)

// Risk Management
risk_per_trade_percent = input.float(2.0, title="Risk Per Trade (%)", minval=0.1, maxval=10.0, step=0.1) // % of equity to risk per trade
stop_loss_percent = input.float(0.8, title="Stop Loss (%)", minval=0.1, step=0.1) // % from entry price
risk_reward_ratio = input.float(2.0, title="Risk-Reward Ratio", minval=0.5, step=0.1) // 2.0 = 2R, 3.0 = 3R etc.

// Advanced Trailing Stop Loss
trailing_start_percent = input.float(1.0, title="Trailing Stop Start (%)", minval=0.1, step=0.1) // % profit to activate TSL
trailing_stop_percent = input.float(0.5, title="Trailing Stop Trail (%)", minval=0.1, step=0.1) // % to trail by once activated

// --- Calculations ---
// Calculate SMAs
fast_sma = ta.sma(close, fast_length)
slow_sma = ta.sma(close, slow_length)

// Plot SMAs on chart
plot(fast_sma, color=color.blue, title="Fast SMA")
plot(slow_sma, color=color.red, title="Slow SMA")

// Crossover conditions (calculated on previous bar to prevent look-ahead bias)
long_condition = ta.crossover(fast_sma[1], slow_sma[1])
short_condition = ta.crossunder(fast_sma[1], slow_sma[1])

// --- Money Management and Position Sizing ---
// Calculate account equity and risk amount
account_equity = strategy.initial_capital + strategy.netprofit
risk_amount = account_equity * (risk_per_trade_percent / 100)

// Calculate Stop Loss price based on entry and SL percentage
var float long_stop_price = na
var float short_stop_price = na
var float long_take_profit_price = na
var float short_take_profit_price = na

// --- Trailing Stop Loss Variables ---
var float trailing_long_activated_price = na // Price at which TSL is activated for long
var float trailing_short_activated_price = na // Price at which TSL is activated for short
var float current_trailing_stop_long = na
var float current_trailing_stop_short = na
var bool  is_long_trailing_active = false
var bool  is_short_trailing_active = false

// --- Strategy Entry and Exit Orders ---
if long_condition
    // Reset TSL variables for a new entry
    trailing_long_activated_price := na
    current_trailing_stop_long := na
    is_long_trailing_active := false

    // Calculate SL, TP for long entry
    long_stop_price := close * (1 - stop_loss_percent / 100) // SL below entry
    long_take_profit_price := close * (1 + (stop_loss_percent * risk_reward_ratio) / 100) // TP above entry based on RRR

    // Calculate position size for long entry
    price_change_per_unit = close * (stop_loss_percent / 100)
    if price_change_per_unit > 0
        long_quantity = risk_amount / price_change_per_unit
        strategy.entry("Long", strategy.long, qty=long_quantity, comment="Buy Signal")
    else
        strategy.entry("Long", strategy.long, comment="Buy Signal (Risk calculation skipped)") // Fallback if SL is 0 or negative

if short_condition
    // Reset TSL variables for a new entry
    trailing_short_activated_price := na
    current_trailing_stop_short := na
    is_short_trailing_active := false

    // Calculate SL, TP for short entry
    short_stop_price := close * (1 + stop_loss_percent / 100) // SL above entry
    short_take_profit_price := close * (1 - (stop_loss_percent * risk_reward_ratio) / 100) // TP below entry based on RRR

    // Calculate position size for short entry
    price_change_per_unit = close * (stop_loss_percent / 100)
    if price_change_per_unit > 0
        short_quantity = risk_amount / price_change_per_unit
        strategy.entry("Short", strategy.short, qty=short_quantity, comment="Sell Signal")
    else
        strategy.entry("Short", strategy.short, comment="Sell Signal (Risk calculation skipped)") // Fallback if SL is 0 or negative

// --- Stop Loss, Take Profit, Trailing Stop Logic ---

// Long position management
if strategy.position_size > 0 // We are in a long position
    entry_price = strategy.opentrades.entry_price(0)
    current_profit_percent = ((close - entry_price) / entry_price) * 100

    // Initial SL and TP set at entry
    strategy.exit("Exit Long", from_entry="Long", stop=long_stop_price, limit=long_take_profit_price, comment="TP/SL Long")

    // Check for Trailing Stop activation
    if not is_long_trailing_active and current_profit_percent >= trailing_start_percent
        is_long_trailing_active := true
        // Set initial trailing stop when activated
        trailing_long_activated_price := high // Or close, depending on preference
        current_trailing_stop_long := high * (1 - trailing_stop_percent / 100)

    // If trailing stop is active, update it
    if is_long_trailing_active
        // Only move the trailing stop up (for long positions)
        potential_new_stop = high * (1 - trailing_stop_percent / 100)
        current_trailing_stop_long := math.max(current_trailing_stop_long, potential_new_stop)

        // Ensure trailing stop is not below the initial long_stop_price
        // This prevents the trailing stop from being less protective than the initial SL if the price drops after activation.
        current_trailing_stop_long := math.max(current_trailing_stop_long, long_stop_price)

        strategy.exit("Trailing Exit Long", from_entry="Long", stop=current_trailing_stop_long, comment="Trailing SL Long")

// Short position management
if strategy.position_size < 0 // We are in a short position
    entry_price = strategy.opentrades.entry_price(0)
    current_profit_percent = ((entry_price - close) / entry_price) * 100

    // Initial SL and TP set at entry
    strategy.exit("Exit Short", from_entry="Short", stop=short_stop_price, limit=short_take_profit_price, comment="TP/SL Short")

    // Check for Trailing Stop activation
    if not is_short_trailing_active and current_profit_percent >= trailing_start_percent
        is_short_trailing_active := true
        // Set initial trailing stop when activated
        trailing_short_activated_price := low // Or close, depending on preference
        current_trailing_stop_short := low * (1 + trailing_stop_percent / 100)

    // If trailing stop is active, update it
    if is_short_trailing_active
        // Only move the trailing stop down (for short positions)
        potential_new_stop = low * (1 + trailing_stop_percent / 100)
        current_trailing_stop_short := math.min(current_trailing_stop_short, potential_new_stop)

        // Ensure trailing stop is not above the initial short_stop_price
        current_trailing_stop_short := math.min(current_trailing_stop_short, short_stop_price)

        strategy.exit("Trailing Exit Short", from_entry="Short", stop=current_trailing_stop_short, comment="Trailing SL Short")

// Plot background color to indicate active position (optional)
bgcolor(strategy.position_size > 0 ? color.new(color.green, 90) : na, title="Long Position Background")
bgcolor(strategy.position_size < 0 ? color.new(color.red, 90) : na, title="Short Position Background")