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)

ThinkScript

Snippet

# EMA Crossover Strategy# Based on Pine Script v6 strategy.## This script identifies EMA crossovers and uses them to enter long or short positions.# It automatically reverses a position on an opposing signal.# # --- Strategy Inputs ---# Define the lengths for the fast and slow Exponential Moving Averages.input fastEmaLength = 12;input slowEmaLength = 26; # --- EMA Calculations ---# Calculate the fast and slow EMAs using the ExpAverage function.def fastEMA = ExpAverage(close, fastEmaLength);def slowEMA = ExpAverage(close, slowEmaLength); # --- Plotting the EMAs ---# These plots will be displayed on your chart.plot fastEmaPlot = fastEMA;fastEmaPlot.SetDefaultColor(Color.CYAN);fastEmaPlot.SetLineWeight(2); plot slowEmaPlot = slowEMA;slowEmaPlot.SetDefaultColor(Color.MAGENTA);slowEmaPlot.SetLineWeight(2); # --- Crossover Conditions ---# Use the crosses() function to detect when the fast EMA crosses above or below the slow EMA.def crossUp = crosses(fastEMA, slowEMA, CrossingDirection.ABOVE);def crossDown = crosses(fastEMA, slowEMA, CrossingDirection.BELOW); # --- Strategy Orders ---# Add a BUY order when the fast EMA crosses above the slow EMA.# This order will also automatically close any existing short position.AddOrder(OrderType.BUY_TO_OPEN, condition = crossUp, name = "Buy Entry", tradeSize = 1, tickcolor = Color.GREEN, arrowcolor = Color.GREEN); # Add a SELL order when the fast EMA crosses below the slow EMA.# This order will also automatically close any existing long position.AddOrder(OrderType.SELL_TO_OPEN, condition = crossDown, name = "Sell Entry", tradeSize = 1, tickcolor = Color.RED, arrowcolor = Color.RED); # --- Plotting Shapes and Bubbles (Optional Visuals) ---# Add a buy signal shape at the low of the candle on a cross up.plot UpArrow = if crossUp then low else Double.NaN;UpArrow.SetPaintingStrategy(PaintingStrategy.ARROW_UP);UpArrow.SetDefaultColor(Color.GREEN);UpArrow.SetLineWeight(3); # Add a sell signal shape at the high of the candle on a cross down.plot DownArrow = if crossDown then high else Double.NaN;DownArrow.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);DownArrow.SetDefaultColor(Color.RED);DownArrow.SetLineWeight(3);