Scroll Top

Moving average Crossover

 Simple Moving Average (SMA) Crossover Strategy: A Beginner's Guide to Automated Trading

Trading with moving averages is one of the fundamental strategies in technical analysis. In this guide, we'll explore how to implement and automate a Simple Moving Average (SMA) crossover strategy using TradingView's platform.

Understanding Simple Moving Averages

The Simple Moving Average (SMA) is a technical indicator that shows the average price of an asset over a specific period. For example, a 10-day moving average is calculated by adding the closing prices of the last 10 days and dividing by 10. This helps smooth out price data to reveal the overall market trend.

 The SMA Crossover Strategy

The strategy utilizes two moving averages:
- A short-term moving average (faster)
- A long-term moving average (slower)

The basic rules are straightforward:
- Sell when the short moving average crosses below the long moving average
- Buy when the short moving average crosses above the long moving average

Pros and Cons

 Advantages
- Simple and clear signals
- Adaptable to different timeframes
- Easy to automate

Disadvantages
- Can provide late signals as crosses occur after trends have started
- May generate false signals in sideways markets

Building a Simple Moving Average Crossover Strategy with Pine Script

Strategy Overview

The strategy is based on the following key components:

  • Short and Long Simple Moving Averages (SMA) crossover for entry signals
  • ATR-based dynamic stop losses
  • Configurable risk-to-reward ratios
  • Optional RSI filter for trade confirmation
  • Option to use previous candle prices for stop loss calculation
Step 1: Setting Up the Inputs

Let's start by looking at the strategy's configurable parameters:

Pyton
				shortSmaLength = input.int(defval = 20, title = 'Short SMA length')
longSmaLength = input.int(defval = 200, title = 'Long SMA length')
atrMultipleForStopLoss = input.float(defval = 2.0, title = 'ATR multiplier SL')
riskToRewardRatio = input.float(defval = 1.0, title = 'Risk To Reward')
			

These inputs allow traders to:

  • Adjust the short and long SMA periods (default 20 and 200)
  • Modify the ATR multiplier for stop loss calculation
  • Set their desired risk-to-reward ratio
  • Enable/disable RSI filtering and strategy execution
Step 2: Calculating Core Indicators

The strategy calculates three main technical indicators:

Pyton
				shortSma = ta.sma(close, shortSmaLength)
longSma = ta.sma(close, longSmaLength)
atr = ta.atr(14)
			

The ATR (Average True Range) with a 14-period setting helps determine dynamic stop loss levels based on market volatility.


Step 3: Generating Trading Signals


Trade signals are generated when the shorter SMA crosses the longer SMA:

Pyton
				longSignal = ta.crossover(shortSma, longSma)
shortSignal = ta.crossunder(shortSma, longSma)
			
  • Long entry: Short SMA crosses above Long SMA
  • Short entry: Short SMA crosses below Long SMA
Step 4: Implementing RSI Filter (Optional)

The strategy includes an optional RSI filter to avoid trading in overbought/oversold conditions:

Pyton
				rsiValue = ta.rsi(close, rsiLength)
isNeutral = rsiValue > rsiOversoldLevel and rsiValue < rsiOverboughtLevel

if filterWithRsi
    longSignal := longSignal and isNeutral
    shortSignal := shortSignal and isNeutral
			
  • When enabled, trades are only taken when the RSI is in a neutral zone (between oversold and overbought levels).

    Step 5: Stop Loss and Take Profit Calculation

    The strategy offers two methods for stop loss calculation:

    1. ATR-based:
Pyton
				StoplossValue = atr * atrMultipleForStopLoss
LongStoploss = close - StoplossValue
ShortStopLoss = close + StoplossValue
			

                  2. Previous candle based:

Pyton
				if usePreviousCandleAsSl
    LongStoploss := math.min(open, open[1], open[2])
    ShortStopLoss := math.max(open, open[1], open[2])
			

Take profit levels are calculated based on the risk-to-reward ratio:

Pyton
				TakeProfitValue = StoplossValue * riskToRewardRatio
LongTakeProfit = close + TakeProfitValue
ShortTakeProfit = close - TakeProfitValue
			
Step 6: Trade Execution

The strategy enters trades only when there’s no existing position:

Pyton
				inTrade = strategy.opentrades > 0

if longCondition and showStrategyResult
    strategy.entry('long', strategy.long)
    strategy.exit('Long_Exit', from_entry = 'long', qty_percent = 100, stop = LongStoploss, limit = LongTakeProfit)
			
Visualization

The strategy includes visual elements to help traders identify signals:

  • Green triangles for long entry signals
  • Red triangles for short entry signals
  • Blue line for short SMA
  • Red line for long SMA
Considerations and Customization
  1. Timeframe Selection: The strategy can be applied to any timeframe, but longer timeframes typically generate fewer, more reliable signals.
  2. SMA Periods: The default values (20 and 200) represent common settings, but these can be adjusted based on your trading style:
    • Shorter periods: More signals, higher sensitivity
    • Longer periods: Fewer signals, lower sensitivity
  3. Risk Management: The ATR multiplier and risk-to-reward ratio should be adjusted based on:
    • Your risk tolerance
    • The instrument’s volatility
    • Your overall trading strategy
  4. RSI Filter: Consider enabling the RSI filter in trending markets to avoid false signals in overbought/oversold conditions.

Testing Result

Our backtest results revealed interesting patterns across different timeframes:

1. Timeframe Performance:
- 4-hour and 1-hour timeframes showed consistent 60% win rates
- Weekly timeframe showed impressive 71% success rate (though with fewer trades)
- Lower timeframes (5-15 minutes) showed decreased reliability

2. Moving Average Combinations:
- Different SMA combinations (5/20, 10/50, 50/200) showed varying results
- The classic 20/200 combination proved relatively reliable

Market Applications

The strategy was tested across various markets:
- Forex (EUR/USD): ~60% success rate
- Stocks (Tesla): ~59% success rate
- Crypto (Bitcoin): ~55% success rate
- US30 Index: ~51% success rate

Risk Management Considerations

For proper implementation, consider:
- Using ATR for stop-loss placement
- Maintaining a 1:1 risk-to-reward ratio
- Only taking one trade at a time

 Conclusion

The SMA crossover strategy, while simple, can be effective when properly implemented with risk management rules. Higher timeframes tend to produce more reliable signals, though this may mean fewer trading opportunities. As with any trading strategy, it's essential to thoroughly test and adapt it to your specific trading style and risk tolerance.

Remember that past performance doesn't guarantee future results, and it's crucial to account for trading costs like spreads, commissions, and swap fees when evaluating strategy performance.

FULL SCRIPT

Pyton
				// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © tradecraftsimplified

//@version=6
strategy('SMA CrossOver strategy', overlay = true)

// ===================== Inputs ==============

shortSmaLength = input.int(defval = 20, title = 'Short SMA length')
longSmaLength = input.int(defval = 200, title = 'Long SMA length')
atrMultipleForStopLoss = input.float(defval = 2.0, title = 'ATR multiplier SL')
riskToRewardRatio = input.float(defval = 1.0, title = 'Risk To Reward')
showStrategyResult = input.bool(false, title = 'Load Strategy Result')
usePreviousCandleAsSl = input.bool(false, 'Use Previous Candle as SL')

filterWithRsi = input.bool(false, 'Filter with RSI')

// RSI Parameters
rsiLength = input.int(14, minval = 1, title = 'RSI Length')
rsiOverboughtLevel = input.int(70, title = 'Overbought Level')
rsiOversoldLevel = input.int(30, title = 'Oversold Level')

// ===================================

shortSma = ta.sma(close, shortSmaLength)
longSma = ta.sma(close, longSmaLength)
atr = ta.atr(14)

longSignal = ta.crossover(shortSma, longSma)
shortSignal = ta.crossunder(shortSma, longSma)

// Calculate RSI
rsiValue = ta.rsi(close, rsiLength)
isNeutral = rsiValue > rsiOversoldLevel and rsiValue < rsiOverboughtLevel

if filterWithRsi
    longSignal := longSignal and isNeutral
    shortSignal := shortSignal and isNeutral

StoplossValue = atr * atrMultipleForStopLoss
LongStoploss = close - StoplossValue
ShortStopLoss = close + StoplossValue

if usePreviousCandleAsSl
    LongStoploss := math.min(open, open[1], open[2])
    ShortStopLoss := math.max(open, open[1], open[2])

TakeProfitValue = StoplossValue * riskToRewardRatio
LongTakeProfit = close + TakeProfitValue
ShortTakeProfit = close - TakeProfitValue

// ===================== Plots==============

plotshape(longSignal, style = shape.triangleup, location = location.belowbar, color = color.green, size = size.small)
plotshape(shortSignal, style = shape.triangledown, location = location.abovebar, color = color.red, size = size.small)

plot(shortSma, title = 'Short SMA', color = color.blue, linewidth = 2)
plot(longSma, title = 'Short SMA', color = color.red, linewidth = 2)

// ===================================

// ===================== Strategy ==============

inTrade = strategy.opentrades > 0

longCondition = longSignal and not inTrade

if longCondition and showStrategyResult
    strategy.entry('long', strategy.long)
    strategy.exit('Long_Exit', from_entry = 'long', qty_percent = 100, stop = LongStoploss, limit = LongTakeProfit)

shortCondition = shortSignal and not inTrade
if shortCondition and showStrategyResult
    strategy.entry('short', strategy.short)
    strategy.exit('Short_Exit', from_entry = 'short', qty_percent = 100, stop = ShortStopLoss, limit = ShortTakeProfit)

// ===================================
			

Subscribe to our Newsletter

Leave a comment