The following complete strategy script implements an exponential moving average crossover system with visual signal arrows, ATR-based bracket levels, and signal alerts. Entries reverse an opposite position. Stop and target prices are fixed from the signal close, not the eventual entry fill, so a gap changes the actual reward/risk distances. The 10% quantity is equity allocation, not risk; fees and slippage below are illustrative. No backtest performance is reported.
Pine Script v6: Dual EMA crossover trading strategypinescript
//@version=6
strategy("Dual EMA Crossover Strategy [v6]",
overlay = true,
initial_capital = 10000,
default_qty_type = strategy.percent_of_equity,
default_qty_value = 10, pyramiding = 0,
commission_type = strategy.commission.percent, commission_value = 0.1, slippage = 1,
calc_on_every_tick = false, process_orders_on_close = false)
// Input parameters
int fastPeriod = input.int(9, "Fast EMA Period", minval = 1)
int slowPeriod = input.int(21, "Slow EMA Period", minval = 1)
float atrMult = input.float(1.5, "ATR Stop Multiplier", minval = 0.5)
// Technical indicators
float fastEma = ta.ema(close, fastPeriod)
float slowEma = ta.ema(close, slowPeriod)
float atrVal = ta.atr(14)
// Crossover condition evaluation
bool longSignal = ta.crossover(fastEma, slowEma)
bool shortSignal = ta.crossunder(fastEma, slowEma)
// Plot indicator lines
plot(fastEma, "Fast EMA", color = color.blue, linewidth = 2)
plot(slowEma, "Slow EMA", color = color.orange, linewidth = 2)
// Visual shape markers
plotshape(longSignal, "Long Signal", shape.triangleup, location.belowbar, color.green, size = size.small)
plotshape(shortSignal, "Short Signal", shape.triangledown, location.abovebar, color.red, size = size.small)
// Strategy execution
if longSignal and barstate.isconfirmed and not na(atrVal)
float longStop = close - (atrVal * atrMult)
float longTarget = close + (atrVal * atrMult * 2.0)
strategy.entry("Long", strategy.long)
strategy.exit("Exit Long", from_entry = "Long", stop = longStop, limit = longTarget)
if shortSignal and barstate.isconfirmed and not na(atrVal)
float shortStop = close + (atrVal * atrMult)
float shortTarget = close - (atrVal * atrMult * 2.0)
strategy.entry("Short", strategy.short)
strategy.exit("Exit Short", from_entry = "Short", stop = shortStop, limit = shortTarget)
// Signal messages require a running alert configured for alert() calls.
if longSignal and barstate.isconfirmed
alert("Bullish EMA crossover on " + syminfo.tickerid, alert.freq_once_per_bar_close)
if shortSignal and barstate.isconfirmed
alert("Bearish EMA crossunder on " + syminfo.tickerid, alert.freq_once_per_bar_close)