Skip to main content

Automating TradingView Strategies (Tradovate)

This guide covers the full workflow for automating a TradingView strategy (not an indicator) on the Tradovate destination. If you're using an indicator, see Automating TradingView Indicators instead. Not sure which one you have? If your Pine Script starts with strategy(...), it's a strategy. If it starts with indicator(...), it's an indicator. That distinction matters more than you'd think.

Strategies vs. Indicators: Why It Matters

Strategies give you access to dynamic variables like {{strategy.order.action}} and {{strategy.order.contracts}}, which means the alert can automatically populate BUY or SELL and the contract quantity based on what the strategy does. Strategies also expose position state variables ({{strategy.market_position}}, {{strategy.prev_market_position}}) that CrossTrade's Strategy Sync feature uses to keep your broker position aligned with TradingView.

The catch: TradingView requires every strategy to have offsetting actions. An entry must eventually have an exit. The {{strategy.order.action}} variable only produces buy or sell — there's no built-in way to tell "entry" from "exit" from the variable alone. Strategy Sync exists to solve this problem, and it works on Tradovate the same way it works on NinjaTrader.

Indicators give you full control: hardcoded actions, no offsetting requirement, no sync ambiguity. If your strategy does constant stop-and-reverse without going flat, converting the logic to an indicator with flatten_first is often the cleaner build.

The Basic Strategy Payload

Here's the starting point for any TradingView strategy automation on Tradovate:

key=your-secret-key;
command=PLACE;
account=DemoAccount;
instrument=ES1!;
action={{strategy.order.action}};
qty={{strategy.order.contracts}};
order_type=MARKET;
sync_strategy=true;
market_position={{strategy.market_position}};
prev_market_position={{strategy.prev_market_position}};
out_of_sync=flatten;
destination=tradovate;

The sync-specific lines:

sync_strategy=true; turns on position synchronization. CrossTrade compares what TradingView thinks the position is versus what your Tradovate account actually has before placing any order. On Tradovate this check runs against the live broker position, derived from Tradovate's real-time fill stream rather than its (sometimes laggy) position endpoint, so back-to-back signals see the truth.

market_position={{strategy.market_position}}; is the position the strategy wants to be in after this order. TradingView fills it in automatically: long, short, or flat.

prev_market_position={{strategy.prev_market_position}}; is the position the strategy was in before this signal. Together the two define the intended transition (flat→long, long→flat, long→short).

out_of_sync=flatten; defines what happens when TradingView and Tradovate disagree. With flatten, CrossTrade closes the Tradovate position to reset everything to flat, then waits for the next clean entry signal. The other options:

  • wait — withholds the current attempt and returns immediately. Nothing is queued for later; the signal is simply not placed.
  • resync — automatically submits a corrective order to align Tradovate with the strategy's expected position (most hands-off).
  • ignore — places the order anyway despite the mismatch (advanced use only).

For most traders, flatten is the right default.

info

Strategy Sync is evaluated immediately before the entry leg of place, flatplace, reverseposition, and cancelreplace. On a Tradovate cancelreplace, only wait and ignore are accepted — a separate flatten/resync mutation can't be recovered safely inside the replacement workflow.

Setting Up the TradingView Alert

Create your alert in TradingView with the Condition set to your strategy (from the condition dropdown — not a price level or indicator).

In the Message field, delete all default text and paste the payload above with your actual secret key and Tradovate account name.

In the Notifications tab, check the Webhook box and paste your CrossTrade webhook URL.

Set the alert to fire Every time the strategy fires an order (not "Once" or "Once per bar"). Strategy Sync needs to receive every signal the strategy generates.

Important: TradingView alerts snapshot the strategy settings at the time the alert is created. If you change the strategy's inputs after creating the alert, the alert still uses the old values. Delete the old alert and create a new one — TradingView doesn't warn you about this.

Renko bars and alert latency

If your strategy runs on a Renko, Range, Line Break, Kagi, or Point & Figure chart, your alert can fire well after the underlying market move — new bricks only print once price has traveled the full box size. The lag shows up as apparent fill slippage or sync drift. CrossTrade's free TRUE OHLC indicator overlays real-time OHLC values onto non-time charts so your payloads can reference live prices.

Understanding Out-of-Sync Scenarios

Your strategy and Tradovate will get out of sync. It's not a question of if, it's when. Common causes on the Tradovate path:

You manually close a position in Tradovate while the TV strategy is still running. The strategy still thinks it's in a position and will eventually send an exit for a position that no longer exists.

An alert is missed or delayed. TradingView alert delivery isn't guaranteed to be instant. If an entry arrives but the exit doesn't (or vice versa), the state drifts.

A bracket or ATM tier closes the position. If your server-side stop or target fills, Tradovate is flat but TradingView doesn't know it.

Your Tradovate link expires mid-session. An evicted or expired session fails orders until you re-link (see Linking Your Tradovate Account). Signals during the gap are recorded as failures in Alert History, not queued.

When a mismatch is detected, your out_of_sync choice kicks in. With flatten, the position closes and both sides reset; the strategy eventually generates a fresh entry from flat and trading resumes cleanly. Alert History shows sync warnings when they occur, including what TradingView expected vs. what Tradovate had — check there first when debugging.

Using Strategy Sync with ATM Scale-Outs

The Tradovate equivalent of "Strategy Sync plus an ATM template" uses CrossTrade ATM Templates (or inline atm_* fields), which build a native Tradovate multibracket order strategy. The pairing requires the same critical addition as NT8: strategy_exit_block=true;.

Your ATM manages the exits server-side, but the Pine strategy will still generate exit signals (offsetting actions are mandatory in Pine). Without blocking them, TradingView tries to close a position the ATM is already managing.

key=your-secret-key;
command=PLACE;
account=DemoAccount;
instrument=ES1!;
action={{strategy.order.action}};
qty={{strategy.order.contracts}};
order_type=MARKET;
flatten_first=true;
atm_strategy=Two Target Runner;
sync_strategy=true;
market_position={{strategy.market_position}};
prev_market_position={{strategy.prev_market_position}};
out_of_sync=flatten;
strategy_exit_block=true;
destination=tradovate;

What the additions do:

atm_strategy=Two Target Runner; resolves an active CrossTrade ATM Template saved on your Tradovate Webhooks → ATM Templates page. If the template defines per-tier quantities (atm_qtys), they must sum to the alert's qty. A disabled, deleted, or invalid template fails closed — no order is sent, and the failure is recorded.

flatten_first=true; clears the same account and contract (position plus working orders) before the new entry, preventing orphaned tiers from a previous ATM.

strategy_exit_block=true; blocks any signal where the strategy is transitioning out of a position, so only fresh entries from flat reach Tradovate. The ATM handles the exit.

Be aware: when an ATM tier flattens you, the next strategy signal will report an out-of-sync condition. That's expected — with out_of_sync=flatten; it re-flattens (already flat) and waits for the next entry. Normal behavior, not a bug.

If you need dynamic TP/SL levels computed per trade, skip named templates and use take_profit= / stop_loss= (or inline atm_* offsets) built in Pine via alert_message — see the next section.

The {{strategy.order.alert_message}} Variable

{{strategy.order.alert_message}} is a passthrough: it carries whatever string you set inside your Pine Script's strategy.entry() / strategy.exit() calls via the alert_message= parameter, delivered exactly when the order fills.

If you're authoring your own Pine Script, this is how you trigger CrossTrade alerts. Build the full CrossTrade payload as a string inside your script (including the destination=tradovate; line), pass it via alert_message=msg, and put {{strategy.order.alert_message}} in the alert dialog Message field with Condition set to "Order fills only". This is the only approach that lets you compute per-signal values — calculated SL/TP from tick math, asymmetric long/short payloads, qty derived from ATR.

If you didn't build the payload in Pine, {{strategy.order.alert_message}} is empty and the alert will fail. In that case use the individual variables directly in the alert dialog as shown earlier. For Pine examples, see Example Strategies.

Adding Position Protection

Beyond Strategy Sync, the same defense-in-depth fields work on Tradovate:

require_market_position=flat; — blocks the alert unless the live Tradovate position on that instrument is flat. Combinations like long,flat work too.

max_positions=1; — blocks an opening order that would add a new instrument when the account already holds that many open positions.

trading_window=HH:MM-HH:MM ET; — restricts when alerts are accepted. See Trading Window docs.

One NT8 field to know about: strategy_tag (Strategy Lock) is accepted but ignored on Tradovate — the lock lives in the NT8 Add-On's local order book, which Tradovate orders never touch. Use position gates and separate accounts to keep strategies out of each other's way.


Related Guides:

Reference Docs: