Crossing Averages

A candlestick stock chart of the S&P 500 Index showing hourly data, with indicators for buy and sell signals. The chart includes moving averages, marked with buy and sell annotations, and price levels on the right axis.

Introduction

We are looking in this strategy to use the power of moving averages (simple moving average & exponential moving average) to identify a current instrument trend. prices in an bullish trend tend to take small upward steps before taking more aggressive price increases. For a bearish trend, prices take small downward steps before making more aggressive price decreases.

The moving averages tend to identify price trends as they take into account current bear price and also past bar closing prices. The smaller the moving average period value, the shorter time frame is taken into account when calculating moving average. For this, a moving average with a larger time frame (slower) will indicate a trend on the longer term. And a moving average with a smaller time frame (shorter) will indicate a trend on the short term.

Usage

To identify a short term trend in relation to long term trend (or a long term sideways), we then use the intersection of one short term moving average (identify short term trend) with a long term moving average (identify long term trend or sideways).

When the faster moving average crosses bullish a slower moving average, it’s an identification of a current bullish trend. This is then a signal to buy a security (or take long position). When the intersection is bearish, it’s an identification of a bearish trend. It’s therefore a signal to sell a security (or take a short position).

Typical values for faster and slower moving averages are 14 and 26.

Snippet
//@version=6
 
strategy("EMA Crossover Strategy", overlay=true, pyramiding=0) // Added pyramiding=0 to prevent multiple entries in the same direction
 
 
 
// Define EMA lengths
 
ema1Length = input.int(12, title="Fast EMA Length", minval=1)
 
ema2Length = input.int(26, title="Slow EMA Length", minval=1)
 
 
 
// Calculate EMAs
 
ema1 = ta.ema(close, ema1Length)
 
ema2 = ta.ema(close, ema2Length)
 
 
 
// Plot EMAs on the chart
 
plot(ema1, color=color.blue, title="Fast EMA")
 
plot(ema2, color=color.red, title="Slow EMA")
 
 
 
// Determine crossover conditions
 
crossUp = ta.crossover(ema1, ema2)
 
crossDown = ta.crossunder(ema1, ema2)
 
 
 
// --- Label Management Variables ---
 
var label longEntryLabel = na
 
var label shortEntryLabel = na
 
var label longExitLabel = na
 
var label shortExitLabel = na
 
 
 
// Strategy entry and exit logic to ensure only one position is open at a time (either long or short)
 
if crossUp
 
// If currently in a short position, check for profitability before closing and reversing
 
if strategy.position_size < 0
 
// Check if the current short trade is profitable
 
isShortProfitable = close < strategy.opentrades.entry_price(0)
 
 
 
if isShortProfitable
 
strategy.close("Sell") // Close the existing short position
 
// Delete old short entry label if it exists
 
if not na(shortEntryLabel)
 
label.delete(shortEntryLabel)
 
// Create a new "Sell Short" (exit from short) label
 
shortExitLabel := label.new(bar_index, high, "Sell Short", xloc.bar_index, yloc.abovebar, color.red)
 
 
 
strategy.entry("Buy", strategy.long) // Enter a new long position
 
// Delete old long exit label if it exists
 
if not na(longExitLabel)
 
label.delete(longExitLabel)
 
// Create a new "Buy Long" (entry to long) label
 
longEntryLabel := label.new(bar_index, low, "Buy Long", xloc.bar_index, yloc.belowbar, color.green)
 
 
 
// If currently flat (no position), enter a long position
 
else if strategy.position_size == 0
 
strategy.entry("Buy", strategy.long)
 
// Delete old long exit label if it exists
 
if not na(longExitLabel)
 
label.delete(longExitLabel)
 
// Create a new "Buy Long" (entry to long) label
 
longEntryLabel := label.new(bar_index, low, "Buy Long", xloc.bar_index, yloc.belowbar, color.green)
 
 
 
if crossDown
 
// If currently in a long position, check for profitability before closing and reversing
 
if strategy.position_size > 0
 
// Check if the current long trade is profitable
 
isLongProfitable = close > strategy.opentrades.entry_price(0)
 
 
 
if isLongProfitable
 
strategy.close("Buy") // Close the existing long position
 
// Delete old long entry label if it exists
 
if not na(longEntryLabel)
 
label.delete(longEntryLabel)
 
// Create a new "Sell Long" (exit from long) label
 
longExitLabel := label.new(bar_index, high, "Sell Long", xloc.bar_index, yloc.abovebar, color.red)
 
 
 
strategy.entry("Sell", strategy.short) // Enter a new short position
 
// Delete old short exit label if it exists
 
if not na(shortExitLabel)
 
label.delete(shortExitLabel)
 
// Create a new "Buy Short" (entry to short) label
 
shortEntryLabel := label.new(bar_index, low, "Buy Short", xloc.bar_index, yloc.belowbar, color.green) // Changed to green for entry
 
 
 
// If currently flat (no position), enter a short position
 
else if strategy.position_size == 0
 
strategy.entry("Sell", strategy.short)
 
// Delete old short exit label if it exists
 
if not na(shortExitLabel)
 
label.delete(shortExitLabel)
 
// Create a new "Buy Short" (entry to short) label
 
shortEntryLabel := label.new(bar_index, high, "Buy Short", xloc.bar_index, yloc.abovebar, color.red) // Changed to red for short entry
 
 
 
// Optional: Plot buy/sell signals on the chart
 
plotshape(crossUp, title="Buy Signal", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)
 
plotshape(crossDown, title="Sell Signal", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)