Skip to main content

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

CapabilityOwnerWhat that means
Entry, scale-out targets, fixed stops, and OCO relationshipsTradovate nativeThe orders are hosted and executed by Tradovate after submission.
Continuous trailing from entry (atm_trail=true with no trigger)Tradovate nativeTradovate receives trailingStop=true and manages the trail.
Named ATM Template libraryCrossTrade configurationThe 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-exclusiveCrossTrade tracks the highs and lows of its own live pricing while the fixed stop remains active. Once the trigger is reached, CrossTrade keeps tightening that stop so it follows the trade's best price by your offset. The stop only ever moves in your favor.
Trigger memory across restartsCrossTrade-exclusiveThe 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 breakevenCrossTrade-exclusiveCrossTrade 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.

Named Tradovate ATM Templates

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

FieldRequiredOwnershipMeaning
atm_targetsYesTradovate nativeComma-separated profit-target offsets, one per tier (scale-out).
atm_stopsYesTradovate nativeStop offset(s). One value applies to every tier, or give one per tier.
atm_qtysNoTradovate nativeContracts per tier. Must sum to qty. If omitted, qty is split evenly with the remainder on the last tier.
atm_trailNoTradovate native without a triggerPer-tier trailing toggle. Without trigger/offset fields, Tradovate trails continuously from entry.
atm_trail_triggerNoCrossTrade-exclusiveProfit 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_offsetNoCrossTrade-exclusiveHow far behind the trade's best price the stop follows once the trigger is reached. Set with atm_trail_trigger.
atm_breakevenNoCrossTrade-exclusiveTarget tier whose confirmed fill moves the remaining stops to breakeven.
atm_breakeven_offsetNoCrossTrade-exclusiveTicks 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 and leaves the non-trailing tiers alone, which is what the example above does. A full per-tier list is for when trailing tiers need different numbers, and it may leave blank slots for tiers that should not be managed: on a three-tier ATM, atm_trail_trigger=,30,45 manages tiers 2 and 3 only. 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, and it does not allow an existing stop order to be changed into a trailing stop. Those paired fields are a CrossTrade-exclusive management layer. Once CrossTrade's live pricing has moved atm_trail_trigger in the trade's favor, the tier arms: CrossTrade then keeps moving the tier's stop so it stays atm_trail_offset behind the trade's best price, confirming each move with the broker, until the stop or its target executes. The trail never loosens protection: the stop only ever moves in the trade's favor, and a stop already tighter than the computed price (for example one you moved by hand) is left alone.

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.

What triggered trailing needs

CrossTrade-exclusive triggered trailing requires CrossTrade's own live pricing to observe the trigger and to keep following the trade afterward. The user dashboard, browser, TradingView, NinjaTrader, and Tradovate market-data entitlement are not required.

Watch for degraded trail activation

The tier is always protected by a real working stop, so the position is never left unprotected. But if CrossTrade cannot evaluate the trigger (no trusted quote) or the broker refuses a stop adjustment, the stop simply stays at its last confirmed price and you receive an ATM stop-management 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.

Watch for degraded breakeven management

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 and CrossTrade-managed breakeven and triggered trailing are all generally available. Verify the complete CrossTrade management lifecycle on a demo account before using those enhancements live. Some execution providers may reject a stop adjustment; if that happens, the stop remains working at its last confirmed price 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 with take_profit / stop_loss (use one bracket style, not both) or with cancel_after.
  • A managed atm_trail_trigger must be closer than that tier's profit target; otherwise the target would close the tier before trailing could activate.
  • atm_breakeven cannot 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 same order_id you 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.