Pine Script Signal Detection

Pine Script Crossover: How to Code ta.crossover() Signals and Rules

In Pine Script, ta.crossover(source1, source2) checks if the first series has crossed over the second series. It returns true if on the current bar source1 is strictly greater than source2, and on the previous bar source1 was less than or equal to source2. A valid crossing requires the relevant current and preceding values; missing data does not establish a crossing.

Build Crossover Strategies with AI

Understanding ta.crossover syntax and behavior in Pine Script v6

ta.crossover() compares the ordering of two values now and on the preceding bar. It accepts numeric series or fixed levels. The event is not the same as remaining above a level, and it is not inherently a profitable entry.

Function expressionCondition required for truePrimary use caseCommon pitfall
ta.crossover(fastMa, slowMa)fastMa > slowMa and fastMa[1] <= slowMa[1]Golden Cross trend entriesLagging entries during range-bound chop
ta.crossover(rsi, 30)rsi > 30 and rsi[1] <= 30Oversold rebound exits and reversalsPremature long entry before trend exhaustion
ta.crossover(close, upperBand)close > upperBand and close[1] <= upperBand[1]Crossing a defined upper bandA Donchian upper bound including the current high cannot be crossed by the same bar close; define the reference window explicitly
ta.crossunder(source1, source2)source1 < source2 and source1[1] >= source2[1]Death Cross exits and short entriesConfusing argument order (x vs y)

Complete Pine Script v6 dual moving average crossover strategy

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)

Choose signal timing and inspect data dependencies

A crossover can be true on an open bar and false by its close. Confirmation chooses the closing decision; it does not make every losing signal disappear. Create an alert for alert() calls to receive the example signal messages, or choose strategy order-fill events for simulated fills. Recreate alerts after code or input changes.

  • Confirm on bar close: For indicators, check barstate.isconfirmed alongside ta.crossover() before emitting alerts to prevent ghost signals.
  • A trend filter changes which signals qualify. Compare its effects under fixed test assumptions; it does not guarantee better results.
  • For confirmed higher-timeframe data, use a previous-bar expression with lookahead_on together. lookahead_off alone can still expose developing realtime HTF values that change after reload.
  • Handling identical values: If two series touch without crossing, ta.crossover returns false because the current bar must strictly exceed the target series.

Comparing ta.crossover vs manual conditional comparisons

While ta.crossover(x, y) can be written manually as x > y and x[1] <= y[1], using the built-in function provides several advantages:

  • Readability: ta.crossover makes signal intent instantly clear to any collaborator or AI agent inspecting your script.
  • Evaluate history-dependent functions consistently across bars before combining them with conditions; a built-in does not repair skipped calculations or wrong source data.
  • Check startup bars and missing data separately. Neither manual comparison nor the built-in can infer a crossing from unavailable observations.
Where Pineify fits

Pine Script AI Coding Agent

Describe crossing rules and order timing, request editable Pine code and a final syntax check, then compare the signals and simulated fills in TradingView.

Also useful: Strategy Optimizer. Explore parameter-search settings while keeping evaluation data separate. The best historical parameter pair is not a guarantee of future performance.

Build Crossover Strategies with AI

Frequently asked questions

Crossover signals depend on historical bar calculation and indicator parameters. Past backtest performance does not guarantee future market behavior. Always combine crossover logic with strict risk management.

Sources and verification