Pine Script Strategy Orders and Exits: Limit, Stop, Brackets, Partial Exits and Pyramiding
The bar where a condition becomes true, the moment an order is created, the emulator fill, and the position close are not necessarily the same event. Multiple strategy.exit() calls also reserve position quantity in code order. This guide does not choose an optimal target or stop. It treats Pine Script v6 orders as a state machine and traces reversals, partial exits and leftovers through the List of Trades.
Who this guide is for: Pine strategy authors debugging unexpected fill bars or quantities, bracket exits, partial exits and pyramiding
Key points to understand first
- Record condition, creation, pending, fill, cancellation and position update as separate events.
strategy.entry()can reverse a position by default, whilestrategy.order()ignores some properties such as pyramiding.- Stop plus limit creates a stop-limit entry/order, but two bracket legs when used in
strategy.exit(). - Multiple exit calls reserve quantity in call order, so a later request can be reduced to the unreserved remainder.
- Reconcile IDs, requested quantity, effective quantity, creation bar and fill bar with List of Trades—not chart markers alone.
A signal is not an order, and an order is not a fill
- 01Condition trueCode calls an order command
- 02CreatedOrder receives ID, side, price and quantity
- 03PendingA limit or stop condition remains outstanding
- 04FilledPosition or realized P/L changes
- 05CancelledExplicit cancellation or OCA removes it
- Market: created → next available tick → filled
- Price order: created → pending → trigger/fill or cancel
- Bracket: one leg fills → sibling is reduced or cancelled
Read an order as a state transition, not just a function call
Order bugs often start when a source call is treated as the same event as a position update. This article traces logical states—created, pending, filled and cancelled—and quantity ownership. The separate question of why the broker emulator filled at a particular bar or price belongs to TV12, so do not mix that investigation with an exit-reservation correction.
- Record the condition
Identify the bar and confirmed values that made it true.
- Record creation
Capture command, ID, direction, qty, limit, stop and from_entry.
- Trace pending state
Check whether a price order stayed active, changed, was reissued or cancelled.
- Record filled state
Record the transition and effective quantity; hand bar-and-price causality to TV12.
- Reconcile the position
Explain reversal, addition, partial exit, remaining quantity and OCA action in List of Trades.
Separate market, limit, stop and stop-limit activation
| Type | How it is created | What it waits for | Common misread |
|---|---|---|---|
| Market | No limit or stop | Next available tick | Assuming a fill at the same condition-bar close |
| Limit | limit price | Specified price or better | Reversing favorable and unfavorable directions |
| Stop | stop price | Activation at the stop or worse | Treating stops as exit-only |
| Stop-limit | stop and limit on entry/order | Stop activation, then a limit fill | Assuming the stop touch itself opens the position |
| Exit bracket | limit and stop on exit | Whichever TP or SL leg triggers first | Treating it as one stop-limit order |
Long and short favorable directions are opposite. Verify with current official examples.
Passing both stop and limit to strategy.entry() or strategy.order() creates one stop-limit order: the stop activates a later limit order. Passing both to strategy.exit() creates two exit orders, a take-profit limit and a stop-loss stop. Put this distinction directly in the code-review ledger.
Entry, order, exit and close are not interchangeable
| Command | Primary job | Position relationship | Audit point |
|---|---|---|---|
| strategy.entry | Entry and default reversal | Same-direction additions respect pyramiding | A reversal transaction can include closing plus opening quantity |
| strategy.order | Basic directional order | Changes net position and ignores some properties | Do not rely on pyramiding as its guard |
| strategy.exit | Price-based exits linked to entries | Brackets, partial and trailing exits | Check from_entry, reservations and OCA |
| strategy.close | Market close linked to an entry ID | Fills on an available tick | Reconcile FIFO/ANY and ID expectations |
| strategy.cancel | Cancel an unfilled order | Does not close an open position | Check whether code reissues it on every bar |
Use the current TradingView documentation as the specification of record.
Pyramiding limits the number of open trades that strategy.entry() can maintain in one direction. It is not simply a one-order-per-bar safety switch. Multiple price orders can be created and triggered together, and strategy.order() ignores pyramiding. When commands are mixed, trace IDs and changes in net position explicitly.
Partial exits conserve quantity in call order
When several strategy.exit() calls target the same entry, each call reserves part of the open position in execution order. If a later request exceeds the unreserved remainder, its effective exit quantity is reduced. Reserving 19 first and requesting 20 second against a 20-unit position can leave only one unit for the second call.
effective exit 1 = min(request 1, open quantity)remaining 1 = open quantity − effective exit 1effective exit 2 = min(request 2, remaining 1)unreserved = max(open quantity − Σ effective exits, 0)This is a non-negative conceptual model. Recalculate after entries, fills, cancellations or order changes.The TP and SL created by one strategy.exit() call form a bracket: filling one cancels its sibling. Orders from multiple exit calls belong to a strategy.oca.reduce group by default, allowing remaining quantities to shrink after another order fills. Document explicit entry-side OCA groups separately.
Build two brackets that conserve the entry quantity
This educational example enters four units and allocates two units to each of two brackets. The entry condition is illustrative and makes no performance claim. Each exit call reserves two units, so requested exit quantity does not exceed the entry.
//@version=6
strategy("Two-bracket reservation audit", overlay = true, pyramiding = 1,
initial_capital = 100000, margin_long = 100, margin_short = 100)
int fastLength = input.int(20, "Fast length", minval = 1)
int slowLength = input.int(50, "Slow length", minval = 2)
float fast = ta.sma(close, fastLength)
float slow = ta.sma(close, slowLength)
bool enterLong = ta.crossover(fast, slow) and strategy.position_size == 0
if enterLong
strategy.entry("Long", strategy.long, qty = 4)
if strategy.position_size > 0
float average = strategy.position_avg_price
float stopPrice = average * 0.98
float targetOne = average * 1.02
float targetTwo = average * 1.04
strategy.exit("Bracket 1", from_entry = "Long", qty = 2,
limit = targetOne, stop = stopPrice)
strategy.exit("Bracket 2", from_entry = "Long", qty = 2,
limit = targetTwo, stop = stopPrice)
plot(fast, "Fast", color.aqua)
plot(slow, "Slow", color.orange)
plot(strategy.position_size, "Position size", display = display.data_window)Each bracket creates a TP and SL and reserves two units. Gaps, slippage and intrabar paths remain simulation assumptions.
For an audit ledger, record order ID, creation bar, limit/stop prices, requested qty, effective reserved qty, fill bar and exit ID. Change the requests to three and three to see the second call shrink in the calculator before checking the strategy result.
Triangulate chart, Data Window and List of Trades
- Visualize creation
Use labels or plots for the condition bar, limit, stop and entry ID.
- Inspect state variables
Trace strategy.position_size, opentrades, closedtrades and position_avg_price.
- Open List of Trades
Reconcile entry/exit IDs, timestamps, prices and quantities.
- Classify the surprise
Choose creation timing, pending state, reversal, reservation, OCA or FIFO.
- Hand off the fill path
If state and quantity reconcile but the bar or price still differs, continue in TV12 with the same version ID.
| Symptom | First check | Second check |
|---|---|---|
| A later stop is too small | Earlier exit reservations | OCA reduce and unreserved remainder |
| Bracket requests exceed the position | Call order and requested qty | Effective qty for every call |
| A cancelled order returns | Per-bar reissue condition | ID and strategy.cancel order |
| Reversal marker is large | Existing position size | Transaction versus new position |
| A different entry closes first | FIFO behavior | close_entries_rule |
Change one cause at a time so the diagnosis remains reproducible.
Keep one order-state row per event and version
- Are entry, order, exit and close responsibilities documented?
- Does every order ID and from_entry reference exist and express one intent?
- Do bracket reservations reconcile to the entry quantity?
- Are pyramiding, FIFO/ANY, OCA and recalculation settings recorded?
- Have you separated a price touch from an emulator fill?
- Were pre- and post-fix results exported over identical market, period and cost assumptions?
Finish the order audit with an order-state ledger that has one row per event. Store version ID, bar index, command, order ID, from_entry, state, requested qty, effective reservation, position before/after and OCA action, and keep corrected logic as a separate version.
The ledger passes when each entry unit is accounted for once as reserved, unreserved, filled or cancelled and the total reconciles with final position size. Link bar-and-fill-price explanations to the TV12 audit by version ID instead of forcing both problems into one table.
Sequential exit reservation
Apply three requested exit quantities in code order and see later requests shrink to the remaining position.
Sequential model: r1=min(b,a); r2=min(c,max(a−r1,0)); r3=min(d,max(a−r1−r2,0)). Total=r1+r2+r3; unreserved=max(a−total,0). Excludes fills, cancellations and reissued orders.
Frequently asked questions
Does limit plus stop in strategy.exit() create a stop-limit order?
No. In an exit call, they create two bracket legs: a take-profit limit and a stop-loss stop. Limit plus stop in an entry or order call creates a stop-limit order.
Why does a later stop close only a small part of the position?
An earlier strategy.exit() call may have reserved most of the open quantity. The later call can use only the unreserved remainder and can be reduced automatically.
Does pyramiding=1 guarantee only one same-direction order?
Not as a universal rule. Pyramiding primarily governs open trades from strategy.entry(). strategy.order() and multiple triggered price orders require separate review.
Does strategy.cancel() close an open position?
No. strategy.cancel() cancels an unfilled order with the selected ID. Closing an open position requires strategy.close(), strategy.close_all() or a suitable exit order.
Primary sources and verification links
- TradingView Pine Script — StrategiesOfficial order types, commands, reservations, OCA, partial exits and pyramiding.
- TradingView Pine Script — Strategies FAQOfficial bracket, multi-target, trailing-stop and troubleshooting examples.
- TradingView Pine Script — Execution modelHistorical and realtime execution, recalculation and rollback.
- TradingView Help — Strategy propertiesProperties for fills, recalculation and pyramiding.
Edited and published by: SG Group · Editorial approach: We prioritize official TradingView Help Center and Pine Script documentation, then use exchange, regulator and other primary materials for market and product context. Features, data, pricing and connection terms change, so verify the current interface and linked sources before use.
Important notice: This article provides general education about TradingView interfaces, charts, alerts, screeners, paper trading and Pine Script. It is not investment advice, a trading signal, a recommendation of any instrument, data source or broker, or a guarantee of future price or profit. Features, pricing, data, exchange coverage, notifications, order integrations and Pine Script behavior vary by plan, region, connection and date and may change. Before risking money, verify current TradingView documentation and the terms of the relevant data source and connected provider, then rehearse the workflow with fictional data or paper trading.

