Pine Script: How to Check if an Open Position Exists?

Introduction: Understanding Open Position Detection in Pine Script

Managing positions is fundamental to building robust trading strategies in Pine Script. While executing orders is a core function, knowing the current state of your strategy’s exposure – whether a position is currently open and its size – is equally critical.

Why Checking for Open Positions is Crucial in Trading Strategies

Reliably determining if your strategy holds an open position is essential for several reasons:

  • Preventing Over-Leveraging: Avoid entering additional trades in the same direction if a maximum position size has already been reached.
  • Executing Exit Logic Correctly: Ensure exit conditions only trigger when a position is active.
  • Implementing Reversal Strategies: Gracefully handle signals that require exiting a current position before entering the opposite direction.
  • Managing Stop Losses and Take Profits: Apply SL/TP orders correctly to only active positions.
  • Sophisticated Scaling: Manage scaling in or out of a position based on current size.

Without accurate position tracking, a strategy can suffer from unintended entries, incorrect exits, or failure to manage risk effectively.

Brief Overview of Pine Script’s Capabilities for Position Management

Pine Script provides built-in variables and functions specifically designed for strategy backtesting and position management. These tools offer real-time information about the strategy’s current state, including open positions, historical trades, and account equity. The most direct way to query the open position status is through a dedicated built-in variable.

Methods for Detecting Open Positions in Pine Script

Pine Script offers straightforward ways to check for the existence and size of an open position within a strategy script. The primary method relies on a specific built-in variable that reflects the current state of the strategy’s simulated trades.

Using strategy.position_size to Determine Position Status

The most direct and commonly used method is checking the value of the strategy.position_size built-in variable.

  • strategy.position_size returns the number of contracts, shares, lots, or units currently held by the strategy.
  • A positive value indicates a long position (number of units held long).
  • A negative value indicates a short position (number of units held short).
  • A value of 0 indicates that there is no open position.

Therefore, to check if any position (long or short) is open, you simply check if strategy.position_size != 0. To check specifically for a long position, use strategy.position_size > 0. For a short position, use strategy.position_size < 0.

This variable is updated at the end of each bar based on the trades executed during that bar’s calculation. It represents the net position size across all entries and exits for the current symbol.

Employing strategy.opentrades and strategy.closedtrades for Advanced Analysis

While strategy.position_size tells you the aggregate size, strategy.opentrades and strategy.closedtrades provide access to arrays containing detailed information about individual trades. strategy.opentrades is an array of objects representing trades that are currently open. strategy.closedtrades contains information about trades that have been closed.

Checking array.size(strategy.opentrades) > 0 can also technically indicate an open position. However, this is generally overkill just to check if any position exists. strategy.position_size is simpler and more performant for that specific purpose. These arrays are more useful when you need to inspect individual trade properties like entry price, entry time, or specific entry comments.

For the sole purpose of knowing if a position exists (long or short), strategy.position_size is the canonical and most efficient method.

Leveraging Order Execution Information to Track Position Changes

Less common for simply checking if a position exists now, but sometimes useful for understanding how the current position was reached, is tracking the successful execution of strategy.entry, strategy.exit, and strategy.order calls. These functions return a bool indicating whether the order was successfully placed in the backtesting engine on that bar.

However, relying solely on tracking order calls to determine the current position state is prone to errors. Orders might be partially filled, or subsequent orders could alter the position size. strategy.position_size automatically accounts for all these interactions and always provides the accurate, net position size at the end of the bar’s calculation. Therefore, always use strategy.position_size to check the current position status rather than trying to infer it from order history within the current script execution.

Practical Examples: Implementing Open Position Checks in Trading Strategies

Let’s look at practical applications of strategy.position_size in strategy logic.

Simple Example: Exiting a Position Based on a Condition and Open Position Check

This example shows how to ensure an exit signal only attempts to close a position if one is actually open.

//@version=5
strategy("Simple Position Check Exit", overlay=true)

entryCondition = close > ta.sma(close, 20)
exitCondition = close < ta.sma(close, 10)

// --- Entry Logic ---
// Check if no position is open before entering long
if entryCondition and strategy.position_size == 0
    strategy.entry("Long", strategy.long)

// --- Exit Logic ---
// Check if a long position is open before exiting
if exitCondition and strategy.position_size > 0
    strategy.close("Long", comment="Exit")

// This simple check `strategy.position_size > 0` ensures we only issue a `strategy.close`
// command when there's a corresponding open long position to close.

Complex Example: Scaling into a Position While Monitoring Existing Trades

Here, we use strategy.position_size to determine if we already have a position before adding to it, effectively scaling in.

//@version=5
strategy("Scaling In Example", overlay=true)

entryCondition = close > ta.sma(close, 50)
scalingCondition = close > strategy.position_avg_price // Example: scale if price moves favourably
maxPositionSize = 3 // Max units/contracts

// --- Entry Logic ---
// Initial entry if no position is open
if entryCondition and strategy.position_size == 0
    strategy.entry("Long", strategy.long, qty = 1)

// Scaling in: If a long position is open AND scaling condition is met AND we are below max size
// We calculate remaining capacity based on current size.
if strategy.position_size > 0 and scalingCondition and strategy.position_size < maxPositionSize
    qtyToScale = math.min(1, maxPositionSize - strategy.position_size) // Add 1 unit, but not exceeding max
    strategy.entry("Long", strategy.long, qty = qtyToScale, comment = "ScaleIn")

// --- Exit Logic (Simplified) ---
// Exit if price falls below a trailing stop or similar logic...

Example: Reversing Position When Opposite Signal Appears and Position Exists

This pattern is common in strategies that always want to be in the market, either long or short. When a signal for the opposite direction appears, the current position must first be closed.

//@version=5
strategy("Reversal Strategy with Position Check", overlay=true, initial_capital=10000, commission_type=strategy.commission.percent, commission_value=0.1)

longCondition = ta.ema(close, 10) > ta.ema(close, 30)
shortCondition = ta.ema(close, 10) < ta.ema(close, 30)

// --- Reversal Logic ---
// If currently long AND short signal appears:
// 1. Close the long position.
// 2. Enter the short position.
if strategy.position_size > 0 and shortCondition
    strategy.close("Long", comment="Reverse to Short")
    // The strategy engine processes closes before entries on the same bar.
    // The short entry will happen after the long exit is processed.
    strategy.entry("Short", strategy.short)

// If currently short AND long signal appears:
// 1. Close the short position.
// 2. Enter the long position.
if strategy.position_size < 0 and longCondition
    strategy.close("Short", comment="Reverse to Long")
    strategy.entry("Long", strategy.long)

// --- Initial Entries (if flat) ---
// If no position and long signal
if strategy.position_size == 0 and longCondition
    strategy.entry("Long", strategy.long)

// If no position and short signal
if strategy.position_size == 0 and shortCondition
    strategy.entry("Short", strategy.short)

// Note: In reversal strategies, the explicit `strategy.position_size == 0` check
// is often not strictly necessary for the initial entry *if* you structure the
// logic such that reversal conditions are checked first. However, including
// it can make the logic flow clearer for initial trades.

Best Practices and Considerations

Using strategy.position_size is straightforward, but keep these points in mind for robust strategies:

Accounting for Slippage and Commission in Position Size Calculations

strategy.position_size in backtesting reflects the size intended by your entry/exit orders, adjusted for any partial fills if applicable (though typically less complex in standard strategy backtesting than real live trading). It generally represents the number of units held before factoring in the costs of closing the trade (slippage, commission). Realized profit/loss and equity calculations do account for these costs upon trade closure, but the strategy.position_size variable itself focuses purely on the number of units currently open.

Handling Multiple Entries and Exits within a Single Position

strategy.position_size automatically aggregates the size from multiple entries and exits within the same direction. If you enter long with 1 contract, strategy.position_size becomes 1. If you later add another 2 contracts, it becomes 3. If you then exit 1 contract, it becomes 2. This cumulative nature is usually exactly what you need when checking the overall exposure.

Optimizing Code for Efficiency and Accuracy in Position Tracking

strategy.position_size is a highly efficient built-in variable. Accessing it has negligible performance cost. The key to accuracy is understanding that its value represents the state at the end of the previous bar’s processing or, during the current bar, reflects the state based on orders processed so far according to Pine Script’s execution model (e.g., strategy.close before strategy.entry on the same bar with default settings). For most conditional checks at the start of a new bar, its value is reliably the position size as of the market close of the previous bar.

Avoid complex logic attempting to manually track position size using variables and counters based on order fills. This is error-prone and replicates functionality already provided reliably by strategy.position_size.

Conclusion: Mastering Open Position Detection for Enhanced Trading Strategies

Checking whether an open position exists is a fundamental requirement for building sophisticated and safe trading strategies in Pine Script. It allows your script to make informed decisions based on its current exposure, preventing erroneous trades and enabling more complex logic like scaling or reversals.

Recap of Techniques for Checking Open Positions

The primary method for checking the existence and size of an open position is using the strategy.position_size built-in variable:

  • strategy.position_size != 0: Any position (long or short).
  • strategy.position_size > 0: Long position.
  • strategy.position_size < 0: Short position.

While strategy.opentrades provides more detail about individual open trades, strategy.position_size is the most direct and efficient way to query the overall position status.

Future Enhancements and Advanced Strategies Using Position Awareness

Mastering strategy.position_size opens the door to implementing more advanced strategy features:

  • Implementing dynamic position sizing based on current exposure and market volatility.
  • Developing strategies that manage multiple positions across different symbols (though position size is specific to the current chart’s symbol).
  • Building complex state machines where logic transitions depend on whether the strategy is flat, long, or short.

By effectively using strategy.position_size, developers can create more robust, intelligent, and professional-grade trading algorithms on the TradingView platform.


Leave a Reply