Skip to content

Pine Script

ta.crossover() in Pine Script: Crossover, Crossunder and ta.cross

ta.crossover(source1, source2) in Pine Script returns true on a bar where source1 is greater than source2 and, on the previous bar, source1 was less than or equal to source2. ta.crossunder() mirrors it: less than now, greater than or equal on the previous bar. Each result is true only on the bar where the ordering changes, not while one series stays above the other.

Illustrative Pine Script crossover cover with two abstract series changing order at a single marked bar, with the official PineConnector logo.
A crossover is a change in ordering between two bars, not a lasting state.

Part of the Pine Script guide and function reference. Definitions follow the Pine Script v6 Reference Manual as of 25 September 2026.[1]

ta.crossover, ta.crossunder and ta.cross at a glance

Scroll horizontally to read every column.

Function True on the current bar when
ta.crossover(source1, source2) source1 > source2 now, and source1 <= source2 on the previous bar
ta.crossunder(source1, source2) source1 < source2 now, and source1 >= source2 on the previous bar
ta.cross(source1, source2) The reference says the two series "have crossed each other"; no direction is reported

All three share the signature pattern (source1, source2) → series bool, and both arguments are series int/float values. A source can be a price, an indicator output or a constant level such as 50.[1][2]

What does ta.crossover compare, exactly?

ta.crossover(a, b) = (a > b on this bar) AND (a <= b on the previous bar)
ta.crossunder(a, b) = (a < b on this bar) AND (a >= b on the previous bar)

The definition uses two bars and two comparisons. The current comparison is strict, so equal values on the current bar are not a crossover. The previous comparison includes equality, so a series that touches the other and then moves above it produces a crossover on the move.[1]

Argument order matters. ta.crossover(fast, slow) asks whether fast moved above slow. From the two definitions, ta.crossover(slow, fast) tests the same event as ta.crossunder(fast, slow): slow above fast now, and slow at or below fast before.

The reference gives ta.cross() only a one-line description and does not spell out its equality handling. When the exact comparisons matter, ta.crossover(a, b) or ta.crossunder(a, b) states them explicitly.[1]

Worked example: five bars, two crossings

Illustrative values, not market data. A fast series is compared with a slow series that stays at 10. Bar 1 serves only as the previous bar for bar 2.

Bar: fast vs slow Comparisons Result
2: 10 vs 10 10 > 10 and 10 < 10 are both false No crossover; no crossunder
3: 11 vs 10 11 > 10 now; 10 <= 10 before ta.crossover true
4: 12 vs 10 12 > 10 now; 11 <= 10 is false before No new crossover
5: 9 vs 10 9 < 10 now; 12 >= 10 before ta.crossunder true

Bar 1 has fast 9 and slow 10. Bar 2 is a touch, and bar 3 counts as the crossover because the previous comparison allows equality. On bar 4 the fast series is still above, but the event has already happened. A rule that means "while fast is above slow" needs fast > slow, not ta.crossover().

Illustrative five-bar ta.crossover example: a touch at 10 on bar 2, a crossover on bar 3, no new event on bar 4 and a crossunder on bar 5.
Illustrative values. Each result compares the current bar with the previous bar only.

Why can a crossover appear and then disappear?

On a realtime bar, an indicator recalculates as new prices arrive. A calculation using close, high or low, including most built-in indicators, can change until the bar closes. A crossover that is true on one update can therefore be false on the closing update.[2]

TradingView describes this as the most common repainting case for alerts. It occurs when the alert can trigger before bar close, with any frequency other than Once Per Bar Close. TradingView calls Once Per Bar Close "the simplest way" to avoid it and notes that the trade-off is immediacy.[2]

Strategies calculate at the close of realtime bars by default. With calc_on_every_tick left off, their alert() calls use bar-close frequency whatever the freq argument says.[2] The barstate.isconfirmed guide explains confirmation for indicators, and higher-timeframe requests add a separate repainting source.

How do you alert on a crossover?

Illustrative sketch; not compiled or tested. Paste into TradingView's Pine Editor. The lengths 10 and 30 are arbitrary placeholders, not recommended settings, and the messages are plain notifications.

//@version=6
indicator("Crossover events", overlay = true)
fast = ta.sma(close, 10)
slow = ta.sma(close, 30)
crossUp = ta.crossover(fast, slow)
crossDown = ta.crossunder(fast, slow)
plot(fast, "Fast SMA")
plot(slow, "Slow SMA")
plotshape(crossUp, "Cross up", shape.triangleup, location.belowbar)
plotshape(crossDown, "Cross down", shape.triangledown, location.abovebar)
alertcondition(crossUp, "Fast crossed over slow", "Fast SMA crossed over slow SMA")
alertcondition(crossDown, "Fast crossed under slow", "Fast SMA crossed under slow SMA")

Each alertcondition() call adds a named entry to the Condition list in Create Alert. Its frequency is chosen in that dialog, and its message argument must be a const string. alertcondition() works in indicators; alerts cannot be created from it in a strategy.[2][1]

The crossover values are assigned at the top level, so they are calculated on every bar. In Pine Script v6, and and or evaluate lazily. TradingView's migration guide says functions that rely on previous values should be evaluated on each bar, for example by assigning them to a global variable before combining them in a condition.[3]

The alertcondition() vs alert() comparison covers the alert() route, where the frequency is an argument and messages can be built at runtime.[2] For strategies, strategy.entry() and order fill alerts separate the crossover from the simulated fill.

What does an illustrative PineConnector message look like?

Verify on a demo account first. Before any executable test, confirm that every account sharing the License ID is a demo account, and follow the demo test guide.[5]

Illustrative message, not an instruction to trade. PineConnector's syntax reference documents this form for the TradingView alert's Message field:[4]

LicenseID,buy,EURUSD,vol_lots=0.01,sl_pips=20

Here vol_lots=0.01 requests 0.01 lot, and sl_pips=20 is a stop distance in PineConnector pips. Choose your own symbol, size and rules; the broker symbol must match exactly. As a constant string, the line could also serve as an alertcondition() message.[4][2]

A true crossover is only the first stage. The alert must trigger, the webhook must be delivered and PineConnector must process the signal. The EA then sends an order request, and the broker decides acceptance, the deal and the resulting position. The TradingView alert syntax guide covers message construction.[5]

Common ta.crossover mistakes

  • Treating the event as a state: ta.crossover() is true for one bar. Use a comparison for "is above".
  • Swapping arguments: ta.crossover(slow, fast) is the downward event for fast.
  • Intrabar alerts: a realtime crossover can vanish before close. Once Per Bar Close avoids that case, not every repainting cause.[2]
  • Conditional evaluation: compute crossovers in the global scope rather than behind a lazily evaluated and.[3]
  • Editing without replacing the alert: a created alert keeps a snapshot of the script and inputs. Delete it and create a new one after changes.[6]
  • Assuming a crossover is a strategy: the event says nothing about entries, exits, sizing or expectancy. See moving average crossover rules.

Frequently asked questions

What does ta.crossover do in Pine Script?

ta.crossover(source1, source2) returns true on a bar where source1 is greater than source2, and on the previous bar source1 was less than or equal to source2. The result is true only on the bar where the ordering changes, not on later bars where source1 simply remains above source2.

What is the difference between ta.crossover and ta.crossunder?

ta.crossover() detects the first series moving above the second; ta.crossunder() detects it moving below. Crossunder requires source1 less than source2 now and greater than or equal on the previous bar. Swapping the arguments of crossover gives the same event as crossunder with the original order.

What does ta.cross return?

ta.cross(source1, source2) returns a series bool that the Pine Script v6 reference describes as true "if two series have crossed each other". It does not report the direction. Where the exact comparison rules matter, combining ta.crossover(a, b) or ta.crossunder(a, b) makes both directions and the equality handling explicit.

Why did my crossover alert fire but no marker remains on the chart?

On a realtime bar, the crossover can be true on an intermediate price update and false at the close. An alert set to trigger before bar close can fire on that update, while the finished bar shows the final values. TradingView's alerts documentation recommends Once Per Bar Close as the simplest way to avoid this repainting case.

Reviewed 25 September 2026. Facts were checked against the linked sources on that date. Nothing in this article was tested on a trading account and no code was compiled.

Related reading

Sources

  1. TradingView – Pine Script v6 Reference Manual: ta.cross(), ta.crossover(), ta.crossunder() and alertcondition(), accessed 25 September 2026.
  2. TradingView – Alerts, accessed 25 September 2026.
  3. TradingView – To Pine Script version 6: lazy evaluation of conditions, accessed 25 September 2026.
  4. PineConnector – PineConnector Syntax, accessed 25 September 2026.
  5. PineConnector – Test your setup, accessed 25 September 2026.
  6. TradingView – Pine Script FAQ: Alerts, accessed 25 September 2026.

PineConnector executes the instructions you send it. It does not select trades, manage money, or hold funds. Trading carries risk, and past performance of any strategy does not indicate future results.


Leave a comment

Back To PiCo Blog

Ready when your strategy is

You bring the strategy.We bring the infrastructure.

Connect TradingView to MetaTrader, choose where MT5 runs and put the full PineConnector workflow through its paces from your first month.

Strategy and trading decisions remain yours. The MT5 environment can be ours.

PineConnector Edge

Run the full PineConnector workflow.

$59/mo at launch

Core plan · 1 connection · 1 hosted MT5 environment

Try Core for $7

7 days of Core for $7, then $59/month at the launch price unless you cancel.