Skip to main content

Position Management & Strategy Sync

Managing open positions is one of the trickier parts of automated trading. CrossTrade gives you several payload-level tools to handle reversals, prevent hedging, and keep NinjaTrader 8 in sync with your TradingView strategy. This page covers flatten_first, require_market_position, and the full strategy-sync toolkit including sync_strategy, \{\{strategy.market_position\}\}, and strategy_exit_block.

Frequently Asked Questions

What is the difference between flatten_first and require_market_position?

They serve opposite purposes. flatten_first=true; flattens the position and working orders for the account + instrument before the PLACE command executes. Use it when you already know the new signal is a reversal and you want the instrument zeroed out first. require_market_position=flat; (or long/short) is a filter. It prevents the order from taking action unless the live position matches, and the blocked result is recorded in Alert History. One forces a clean slate; the other gates the order on existing state.

How do I guarantee that NT8 ignores a new signal when I'm already in a position?

Use require_market_position=flat; in your payload. If the account isn't flat when the alert arrives, the order is blocked entirely: it won't flip, add, or reverse. max_positions=1 limits the number of open instruments, but it does not block scaling or reversing an instrument that is already open.

How do I block orders that would create a same-direction add?

Use require_market_position=flat; when every new entry must start flat. If a command intentionally allows more than one state, pass a comma list such as require_market_position=flat,short;. max_positions controls how many different instruments may be open; it does not cap contracts or same-instrument adds.

How do I prevent hedging across accounts on a prop firm?

You can check the market position (flat/long/short) of each account with require_market_position, but the filter applies per account — it does not check a group of accounts. Groups for Account Management are on the roadmap; for now, enforce the no-hedge rule on every account individually, or prevent opposing signals from being sent in the first place.

Does flatten_first flatten everything on the account, or just the instrument?

flatten_first is tied to the account + instrument; other instruments are untouched. When a position exists, flattening also clears its working orders before entry. On NT8, use an explicit CANCELORDERS when the account is already flat but orphan working orders may remain.

What's the easiest way to handle reversals in a payload?

If you know a given alert represents a reversal, set flatten_first=true; on that PLACE order. It will zero out the existing position and any working orders before entering the new one in a single webhook call — no second request needed.

How do I cancel hanging TP/SL orders when I close a position?

Use CANCELORDERS when orphan orders must be cleared regardless of position state. flatten_first also clears same-instrument orders as part of flattening an active position, but on NT8 it is not a substitute for CANCELORDERS when the account is already flat. If you partially close while canceling a stop separately, serialize the alerts to avoid racing the two operations.

When should I use Strategy Sync instead of flatten_first?

Strategy Sync (sync_strategy=true;) is built for TradingView strategies where signals add to a position in one direction and only flatten when the direction flips. A typical pattern: keep adding on same-direction signals, but flatten-and-open-opposite when the direction changes — without having to hand-code flatten_first on every reversal alert. You do not need flatten_first when you're using strategy sync; the sync logic already handles it. Remove flatten_first from alerts that use sync.

What do strategy.market_position and strategy.prev_market_position do?

They are TradingView placeholders that the strategy substitutes with the current and previous position state (long/short/flat) at alert fire time. When you enable sync_strategy=true; and pass these variables in the payload, CrossTrade can compare the TradingView strategy's expected state to the NT8 account's actual state and either trust it, sync it, or flatten on mismatch depending on your out_of_sync setting. The variable values come from the strategy — you pass the template and the strategy fills them in.

Strategy Sync payload with market_position variables
account=MyAccount; instrument=NQ1!; action={{strategy.order.action}}; qty={{strategy.order.contracts}};
sync_strategy=true; market_position={{strategy.market_position}}; prev_market_position={{strategy.prev_market_position}};
What does out_of_sync=flatten actually do?

Strategy Sync performs a "nuclear" flatten on all positions and orders for that instrument when it detects a state mismatch between the TradingView strategy and NT8. It's a safety mechanism — if your platforms drift out of alignment (for example, a partial fill, a manual intervention, or a missed signal), flattening prevents you from stacking incorrect trades on top of bad state. If you'd rather have the mismatch corrected instead of closed out, use out_of_sync=resync; with target_quantity={{strategy.position_size}}; that's the default in our examples, because it realigns the position and keeps the strategy trading. If you'd rather let the trade go through even when state doesn't agree, set out_of_sync=ignore; — but understand you lose the safety net.

What happens if I choose wait when the strategy is out of sync?

That order attempt is withheld and returned immediately with a warning; it is not queued for later release. A later signal is evaluated independently against the then-current position.

What if Strategy Sync says it flattened but the position keeps running?

Strategy Sync issues a flatten on all positions and orders for that instrument. If the position still appears open after, it's usually a "ghost position" stuck in the NT8 UI. Restart NT8 — if the position disappears on restart, that confirms it was a UI-only artifact, not a real exchange position.

Why did Strategy Sync trigger a flatten on what looked like a fresh entry?

A webhook Success on the entry only confirms the order was accepted — it doesn't mean out_of_sync was involved. If a flatten fires shortly after, look at whether an Account Manager threshold (profit/loss), a trading window boundary, or a separate command triggered it. The out_of_sync action only runs when the strategy state and NT8 state genuinely disagree.

Can I use Strategy Sync with a stop-and-reverse strategy?

Stop-and-reverse strategies are the one case where Strategy Sync isn't the right tool. For those, most traders coding their own send a CLOSEPOSITION command on the strategy.exit event and a separate PLACE for the new direction — a plain strategy.exit in Pine will otherwise reverse the position instead of exiting cleanly, which isn't what you usually want.

How do I send a plain exit from a Pine strategy without reversing?

Wire your strategy.exit alert to issue a CLOSEPOSITION command rather than a PLACE order. That closes the open contracts without opening a new opposite position. See the close-position command docs for payload details.

What is strategy_exit_block?

It restricts Strategy Sync payloads to remote transitions that begin from prev_market_position=flat. If the remote previous state is long or short, the signal is rejected before live-state comparison.

Do I have to use Strategy Sync?

No. Strategy Sync is a convenience for TradingView strategy users — it is not required. Many traders run CrossTrade with plain PLACE / CLOSEPOSITION commands and manage reversals manually with flatten_first. Use sync if it fits your workflow; skip it if simpler commands get the job done.

Do I still need the leading negative sign on offsets?

No. Use positive distance magnitudes for take_profit and stop_loss, for example stop_loss=40ticks;. CrossTrade derives the protective direction from the entry side. Signed entry offsets are different: limit_price and stop_price may still be positive or negative to select above or below the quote.

Can I partially close a position instead of flattening it?

Yes — scale out using CLOSEPOSITION with a quantity. Unlike flatten_first, which zeroes everything for the instrument, CLOSEPOSITION can take a specific number of contracts so you keep the remaining position open.

If I run the same strategy on multiple timeframes, how do I keep them from stepping on each other?

On NT8, strategy_tag provides an Add-On-side ownership lock so differently tagged strategies cannot manage the same account/instrument position, and Opposing Position Protection can enforce configured cross-account rules. Tradovate accepts strategy_tag for shared-template compatibility but ignores it and has no cross-account OPP, so separate accounts or explicit position gates are still required there.

How do I add to a position on same-direction signals but flatten on a flip?

Two ways. TradingView Pyramiding — configure it in the strategy settings so same-direction signals add and opposite signals flatten-and-reverse (handled on TradingView's side before the alert even fires). Or Strategy Sync — let sync_strategy=true; plus strategy.market_position handle the state transition, so CrossTrade knows when to add vs. when to reverse without you tagging every alert.