Pine Script Integration
CrossTrade alerts are most commonly generated from TradingView Pine Script. The way you configure the alert depends on whether your script is an indicator(...) or a strategy(...), and on how you choose to build the payload. This page covers the distinctions that matter most when wiring Pine Script into CrossTrade.
Is my Pine script a strategy or an indicator?
Open the script editor and look at the declaration on the first non-comment line. If it starts with strategy(...), it is a strategy. If it starts with indicator(...), it is an indicator. That distinction determines which dynamic variables are available and how you structure the alert.
What's the practical difference between a strategy and an indicator for CrossTrade?
A strategy exposes dynamic variables like \{\{strategy.order.action\}\} and \{\{strategy.order.contracts\}\}, so the alert can populate the action and quantity automatically. It also exposes \{\{strategy.market_position\}\} and \{\{strategy.prev_market_position\}\}, which are required for CrossTrade's Strategy Sync feature. The trade-off is that Pine strategies require every entry to have an offsetting exit for backtesting, which can complicate stop-and-reverse setups.
An indicator gives you full control: you define exactly which condition fires a BUY alert and which fires a SELL alert, and you hardcode the action and quantity in the payload. There's no offsetting requirement and no ambiguity about entries vs. exits. Indicators do support a smaller set of dynamic variables (\{\{close\}\}, \{\{open\}\}, \{\{high\}\}, \{\{low\}\}, \{\{ticker\}\}) which are useful for dynamic pricing or symbol passthrough.
Should I use alertcondition() or the alert() function?
Both work with CrossTrade; they have different trade-offs.
alertcondition() is the classic Pine approach. You define a named condition in the script, then create a TradingView alert manually and select that condition from the Condition dropdown. The alert message is whatever you paste into TradingView's alert dialog. This works on all TradingView plans.
The alert() function lets you fire alerts programmatically from inside the script — including dynamically built payloads — without the user having to create one alert per condition. This is powerful for strategies that build the full CrossTrade payload in Pine and emit it via \{\{strategy.order.alert_message\}\}, but note that the alert() function requires a paid TradingView plan (Essential or higher). alertcondition() does not.
What does a minimal Pine strategy alert payload look like in the TradingView message field?
For a strategy, paste the payload directly into the alert Message field and let TradingView substitute the dynamic variables at fire time:
key=your-secret-key;
command=PLACE;
account=Sim101;
instrument=ES1!;
action={{strategy.order.action}};
qty={{strategy.order.contracts}};
order_type=MARKET;
tif=DAY;
flatten_first=true;
\{\{strategy.order.action\}\} resolves to buy or sell based on what the strategy did. \{\{strategy.order.contracts\}\} resolves to the number of contracts in the order. flatten_first=true; closes any existing position before opening the new one, which gives clean stop-and-reverse behavior without needing Strategy Sync.
How do I build the CrossTrade payload inside the Pine script itself?
Build the payload as a string in Pine and pass it to strategy.entry() / strategy.exit() via the alert_message parameter. Then in the TradingView alert Message field, use only \{\{strategy.order.alert_message\}\} as a passthrough.
//@version=5
strategy("XT Example Strategy", overlay=true)
// --- your signal logic ---
fastMA = ta.sma(close, 9)
slowMA = ta.sma(close, 21)
longCond = ta.crossover(fastMA, slowMA)
shortCond = ta.crossunder(fastMA, slowMA)
// --- build payloads ---
key = "your-secret-key"
account = "Sim101"
symbol = "ES1!"
buyPayload = "key=" + key + ";command=PLACE;account=" + account +
";instrument=" + symbol + ";action=buy;qty=1;order_type=MARKET;" +
"tif=DAY;flatten_first=true;take_profit=50 ticks;stop_loss=50 ticks;"
sellPayload = "key=" + key + ";command=PLACE;account=" + account +
";instrument=" + symbol + ";action=sell;qty=1;order_type=MARKET;" +
"tif=DAY;flatten_first=true;take_profit=50 ticks;stop_loss=50 ticks;"
if (longCond)
strategy.entry("Long", strategy.long, alert_message=buyPayload)
if (shortCond)
strategy.entry("Short", strategy.short, alert_message=sellPayload)
Then in the TradingView alert Message field, use exactly:
{{strategy.order.alert_message}}
This approach lets you set any field (instrument, quantity, TP/SL) dynamically from Pine logic. The downside is that \{\{strategy.order.alert_message\}\} is a pure passthrough — if you forget to populate alert_message= on a given strategy.entry() / strategy.exit() call, the alert will be empty and will fail.
Can I filter or block certain signals (for example, only allow buy orders)?
There is no native CrossTrade setting to filter by direction. This kind of logic belongs upstream in the Pine Script itself — gate the strategy.entry() / alert() calls with your own condition (for example, only emit long entries, skip shorts). That decision should happen at the strategy code level, not in the CrossTrade payload.
My indicator draws buy/sell arrows on the chart but my alert never fires — why?
Some indicators calculate and draw signals retroactively as new bars form. These are repainting signals: they look valid on the chart after the fact, but they are not fired in real time, so an alert attached to them never triggers. If your alert silently never fires despite obvious signals on the chart, repainting is the most likely cause. Check with the indicator's author or documentation to confirm that real-time alerting is supported.
Why did my Pine alert suddenly stop matching my strategy settings?
TradingView alerts snapshot the strategy inputs at the moment the alert is created. If you later change a strategy input (different MA length, different risk parameter, etc.), existing alerts continue using the old settings and TradingView does not warn you. After changing strategy inputs, delete and recreate the alert so it picks up the new configuration.