Skip to main content

Getting Your Pine Script Entry Prices Right (It's Trickier Than You Think)

· 4 min read
Getting Your Pine Script Entry Prices Right

So you've been writing Pine Script strategies and noticed something weird - the entry price your script thinks it got isn't matching what you see in TradingView's Strategy Tester. Don't worry, you're not going crazy. This happens to pretty much everyone when they start out.

Let me explain what's going on and how to actually get the right entry price in your code.

Why Your Entry Prices Are Off

Here's the thing that trips up most people: when you place an order in Pine Script, it doesn't get filled immediately. By default, your order gets filled at the open of the next bar, not the current one where your condition triggered.

So let's say you have a condition that triggers at 3 PM when the price is $100. Your script says "buy now!" but the actual fill happens at 3:05 PM (next bar) when the price might be $101. Your script still thinks it bought at $100, but reality says $101.

This is why your stop losses and take profits sometimes look wonky in backtests.

The Two Main Ways Orders Get Processed

The Best Pine Script Generator

Option 1: Next Bar Open (Default)

  • Your condition triggers on the current bar
  • Order fills at the open of the next bar
  • There's usually a price difference

Option 2: Current Bar Close

  • Add process_orders_on_close=true to your strategy
  • Orders fill at the close of the current bar
  • More accurate for backtesting, but not always realistic for live trading

How to Actually Get the Right Entry Price

Okay, so how do you capture what price you actually got filled at? Here are the methods that actually work:

Method 1: Use strategy.position_avg_price

This is probably the easiest way. Just remember it's only available after your entry bar closes:

entryPrice = strategy.position_avg_price

Method 2: Set calc_on_order_fills=true

This makes your script recalculate immediately after an order fills, so you can grab the entry price right away:

strategy("My Strategy", calc_on_order_fills=true)

Method 3: Use the opentrades functions

This grabs the entry price of your most recent trade:

entryPrice = strategy.opentrades.entry_price(strategy.opentrades - 1)

A Real Example That Actually Works

Here's a simple strategy that properly captures the entry price:

//@version=5
strategy("Entry Price Done Right", overlay=true, calc_on_order_fills=true)

// Basic setup
atrLength = input(14, "ATR Length")
atrMultiplier = input.float(2.0, "ATR Multiplier")

// Calculate our ATR for stops
atr = ta.atr(atrLength) * atrMultiplier

// Simple moving average crossover entry
ma = ta.sma(close, 20)
buySignal = ta.crossover(close, ma)

// Enter the trade
if buySignal
strategy.entry("Long", strategy.long)

// Get our actual entry price
var float actualEntryPrice = na
if strategy.position_size > 0 and strategy.position_size[1] == 0
actualEntryPrice := strategy.position_avg_price

// Set our stops based on actual entry, not the signal bar
if strategy.position_size > 0 and not na(actualEntryPrice)
stopLoss = actualEntryPrice - atr
takeProfit = actualEntryPrice + (atr * 2)
strategy.exit("Exit", "Long", stop=stopLoss, limit=takeProfit)

// Plot so we can see what's happening
plot(actualEntryPrice, "Actual Entry", color=color.yellow, linewidth=2)

Things That'll Save You Headaches

Always backtest with realistic settings. If you're planning to trade this live, don't use process_orders_on_close=true unless you're actually planning to trade at bar closes.

Check your position size logic. I use strategy.position_size > 0 and strategy.position_size[1] == 0 to detect when we just entered a position. This prevents the entry price from getting overwritten.

Plot your entry prices. Seriously, just plot them on the chart so you can visually verify everything looks right.

Wrapping Up

Getting entry prices right in Pine Script isn't intuitive at first, but once you understand that orders fill on the next bar (unless you change the settings), everything starts making sense.

The key is using strategy.position_avg_price or the opentrades functions to capture what price you actually got, not what price triggered your signal. Your stop losses and take profits will thank you for it.

And remember - if something looks weird in your backtest, it probably is. Don't ignore those little discrepancies. They usually point to something important about how your strategy actually works versus how you think it works.