Pine Script v6 order lifecycle

Pine Script Limit Orders: Placement, Fills, Cancellation and Costs

Create a Pine Script limit order by passing an absolute price to strategy.entry() with limit. A buy limit accepts that price or lower; a sell limit accepts that price or higher. An unfilled order stays pending until it fills or you cancel it with strategy.cancel() using the same order ID. These commands operate on TradingView simulated orders, not a connected brokerage account.

Adapt the Limit Order Example

Which side of the market should the limit use?

The limit argument is a price, not a distance in ticks. For a pullback buy, subtract a tick offset from the reference price. For a rally sell, add it. A buy limit above the current market, or a sell limit below it, is already favorable to execute and can fill on the next available tick. It is not a breakout trigger. Supplying both stop and limit to strategy.entry() creates a stop-limit order, a different lifecycle.

Constructed case: current price 100Order intentExpected behavior
Buy limit 99Buy at 99 or lowerWait for an eligible price after submission.
Buy limit 101Pay no more than 101Already executable at the current price; no need to rise to 101.
Sell limit 101Sell at 101 or higherWait for an eligible price after submission.
Sell limit 99Accept 99 or higherAlready executable at the current price; no need to fall to 99.

Minimal strategy: submit once and expire after three bars

This diagnostic strategy submits one long order on a chosen bar index, freezes its price and gives it three subsequent bars to fill. If still pending at the third close, it cancels the order. A filled position gets a timed market exit only to complete the test. There is no trading signal or protective stop. Use a standard candlestick chart and a symbol whose price and contract value fit the test capital.

  • Use the Data Window to choose a submission index with at least several following bars. Record its timestamp too: indices can shift when the loaded dataset changes.
  • The code requires a positive calculated limit and intentionally places only one order. No P marker means the chosen bar is unavailable or the positive-price guard failed.
  • With submission on bar 100 and lifetime 3, the order can fill during bars 101, 102 or 103. Cancellation happens at the close of 103 only if it remains unfilled.
  • If a fill is first observed at the close of 101, holdBars = 2 submits the exit at the close of 103. Under these settings its market fill is on the next available tick, normally the open of 104.
  • The pending flag is local bookkeeping for this single-entry example. If the emulator rejects an order because of capital or symbol constraints, the flag alone does not prove that a pending order exists.
Pine v6 lifecycle example. P marks submission and X marks cancellation. The blue line retains the requested price; the Data Window exposes pending state.pinescript
//@version=6
strategy("One limit order lifecycle", overlay = true, initial_capital = 100000, pyramiding = 0, commission_type = strategy.commission.percent, commission_value = 0.1, slippage = 1, backtest_fill_limits_assumption = 0, process_orders_on_close = false, calc_on_every_tick = false, calc_on_order_fills = false, use_bar_magnifier = false)
submitBar = input.int(100, "Submission bar index", minval = 0)
offsetTicks = input.int(4, "Buy offset in ticks", minval = 1)
expiryBars = input.int(3, "Pending lifetime in bars", minval = 1)
holdBars = input.int(2, "Bars after observing the fill", minval = 1)

var float limitPrice = na
var int submittedBar = na
var int observedFillBar = na
var bool pending = false
bool submitted = false
bool cancelled = false

if bar_index == submitBar and strategy.position_size == 0
    limitPrice := math.round_to_mintick(close - offsetTicks * syminfo.mintick)
    if limitPrice > 0
        strategy.entry("L", strategy.long, qty = 1, limit = limitPrice)
        submittedBar := bar_index
        pending := true
        submitted := true

if pending and strategy.position_size > 0
    pending := false
    observedFillBar := bar_index

if pending and bar_index - submittedBar >= expiryBars
    strategy.cancel("L")
    pending := false
    cancelled := true

if strategy.position_size > 0 and bar_index - observedFillBar == holdBars
    strategy.close("L")

plot(limitPrice, "Requested limit", color = color.blue, style = plot.style_linebr)
plot(bar_index, "Bar index", display = display.data_window)
plot(pending ? 1 : 0, "Pending at calculation", display = display.data_window)
plotshape(submitted, title = "Submitted", text = "P", style = shape.labelup, location = location.belowbar, color = color.blue, textcolor = color.white)
plotshape(cancelled, title = "Cancelled", text = "X", style = shape.labeldown, location = location.abovebar, color = color.orange, textcolor = color.black)

Check the lifecycle against explicit expected outcomes

Use these constructed cases as acceptance criteria, not as claimed chart observations. Assume bar 100 closes at 100, the minimum tick is 0.25 and the offset is 4 ticks. The requested buy limit is 100 - 4 × 0.25 = 99. Verification is zero, capital is sufficient and the order is submitted at the close of 100.

  • Removing the entry condition on later bars does not cancel the existing order. The script must call the cancellation command.
  • Repeated calls with the same entry ID and a changing limit can update the pending order. That is a moving-price rule; this example calls entry only once.
  • strategy.cancel("L") removes an unfilled order. strategy.close("L") submits a market exit for an open trade. Choose according to order state.
Following prices or eventExpected resultWhat the case tests
Bar 100 itself had a low of 98No retrospective fill on bar 100.Submission time comes after that historical low.
Bar 101 opens at 100 and later reaches 99A simulated entry at 99 is eligible.The order exists when the limit is reached.
Bar 101 opens at 98 after the previous close of 100The gap can fill the buy at 98.A favorable gap can improve the fill price.
Bars 101, 102 and 103 all stay above 99Cancel at the close of 103; a touch on 104 cannot fill that cancelled order.Expiry removes an unfilled entry.
Bar 103 reaches 99 before closingThe fill takes precedence; the pending flag clears and no X is produced.Close-time cancellation cannot undo an earlier fill.

Historical paths and Bar Magnifier answer different questions

Without Bar Magnifier, the emulator infers an OHLC path: open to the nearer extreme, then the other extreme, then close. This is an assumption about sequence. Bar Magnifier uses lower-timeframe bars when available. Neither supplies an exchange order queue. Keep calculation settings fixed when comparing fills; changing calc_on_order_fills at the same time changes when the script can react.

  • Run the example first with use_bar_magnifier = false, then change only that property if available on your account. Save the trade list and settings for both runs.
  • For this single resting entry, unchanged results are a valid outcome. Bar Magnifier is more consequential when competing price levels or intrabar reactions depend on event order.
  • Do not infer real partial fills, queue priority or sufficient liquidity from an OHLC touch. Those details are absent from this test.
Test settingConstructed comparisonInterpretation
Default historical pathO=100, H=102, L=95, C=101 gives open → high → low → close.The open is 2 from the high and 5 from the low. A pending buy at 99 is encountered on the descent.
Bar Magnifier enabledInspect the available intrabars around the same 99 entry.They can change fill timing and the order of events within the parent bar. A single resting limit may still fill in both runs.
Close-only expiry unchangedCompare the cancellation decision at the parent bar close.Bar Magnifier does not turn this code into an intrabar cancellation algorithm.
Earlier history lacks intrabarsCheck whether the selected period has lower-timeframe coverage.The documented 200,000 lower-bar limit can leave older trades unaffected.

Model verification and costs separately

Price verification makes a historical limit fill require movement beyond its level. With a 99 buy limit, a 0.25 tick and verification of 2 ticks, the threshold is 98.50; a low of 98.75 is insufficient. The verified fill retains the requested limit price, so this is a sensitivity assumption rather than an order-book reconstruction. The sample starts with verification zero. Test another setting separately.

  • Independent stock example: 100 shares filled at 99 and sold at an already slippage-adjusted 101 produce gross P&L of 100 × (101 - 99) = 200.
  • At 0.1% commission per side, fees are (100 × 99 + 100 × 101) × 0.001 = 20. Net is 180 before any other costs. This is arithmetic, not the output of the one-unit sample.
  • Assumptions: account and quote currency match, point value is 1, and no borrow fees or taxes apply. Futures multipliers, currency conversion and other charges require their own calculation.
AssumptionMeaning in this exampleBoundary
commission_value = 0.1 with percent modeCharge 0.1% of each executed entry and exit value.This is an illustrative rate, not a broker quote.
slippage = 1Apply one tick to the timed market exit.This setting applies to market and stop orders, not a fixed penalty on the resting limit entry.
Verify limit price = 0 or 2 ticksCompare touch-based and deeper-penetration fills.This does not model queue position or exchange liquidity.

Validate the intended behavior before adapting the order rule

Keep one fill case and one cancellation case with their symbol, timeframe, timestamp, inputs and strategy properties. Compare P, X, the Data Window and the trade list. Request changes to the smallest script that reproduces the disagreement. A syntax pass establishes that source can be accepted; it does not establish that a chart touch occurred after submission or that a real broker would fill it.

  • No trade: check that P exists, the limit was reached while pending, verification is satisfied, and initial capital covers the position with the instrument multiplier and margin.
  • Unexpected immediate entry: check whether the limit was already favorable to execute and whether the next bar opened through it.
  • Unexpected later entry: inspect pending expiry and whether the order was modified on intervening calculations.
Where Pineify fits

Pine Script AI Coding Agent

Give Pineify this minimal strategy, your intended expiry rule and the expected fill or cancellation case. Ask the agent to edit the code and request a syntax check where your plan supports it. Compare the result in TradingView using the same data and properties.

Adapt the Limit Order Example

Frequently asked questions

Technical education, not investment advice. Numerical cases are constructed examples, not recorded trades or performance claims. This diagnostic strategy has no protective stop. Simulated fills and syntax validation do not establish live execution, profitability or suitability.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.