Skip to main content
On this page

strategy.exit() Guide: Stop Loss, Take Profit & Trailing Stops

· 7 min read
Pineify Team
Pine Script and AI trading workflow research team

strategy.exit() creates price-based exit orders in a Pine strategy: stop loss, take profit, or a trailing stop. These are orders for TradingView's broker emulator, not an assurance of live execution at the requested price. A bracket can close all or part of the entry it references.

Mastering Pine Script strategy.exit: The Complete Guide to Automated Trade Exits

What strategy.exit Does for Your Trades​

Use strategy.exit() for stop and limit exits. Use strategy.close() or strategy.close_all() when the intended action is a market close. A gap can produce a fill different from the order price; inspect the Strategy Tester trade list rather than assuming the plotted level is the fill.

Key Advantages​

  • Bracket orders: One exit call can create a stop and a target. Filling one cancels the other order from that bracket.
  • Partial exits: qty or qty_percent controls the amount reserved for an exit. Several calls can reserve separate portions of a position; later calls cannot exit quantities already reserved by earlier calls.
  • Trailing exits: A trailing order has an activation threshold and a following distance. Both need explicit units.

For an introduction to entries, see Pine Script strategy development. Pineify's feature overview describes its available building workflows; always inspect generated exit logic and test it in TradingView.

strategy.exit Function Syntax and Parameters​

The Best Pine Script Generator

The commonly used function parameters are:

strategy.exit(id, from_entry, qty, qty_percent, profit, limit, loss, stop, trail_price, trail_points, trail_offset, oca_name, comment, comment_profit, comment_loss, comment_trailing, alert_message, alert_profit, alert_loss, alert_trailing, disable_alert) → void

Most parameters are optional, but an exit requires a valid price-based condition or trailing-stop parameter pair:

Core Parameters:

  • id: Required. A unique name for your exit order.
  • from_entry: Links this exit to a specific entry. If omitted, it can apply to entries regardless of their IDs; understand its persistence when later entries are placed.
  • qty/qty_percent: How much of the position to exit.

Price-Based Exits:

  • profit/limit: Take profit in ticks from entry, or an absolute price.
  • loss/stop: Stop loss in ticks from entry, or an absolute price.

Advanced Features:

  • trail_price: Absolute activation price. trail_points: Activation distance from entry, in ticks. trail_offset: Following distance after activation, also in ticks. Pair the offset with an activation parameter.
  • oca_name: Names an order-cancels-all group. Exit orders use reduce behavior by default; reservations and fills affect the remaining order quantities.

Practical Implementation Example​

This MACD example places a bracket using the average entry price once the strategy observes an open position:

//@version=5
strategy("MACD Exit Strategy", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10)

// MACD calculation
fastMA = ta.ema(close, 12)
slowMA = ta.ema(close, 26)
macd = fastMA - slowMA
signal = ta.ema(macd, 9)
histogram = macd - signal

// Entry condition: MACD histogram crosses above zero
longCondition = ta.crossover(histogram, 0)

if longCondition
strategy.entry("Long", strategy.long, comment="MACD Bullish Cross")

// Fixed percentages of the average entry price, not the current bar
if strategy.position_size > 0
strategy.exit("Long Exit", "Long",
stop = strategy.position_avg_price * 0.97,
limit = strategy.position_avg_price * 1.05)

The requested stop is 3% below the average entry price and the target is 5% above it. This is a long-only illustration with no added entries while a position is open under the default pyramiding setting.

With the default calculation settings, the entry normally fills on the next available tick and the script observes that position at its next scheduled calculation. The bracket is therefore not present immediately at the entry fill. An initial bracket using loss/profit ticks can be submitted with the entry when immediate order placement is required. Enabling calc_on_order_fills changes recalculation timing and can create optimistic historical results; it is not an automatic realism improvement.

Trailing Stops: Activation Versus Offset​

This separate example isolates the trailing order rather than combining competing stop types:

//@version=5
strategy("MACD Trailing Exit Example", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10)
[macdLine, signalLine, histogram] = ta.macd(close, 12, 26, 9)
longCondition = ta.crossover(histogram, 0)
if longCondition and strategy.position_size == 0
strategy.entry("Long", strategy.long)
strategy.exit("Trail", "Long", trail_points=100, trail_offset=50)

Here, 100 ticks is the favorable move from entry needed for activation; 50 ticks is the trailing distance after activation. Convert either to a price distance by multiplying by syminfo.mintick. Neither number is a percentage. Before activation, this trailing-only example has no protective stop. It demonstrates parameter behavior, not a complete risk-management system.

Verify Orders Trade by Trade​

Use TradingView's strategy documentation when interpreting the broker emulator. For each test, record the symbol, timeframe, date range, code version, position sizing, commission, slippage, and calculation settings.

  1. Find an entry in the Strategy Tester trade list and record its actual fill price and time.
  2. Calculate the expected stop/target or trailing activation level using that fill and the symbol's tick size.
  3. Check when the exit order was created, not just when its price was touched. An order cannot fill before it exists.
  4. Compare the reported exit fill with the level, allowing for gaps, slippage, and the emulator's historical intrabar assumptions. Use Bar Magnifier where available to inspect fills with lower-timeframe data.
  5. For partial exits, verify each call's reserved quantity and the remaining position after each fill.

No win-rate, trade-count, or drawdown result is claimed for these examples. Compilation verifies syntax; it does not validate execution realism or profitability.

Advanced Exit Techniques​

Scaled exits: Multiple targets can close separate portions of a position. Set quantities deliberately and inspect reservations; do not assume every exit call controls the entire position.

Volatility-based stops: An ATR-derived price level can adapt to volatility. Decide whether the ATR is fixed at entry or recalculated, and whether the stop may loosen. These choices change the strategy and require separate evaluation.

Frequently Asked Questions​

How do I set a stop loss and take profit using strategy.exit()?

loss and profit are tick distances from entry. stop and limit are absolute prices. A bracket exit creates the corresponding orders for the entry ID and quantity it controls.

What is the difference between trail_price, trail_points, and trail_offset?

trail_price is an absolute activation price. trail_points is the favorable activation distance from entry in ticks. trail_offset is the distance the stop follows behind the best price after activation, also in ticks.

Can strategy.exit() handle partial position exits?

Yes. Use qty or qty_percent, and inspect how multiple calls reserve portions of the position. An exit cannot close quantities already reserved by another exit call.

What does the from_entry parameter do?

It selects entries with the specified entry ID. Without it, an exit can apply across entry IDs. Use explicit IDs when entries need different exits.

Does calc_on_order_fills control whether an exit can fill intrabar?

No. Existing stop and limit orders can fill intrabar in the broker emulator. calc_on_order_fills controls extra script recalculations after fills. Check order creation time, tick size, reservations, gaps, and emulator assumptions when an exit differs from your expectation.