Skip to main content

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

· 7 min read
Getting Your Pine Script Entry Prices Right

You've been coding Pine Script strategies and something's driving you nuts - the entry price your script thinks it got doesn't match what TradingView's Strategy Tester shows. Trust me, you're not losing your mind. This confusion hits pretty much everyone when they start building their first trading strategies.

I've been there too, staring at my screen wondering why my carefully calculated stop losses were triggering at weird prices. After months of debugging and testing different approaches, I finally figured out what's really happening behind the scenes.

Let me walk you through the real mechanics of Pine Script order execution and show you exactly how to capture accurate entry prices in your strategies.

The Hidden Truth About Pine Script Order Execution

Here's what nobody tells you upfront: when your Pine Script strategy triggers a buy or sell signal, that order doesn't get filled instantly on the same bar. By default, Pine Script fills your order at the opening price of the next bar.

Think about it like this - you're watching a 5-minute chart, and at 2:15 PM your moving average crossover condition triggers when the price is $150. Your brain says "I'm buying at $150!" But Pine Script actually fills your order at 2:20 PM (the next 5-minute bar) when the opening price might be $152.

This delay is actually realistic - in real trading, you can't magically buy at the exact price where your signal triggered. There's always some slippage and delay.

But here's where it gets tricky for backtesting: your script still "thinks" it bought at $150, while the Strategy Tester correctly shows the fill at $152. This mismatch is why your stop losses, take profits, and risk calculations sometimes look completely wrong.

Understanding Pine Script's Order Processing Methods

The Best Pine Script Generator

Pine Script gives you two main ways to handle order execution, and understanding both is crucial for accurate backtesting:

Method 1: Next Bar Open (Default Behavior)

  • Signal triggers on current bar
  • Order fills at next bar's opening price
  • Realistic for most trading scenarios
  • Creates the price mismatch we discussed

Method 2: Current Bar Close Processing

  • Add process_orders_on_close=true to your strategy declaration
  • Orders fill at the close of the current bar
  • More accurate for backtesting purposes
  • Less realistic for actual live trading

Most beginners don't realize they can control this behavior, which leads to a lot of confusion when their backtest results don't match their expectations.

Three Reliable Methods to Capture Actual Entry Prices

After testing dozens of different approaches, I've found three methods that consistently work for getting the real entry price in your Pine Script strategies:

This is my go-to method because it's simple and reliable. The strategy.position_avg_price function returns the average price of your current position, which reflects the actual fill price:

actualEntryPrice = strategy.position_avg_price

The only catch is that this value is only available after your entry bar has closed. But for most strategies, this timing works perfectly fine.

Method 2: Enable calc_on_order_fills

This approach makes your script recalculate immediately after any order gets filled, allowing you to capture the entry price right when it happens:

strategy("My Strategy", calc_on_order_fills=true)

When you enable this setting, Pine Script will run your script again every time an order fills, giving you instant access to the actual fill price through strategy.position_avg_price.

Method 3: Using opentrades Functions

For more advanced scenarios, you can access the entry price of specific trades using the opentrades namespace:

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

This method is particularly useful when you're managing multiple positions or need to access historical trade data.

Complete Working Example: Entry Price Done Right

Here's a full strategy that demonstrates proper entry price handling. I've used this exact approach in my own trading strategies:

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

// Input parameters
atrPeriod = input.int(14, "ATR Period", minval=1)
atrMultiplier = input.float(2.0, "ATR Multiplier", minval=0.1)
maLength = input.int(20, "Moving Average Length", minval=1)

// Calculate indicators
atr = ta.atr(atrPeriod) * atrMultiplier
ma = ta.sma(close, maLength)

// Entry condition
longCondition = ta.crossover(close, ma)

// Execute trade
if longCondition
strategy.entry("Long", strategy.long)

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

// Set exit levels based on actual entry price
if strategy.position_size > 0 and not na(realEntryPrice)
stopLevel = realEntryPrice - atr
profitLevel = realEntryPrice + (atr * 1.5)
strategy.exit("Exit Long", "Long", stop=stopLevel, limit=profitLevel)

// Visual confirmation
plot(realEntryPrice, "Actual Entry Price", color=color.yellow, linewidth=2, style=plot.style_line)
plot(ma, "Moving Average", color=color.blue)

This strategy properly captures the actual fill price and uses it for stop loss and take profit calculations, eliminating the confusion between signal price and execution price.

Essential Best Practices for Accurate Backtesting

Through trial and error (and a few blown demo accounts), I've learned these practices are crucial for reliable strategy development:

Match Your Backtest Settings to Reality If you plan to trade your strategy live, don't use process_orders_on_close=true unless you're actually planning to place orders at bar closes. The more realistic your backtest, the better your live results will be.

Implement Proper Position Detection Logic I use strategy.position_size > 0 and strategy.position_size[1] == 0 to detect fresh position entries. This prevents the entry price from being overwritten on subsequent bars and ensures you capture the price only once per trade.

Always Plot Your Entry Prices This might seem obvious, but plotting your actual entry prices on the chart is invaluable for debugging. You'll immediately spot any issues with your entry price logic just by looking at the chart.

Consider Slippage in Your Calculations Real trading involves slippage - the difference between expected and actual fill prices. While Pine Script backtesting doesn't automatically include slippage, you can manually adjust your entry prices to account for it in your calculations.

Advanced Techniques for Complex Strategies

For those working on more sophisticated strategies, here are some advanced considerations:

Multiple Position Management When managing multiple positions or scaling in/out of trades, you'll need to track entry prices for each position separately. The opentrades functions become particularly useful here.

Partial Fill Scenarios In live trading, large orders might get partially filled at different prices. While Pine Script backtesting doesn't simulate this, strategy.position_avg_price will give you the average price across all fills, which is exactly what you'd get in reality.

Time-Based Entry Tracking Sometimes you need to know not just the price but also when your entry occurred. Combine entry price tracking with strategy.opentrades.entry_time() for complete trade records.

If you're serious about improving your Pine Script skills, I highly recommend checking out these related guides:

The Bottom Line

Getting entry prices right in Pine Script isn't just about writing cleaner code - it's about building strategies that actually work when you put real money on the line. The difference between thinking you bought at $100 and actually buying at $102 can make or break a trading strategy.

The key insight is understanding that Pine Script's default behavior (filling orders on the next bar) is actually more realistic than filling at the signal price. Once you accept this and use the proper functions like strategy.position_avg_price to capture actual fill prices, your backtests become much more reliable.

Remember, every successful trader I know has gone through this same learning curve. The confusion you're feeling about entry prices is actually a sign that you're paying attention to the details that matter. Keep questioning those little discrepancies in your backtests - they're usually pointing you toward important truths about how your strategy really performs.

Your future trading self will thank you for taking the time to get this right.