Which hits first, your stop or your target
If a bar's range contains both your stop and your target, one of them filled and the other did not. The backtest had to pick. Most writing on this subject guesses; TradingView documents it.
The rule
The broker emulator infers the path price took through the bar from where the open sits relative to the high and the low [1]:
If the opening price of a bar is closer to the high than it is to the low, the emulator assumes that the market price moved in this order: open → high → low → close. If the opening price of a bar is closer to the low than it is to the high, the emulator assumes that the market price moved in this order: open → low → high → close. [1]
So for a long position:
| Bar's open is | Assumed path | Which level is reached first |
|---|---|---|
| nearer the high | open → high → low → close | your target |
| nearer the low | open → low → high → close | your stop |
That is the whole mechanism. It is deterministic, it is knowable per bar, and it is an assumption rather than a measurement.
Why this matters more than it sounds
Any strategy where a stop and a target can both sit inside one bar's range has a backtest partly decided by this heuristic. The shorter your timeframe relative to your stop distance, the more often it applies — a scalping strategy with tight stops on a volatile instrument may have most of its exits resolved this way.
Two things follow, and both are actionable:
You can find out. Open the List of Trades, take the exits, and check how many of them are on bars whose range contains both levels. If that fraction is large, your equity curve is substantially a product of the rule above.
Widening the gap between stop and target reduces the exposure. Not because wider stops are better, but because a stop and target that cannot both fall inside one bar leave nothing for the emulator to guess about.
This is also precisely where MetaTrader 5 differs: its tester can replay real broker-accumulated ticks with no simulation, so it does not need to infer the path [2]. Neither approach is wrong — but they cannot agree, and the comparison sets out why.
Gaps are treated as empty
One more documented behaviour with a real consequence: if price crosses an order's level during the gap between one bar's close and the next bar's open, the emulator assumes intrabar data does not exist within the gap [1].
So a stop inside a weekend gap is not filled at your stop price. It is dealt with when the market reopens, and the difference is the gap itself. Any strategy carrying positions over a session break should expect its real losses on those trades to be worse than the backtest's.
Only one exit order fills
If a single strategy.exit() call produces more than one exit order type for
an entry, the strategy fills only the first triggered one and automatically
cancels the others [1].
That is the behaviour you want, and worth knowing because it means a stop and a target on the same entry are genuinely exclusive — you cannot be filled on both and end up double-exited.
Exits: absolute versus relative
strategy.exit() accepts your stop and target in two different currencies,
and mixing them is how a stop ends up somewhere you did not intend.
| Parameter [1] | Expressed as |
|---|---|
stop | an absolute price |
limit | an absolute price |
loss | a relative distance in ticks |
profit | a relative distance in ticks |
trail_price | the absolute price at which trailing starts |
trail_points | the trailing trigger as a relative distance |
trail_offset | how far behind price the trail sits |
qty / qty_percent | how much of the position to close |
from_entry | which entry this exit belongs to |
Two rules follow, and both cause real bugs.
Do not set both an absolute and a relative version of the same side. If you
pass stop and loss together, you have specified the stop twice, in two
units. Pick one per side.
Zero is a value, not "unset". profit = 0 does not mean "no target"; it
means a target zero ticks away — which is the entry price. In v6, when an exit
call has both a relative and an absolute level, whichever triggers first wins,
so this now exits immediately at entry rather than being overridden. It is in
the v6 change list for exactly this reason —
the silent changes has the
table. Leave a parameter out to mean "not used".
Stops in ticks versus stops in ATR
A fixed tick stop is the same distance in every market condition, which means it is too tight in high volatility and too loose in low. An ATR-based stop scales with recent range, so the same code behaves comparably across regimes and across instruments.
The practical difference for a converted strategy: a tick stop needs re-tuning for every symbol you apply it to, and an ATR stop mostly does not. That is also why an ATR stop makes cross-instrument testing meaningful — see the ATR and session filters.
Neither is "safer". An ATR stop widens exactly when the market is violent, which is when you may most want to be out.
Position sizing is a risk control, not a cosmetic setting
default_qty_type decides whether your equity curve compounds [1]:
strategy.fixed— a constant number of contracts. Does not compound, and is the harder test to pass.strategy.percent_of_equity— a share of available capital. Compounds, and will make a mediocre edge look dramatic over a long backtest.
If you are judging a strategy rather than projecting returns, test with fixed size. Percent-of-equity answers "what would this have grown to", which is a different and much more flattering question.
And since v6, margin_long and margin_short default to 100, so a strategy
that needs more money than is available does not open the entry [1]. A v5
strategy that was quietly overleveraged will now simply take fewer trades — no
error, just a different trade list.
The risk limits that act as a circuit breaker
Beyond per-trade exits there are account-level stops, which run in the emulator
rather than in your logic. strategy.risk.allow_entry_in() restricts which
direction the strategy may open at all [1] — the honest use is to stop a
long-only idea from quietly making money on shorts it was never meant to take.
These are worth setting deliberately even when you expect never to hit them, because the version of a strategy that survives an unexpected regime is usually the one with a limit that fired.
Tactix AI — Studio vs Guide
Tactix AI is AlfaTactix’s product assistant brand (open Tactix AI).
- Tactix Studio turns a one-sentence strategy description into a draft across Timeframe, Signals, Filters, and Risk in the visual Strategy Builder. You review and edit every field before Code Generator writes MQL5 or Pine Script.
- Tactix Guide explains the step you are on — what to fill, what a control means, or how to phrase a rule — without dumping untested source code.
That is form-first automation: the LLM never replaces Code Generator, and you keep plan limits and real-time validation.

