Skip to content

How to open trades with limit orders in TradingView's Pine Script?

How to open trades with limit orders in TradingView’s Pine Script?

Section titled “How to open trades with limit orders in TradingView’s Pine Script?”

TL;DR
Use strategy.order(id, direction, limit=price) or strategy.entry(id, direction, limit=price) right after your signal—TradingView keeps the order active until price touches the limit or you cancel it.

DifficultyIntermediate
Time to implement15-20 min
CategoryOrder Management
//@version=5
strategy("Limit entry demo", overlay=true)
signalLong = ta.crossover(ta.sma(close, 20), ta.sma(close, 50))
limitPrice = close - 0.5 * syminfo.mintick
if signalLong
strategy.order("LongLimit", strategy.long, limit=limitPrice)
Tip. Limit prices must respect the instrument’s tick size. Use `math.round(price / syminfo.mintick) * syminfo.mintick` to align custom calculations.

Market orders can slip; limit orders let you control entry price. Pine can stage limit entries when signals arise, leaving the order active until price touches your level. That’s vital for breakout retests, pullback entries, or fade setups where execution price defines the edge.

  • Choose between strategy.order and strategy.entry for limit submissions.
  • Calculate limit prices relative to signals (e.g., below breakout highs or using ATR offsets).
  • Cancel or replace working limits when conditions change.
  • Combine limit entries with protective stops and risk management.
CallPurpose
strategy.order(id, direction, qty=?, limit=?, stop=?, oca_name=?, oca_type=?)Most flexible order call for limit entries.
strategy.entry(id, direction, limit=price)Shortcut that defaults quantity and handles pyramiding automatically.
strategy.cancel(id)Removes a pending limit order.
strategy.position_avg_priceUseful when adjusting follow-up stops/targets once the limit fills.
syminfo.mintickEnsures limit prices align with the instrument’s tick grid.
  1. Define the signal and limit price
    Decide when to stage the order and calculate a price relative to market structure.

    longSignal = ta.crossover(close, ta.highest(high, 50))
    pullback = close - 5 * syminfo.mintick
  2. Submit the limit order
    Use strategy.order if you need fine-grained control (quantity, OCO groups). Otherwise, strategy.entry keeps things concise.

    if longSignal
    strategy.entry("LongRetest", strategy.long, limit=pullback)
  3. Manage the order life cycle
    Cancel or replace stale orders and add linked exits once filled.

    if not longSignal and strategy.opentrades == 0
    strategy.cancel("LongRetest")
//@version=5
strategy("Breakout retest with limit", overlay=true, pyramiding=0, initial_capital=50_000)
length = input.int(40, "Breakout lookback", minval=5)
retestTicks = input.int(6, "Retest distance (ticks)", minval=1)
stopTicks = input.int(12, "Stop distance (ticks)", minval=1)
targetTicks = input.int(24, "Target distance (ticks)", minval=1)
float toPrice(int ticks) => ticks * syminfo.mintick
highestHigh = ta.highest(high, length)
longSignal = ta.crossover(high, highestHigh)
retestPrice = highestHigh - toPrice(retestTicks)
stopPrice = na
limitId = "LongRetest"
if longSignal
strategy.order(limitId, strategy.long, limit=retestPrice)
if strategy.opentrades > 0 and strategy.opentrades.entry_id(0) == limitId
stopPrice := strategy.position_avg_price - toPrice(stopTicks)
targetPrice = strategy.position_avg_price + toPrice(targetTicks)
strategy.exit("Long OCO", from_entry=limitId, stop=stopPrice, limit=targetPrice)
if close < highestHigh - toPrice(retestTicks * 2)
strategy.cancel(limitId)
plot(highestHigh, "Breakout high", color=color.new(color.green, 60))
plot(retestPrice, "Limit price", color=color.new(color.blue, 0))
Why this works.
  • Signals queue a limit below the breakout high, capturing retests without chasing.
  • Once filled, the script attaches stop and target orders using tick-based distances.
  • Stale limits get cancelled if price collapses, keeping the order book clean.
  • Use unique IDs per limit order. If you reuse an ID, Pine modifies the existing order rather than creating a new one.
  • Combine OCO groups (oca_name, oca_type) when staging both long and short limits simultaneously.
  • Verify that limit prices are on the correct side of the market: longs must sit below current price, shorts above.
  • For multi-entry strategies, check strategy.opentrades to avoid overloading the order book with redundant limits.

If the limit price equals or is worse than current price, TradingView submits a marketable limit order that fills immediately. Nudge the price further away or use close - syminfo.mintick to ensure it’s better than market.

The limit never cancels even after the trend changes

Section titled “The limit never cancels even after the trend changes”

Manually cancel limits when conditions invalidate the setup (strategy.cancel(id)). Otherwise, TradingView keeps the order active until filled or the script issues a cancel.

Can I stage multiple contracts at different prices?

Section titled “Can I stage multiple contracts at different prices?”

Yes. Submit separate strategy.order calls with different IDs and limit prices. You can ladder into positions by varying the tick distance per order.

  • strategy.order / strategy.entry with limit= gives you full control over entry price.
  • Calculate limit prices relative to signals (retests, ATR offsets) to improve fills.
  • Always manage the order life cycle—cancel or replace limits when they no longer apply.
  • Combine limit entries with OCO exits to automate risk as soon as fills occur.

Adapted from tradingcode.net, optimised for Algo Trade Analytics users.