Tradovate ATM (Scale-Out Brackets)
Tradovate webhooks build a broker-native multibracket order strategy: one entry with any number of scale-out target and stop tiers. CrossTrade then adds management capabilities that Tradovate's AutoBracket API does not provide, including profit-triggered trail activation, durable high/low replay, and target-fill breakeven.
What Tradovate provides vs. what CrossTrade adds
| Capability | Owner | What that means |
|---|---|---|
| Entry, scale-out targets, fixed stops, and OCO relationships | Tradovate native | The orders are hosted and executed by Tradovate after submission. |
Continuous trailing from entry (atm_trail=true with no trigger) | Tradovate native | Tradovate receives trailingStop=true and manages the trail. |
| Named ATM Template library | CrossTrade configuration | The reusable template is stored in CrossTrade, not Tradovate or NinjaTrader. CrossTrade expands it into the order fields at signal time. |
Profit-triggered trail activation (atm_trail_trigger + atm_trail_offset) | CrossTrade-exclusive, then native handoff | CrossTrade tracks the highs and lows of its own live pricing while the fixed stop remains active. At the trigger, CrossTrade converts the child to a Tradovate-native trailing stop. |
| Trigger memory across restarts | CrossTrade-exclusive | The highs and lows CrossTrade observed are saved and restored from the entry fill, so a brief service restart doesn't erase an observed trigger touch. |
| Target-fill breakeven | CrossTrade-exclusive | CrossTrade watches the target fill and modifies surviving stops. Tradovate AutoBracket exposes no native breakeven field. |
This ownership distinction is important. Tradovate-native means the broker owns the behavior. CrossTrade-exclusive means CrossTrade supplies functionality that is not present in Tradovate's native AutoBracket field set.
Open Tradovate Webhooks → ATM Templates to create a CrossTrade template, then reference its name with strategy=My Template; or atm_strategy=My Template;. This is not a Tradovate-saved or NinjaTrader desktop ATM template. CrossTrade resolves it when the signal arrives, so saved changes apply immediately to the next signal. Named templates cannot be combined with inline atm_* fields in the same payload.
Fields
| Field | Required | Ownership | Meaning |
|---|---|---|---|
atm_targets | Yes | Tradovate native | Comma-separated profit-target offsets, one per tier (scale-out). |
atm_stops | Yes | Tradovate native | Stop offset(s). One value applies to every tier, or give one per tier. |
atm_qtys | No | Tradovate native | Contracts per tier. Must sum to qty. If omitted, qty is split evenly with the remainder on the last tier. |
atm_trail | No | Tradovate native without a trigger | Per-tier trailing toggle. Without trigger/offset fields, Tradovate trails continuously from entry. |
atm_trail_trigger | No | CrossTrade-exclusive | Profit distance that activates a trailing tier. Until CrossTrade's live pricing reaches it, the Tradovate-native fixed stop stays in place. Set with atm_trail_offset. |
atm_trail_offset | No | CrossTrade-exclusive activation; Tradovate-native after handoff | Distance for the native trail created after CrossTrade confirms the trigger. Set with atm_trail_trigger. |
atm_breakeven | No | CrossTrade-exclusive | Target tier whose confirmed fill moves the remaining stops to breakeven. |
atm_breakeven_offset | No | CrossTrade-exclusive | Ticks or points past entry for the managed breakeven stop. Default 0. |
Example: named template
If an active template named Two Target Runner is saved in CrossTrade:
key=your-secret-key;
command=place;
account=your-tradovate-account;
instrument=ES1!;
action=buy;
qty=2;
order_type=market;
atm_strategy=Two Target Runner;
destination=tradovate;
The template's atm_* fields are substituted before validation. If the template defines atm_qtys, those quantities must sum to the signal's qty. Disabled, deleted, missing, or invalid templates fail closed and no order is sent.
Units and direction
Offsets are distances from the entry price, not absolute prices. A bare number or a tick suffix means ticks; a pt suffix means points. On ES (tick size 0.25), atm_targets=20 is 20 ticks (5.00 points) and atm_targets=5pt is 5.00 points. Direction is automatic from the order side, so always give positive numbers: a long targets above and stops below the entry, and a short is the mirror image.
Example: two-target scale-out with a trailing runner
Enter 2 contracts, scale out 1 at 20 ticks and 1 at 40 ticks, each protected by a 15-tick stop, and let the runner trail:
key=your-secret-key;
command=place;
account=your-tradovate-account;
instrument=ES1!;
action=buy;
qty=2;
order_type=market;
atm_targets=20,40;
atm_stops=15;
atm_qtys=1,1;
atm_trail=false,true;
destination=tradovate;
A bare atm_trail=true tier trails continuously from the moment of entry, at the stop's own distance. To hold the plain stop until the trade earns a profit milestone first, add a trail trigger (next section).
Example: trail activation after a profit trigger
Give the runner from the previous example a 15-tick stop that stays put until the trade is 30 ticks in profit, then trails 10 ticks behind price:
key=your-secret-key;
command=place;
account=your-tradovate-account;
instrument=ES1!;
action=buy;
qty=2;
order_type=market;
atm_targets=20,40;
atm_stops=15;
atm_qtys=1,1;
atm_trail=false,true;
atm_trail_trigger=,30;
atm_trail_offset=,10;
destination=tradovate;
Both fields take the same one-or-per-tier CSV shape as the other atm_* fields, in ticks or points (5pt). A single value arms every trailing tier; a full per-tier list may leave blank slots for tiers that should not be managed (as in atm_trail_trigger=,30 above). The two fields must be set together, and only on tiers where atm_trail=true.
Tradovate's multibracket API provides only a trailingStop true/false toggle. It has no separate activation trigger or post-activation offset. Those paired fields are a CrossTrade-exclusive management layer. Once CrossTrade's live pricing has moved atm_trail_trigger in the trade's favor, CrossTrade converts the tier's stop into a native Tradovate trailing stop pegged atm_trail_offset behind price, then re-reads the order to confirm the change was retained. The conversion never loosens protection: if the working stop is already tighter than price minus the offset, it keeps its price and trails from there. After confirmed conversion, ownership hands off to Tradovate and the trailing stop is broker-native.
CrossTrade never uses the user's Tradovate market-data feed for this decision, even when the login has market-data entitlements. Every Tradovate quote-dependent CrossTrade feature calculates prices the same way, server-side from live market data, so behavior doesn't change based on your account's data entitlements.
If CrossTrade's service restarts, it restores the trigger history from the confirmed entry-fill timestamp before evaluating the trigger, so a touch observed just before a restart is not lost. If fresh, reliable pricing isn't available, CrossTrade does not substitute a Tradovate quote, a single user's quote, or a direct GetQuote response. The fixed stop remains in place, the watcher retries during its 24-hour lifetime, and CrossTrade raises a degraded-management alert after repeated misses.
CrossTrade-exclusive triggered trail activation is beta until the stop is converted. It requires CrossTrade's own live pricing to observe and retain the trigger. The user dashboard, browser, TradingView, NinjaTrader, and Tradovate market-data entitlement are not required. After confirmed conversion, the trail is Tradovate-native.
Until the trigger is reached, the tier is protected by its ordinary stop, so the position is never left unprotected. But if CrossTrade cannot evaluate the trigger (no trusted quote) or cannot confirm the conversion, the stop simply remains a plain stop at its last confirmed price and you receive an ATM trailing-stop activation degraded alert. Do not assume the stop is trailing when this alert appears.
Example: breakeven after the first target
Move the remaining stop to breakeven (plus 2 ticks) once the first target fills:
key=your-secret-key;
command=place;
account=your-tradovate-account;
instrument=ES1!;
action=sell;
qty=2;
order_type=market;
atm_targets=20,40;
atm_stops=15;
atm_qtys=1,1;
atm_breakeven=1;
atm_breakeven_offset=2;
destination=tradovate;
Breakeven is target-fill-triggered: the remaining stops move only after target tier 1 fully fills, not merely when price moves that far. Tradovate AutoBracket has no native breakeven parameter. This is a CrossTrade-exclusive feature: CrossTrade watches the fill, moves the surviving stop orders, and re-reads them to confirm the new price was retained. Failed or unconfirmed changes remain pending and retry within the job's 24-hour lifetime. The pending move is stored in CrossTrade's cloud, so it survives a service restart.
The watcher refreshes Tradovate's child-order links and does not begin breakeven processing until it has discovered the entry plus every configured target and stop tier. It does not freeze or act on an early partial snapshot.
Tradovate may accept the ATM before CrossTrade starts its breakeven watcher. If the watcher cannot start, the ATM remains live at Tradovate but automatic breakeven management is degraded. CrossTrade returns a warning on the leader alert; for a copied follower ATM, it also marks the follower result as degraded and writes a warning to the Copy Log. If a running watcher repeatedly cannot discover the child orders or confirm the stop move, CrossTrade sends an ATM breakeven management degraded alert. Do not assume breakeven is active when either warning appears.
Tradovate-native multibracket placement is separate from the beta status of CrossTrade-managed breakeven and triggered-trail activation. Verify the complete CrossTrade management lifecycle on a demo account before using those enhancements live. Some execution providers may reject advanced trailing-stop conversion; if that happens, the fixed stop remains working and CrossTrade raises a degraded-management alert.
Where it works
atm_* is valid on place, flatplace, and reverseposition. On flatplace the same-instrument position is flattened first. On reverseposition, the existing position is flattened and the ATM is sized from the explicit replacement entry. Bare reverse derives a market entry from the live position and accepts only account and instrument, matching NT8.
Limits (v1)
- A stop is required (
atm_stops). A target-only ATM is rejected, so a Tradovate entry is never left unprotected. atm_*cannot be combined withtake_profit/stop_loss(use one bracket style, not both) or withcancel_after.- A managed
atm_trail_triggermust be closer than that tier's profit target; otherwise the target would close the tier before trailing could activate. atm_breakevencannot point at the final tier (there is no remaining stop to move), and cannot be combined with a trailing tier after the trigger.- CrossTrade-managed breakeven and triggered trailing require a Day entry. GTC/GTD entries are rejected because the durable watcher has a 24-hour safety lifetime.
- Trigger history contains every price observation CrossTrade received. It cannot reconstruct a market move that occurred while CrossTrade had no fresh, reliable pricing; the fixed stop remains the safety fallback.
- To cancel the whole ATM, send
command=cancel;with the sameorder_idyou set on the entry alert. Modifying a running ATM (change) is not supported yet, so cancel and re-send. - Signal-mode copiers replicate the native ATM to followers, re-sized with the same scale-out proportions. Execution-mode copiers see the resulting fills and copy them as market orders rather than recreating the ATM structure.
For a single target and stop (no scale-out), the simpler take_profit / stop_loss bracket also works on Tradovate.