Pine Script: How to Check If a Position Is Open?

Introduction to Detecting Open Positions in Pine Script

Detecting whether your automated strategy holds an open position is a fundamental requirement for implementing robust trading logic in Pine Script. Knowing your current exposure allows you to control entries, manage risk, scale positions, and execute exit conditions correctly.

Why Check for Open Positions?

In automated trading strategies, checking for an open position is crucial for several reasons:

  • Preventing Multiple Entries: Avoid opening a new position when one is already active in the same direction.
  • Managing Risk: Ensure stop losses, take profits, or trailing stops are applied correctly to the active position.
  • Scaling Positions: Implement logic for adding to an existing position based on market conditions.
  • Implementing Exit Logic: Execute complex exit strategies that depend on the current position’s status and direction.
  • Conditional Trading: Define rules that only apply when a position is not open (e.g., looking for a new entry signal).

Without accurately tracking position status, your strategy could behave unpredictably, leading to unintended trades or failure to manage risk effectively.

Understanding the Context: Manual vs. Automated Trading Strategies

It’s important to distinguish between indicators designed purely for manual trading signals and scripts written as automated strategies. The methods for checking position status discussed here primarily apply to strategies, as they interact with TradingView’s backtesting engine and order execution system.

Indicators, by nature, do not manage positions in the same way. While an indicator could potentially track simulated positions using variables, the built-in functions for position management (strategy.*) are only available and meaningful within a strategy() declaration.

Limitations of Built-in Functions and Data

The primary built-in method (strategy.position_size) is remarkably reliable for its intended purpose within the strategy backtesting engine. However, it reflects the aggregated position size across all open trades for a given symbol and account. It doesn’t inherently provide details about individual open trades (like entry price or trade ID) directly through strategy.position_size alone. For individual trade details, you might look into functions like strategy.opentrades (available in Pine Script v5+), but strategy.position_size remains the most direct way to check if any position is open and its aggregate size/direction.

Methods for Identifying Open Positions

Pine Script provides straightforward mechanisms within strategies to determine the current position status.

Using strategy.position_size

This is the most direct and commonly used method. strategy.position_size is a built-in variable that returns:

  • 0: No position is currently open.
  • A positive number (> 0): A long position is open. The value represents the total size (e.g., number of shares, contracts, lots) of the long position.
  • A negative number (< 0): A short position is open. The absolute value (math.abs(strategy.position_size)) represents the total size of the short position.

This single variable effectively tells you if a position is open and, if so, its direction and aggregate size.

Explanation of strategy.opentrades and Related Functions

For more advanced scenarios, Pine Script v5 introduced functions like strategy.opentrades, strategy.opentrades.entry_price(), strategy.opentrades.size(), etc. These functions allow you to iterate through individual open trades if your strategy might have multiple entries contributing to the total strategy.position_size. While powerful for detailed analysis of open trades, simply checking if any position is open is more efficiently done using strategy.position_size.

For example, you could check strategy.opentrades.size() > 0 to see if there’s at least one open trade, which is equivalent to checking strategy.position_size != 0.

Employing User-Defined Variables and Tracking Logic

In some complex strategies or for simulating positions in indicators, you might maintain your own state variables (e.g., a bool inPosition = false) that you update whenever strategy.entry, strategy.exit, or strategy.close commands are executed. However, relying solely on this can be prone to errors, especially with partial fills or complex exit logic. It’s generally best practice in strategies to leverage the built-in strategy.position_size as the definitive source of truth for the current position status, as it’s managed by the backtesting engine itself.

Practical Examples and Code Snippets

Let’s look at how to use strategy.position_size in practice.

Simple Example: Displaying Position Size

This script simply plots the current position size on the chart. When no position is open, it shows 0.

//@version=5
strategy("Position Size Display", overlay=true)

plot(strategy.position_size, title="Current Position Size", color=color.blue, linewidth=2)

// Simple entry/exit example to demonstrate position changes
longCondition = ta. crossover(ta.sma(close, 15), ta.sma(close, 50))
shortCondition = ta. crossunder(ta.sma(close, 15), ta.sma(close, 50))

if longCondition
    strategy.entry("LongEntry", strategy.long, 100)

if shortCondition
    strategy.close("LongEntry", comment="Close Long")
    // Or for a short position
    // strategy.entry("ShortEntry", strategy.short, 100)

// Note: This basic example doesn't explicitly use position_size for logic,
// but shows how its value changes based on strategy actions.

Run this strategy on a chart, and you will see the plotted value change as entries and exits occur.

Advanced Example: Conditional Actions Based on Position Status

This example shows how to use strategy.position_size in if statements to control when entries are allowed.

//@version=5
strategy("Conditional Entry Strategy", overlay=true)

short_ma = ta.sma(close, 20)
long_ma = ta.sma(close, 50)

long_signal = ta. crossover(short_ma, long_ma)
short_signal = ta. crossunder(short_ma, long_ma)

// --- Entry Logic ---

// Only enter LONG if no position is currently open
if long_signal and strategy.position_size == 0
    strategy.entry("Long", strategy.long, 50)

// Only enter SHORT if no position is currently open
if short_signal and strategy.position_size == 0
    strategy.entry("Short", strategy.short, 50)

// --- Exit Logic ---

// Close LONG if a short signal occurs AND we are currently in a long position
if short_signal and strategy.position_size > 0
    strategy.close("Long")

// Close SHORT if a long signal occurs AND we are currently in a short position
if long_signal and strategy.position_size < 0
    strategy.close("Short")

// --- Plotting for visualization ---
plot(short_ma, color=color.blue)
plot(long_ma, color=color.red)

In this code:

  • strategy.position_size == 0 is used to ensure an entry signal is only acted upon when flat.
  • strategy.position_size > 0 is used to confirm a long position is open before attempting to close it.
  • strategy.position_size < 0 is used to confirm a short position is open before attempting to close it.

This pattern is fundamental for preventing pyramiding (unintended multiple entries) unless specifically desired.

Handling Long and Short Positions Differently

As shown in the advanced example, you can specifically check for the direction of the open position:

  • To check if a LONG position is open: strategy.position_size > 0
  • To check if a SHORT position is open: strategy.position_size < 0
  • To check if any position is open (either long or short): strategy.position_size != 0 or math.abs(strategy.position_size) > 0
  • To check if the strategy is flat (no position): strategy.position_size == 0

This allows you to implement distinct logic for managing long positions versus short positions, such as using different exit conditions or risk management rules.

Considerations and Best Practices

Using strategy.position_size is generally straightforward, but keeping a few things in mind is helpful.

Accuracy and Reliability of Position Detection

strategy.position_size is maintained by the TradingView backtesting engine and is highly accurate within that context. It updates synchronously with the script’s execution on each bar, reflecting the state after any strategy calls on that bar have been processed (though nuances exist regarding execution order within a single bar, which is an advanced topic). For the purpose of checking the final position status at the end of a bar’s calculation, it is reliable.

Accounting for Partial Fills and Multiple Entries

strategy.position_size automatically aggregates the size of all currently open trades for the symbol. If your strategy uses multiple strategy.entry calls with the same or different IDs in the same direction without intermediate exits, strategy.position_size will reflect the sum of their sizes. Similarly, partial fills of orders (which are handled automatically by the engine) contribute to the total strategy.position_size once filled. You don’t need to manually track the aggregation; the variable does it for you.

Optimizing Code for Performance

Accessing the strategy.position_size variable is a direct memory read within the backtesting engine and has negligible impact on script performance. There’s no specific optimization needed related to how you check this variable. Focus performance efforts on complex calculations, loops, or overuse of built-in functions within your strategy logic itself.

Conclusion

Determining whether your strategy has an open position is a fundamental step in building effective automated trading systems in Pine Script. The strategy.position_size variable provides a simple, direct, and reliable way to check the current position status, including its direction and aggregate size.

Recap of Methods for Checking Open Positions

The primary method is checking the value of strategy.position_size:

  • == 0: Flat
  • > 0: Long position open
  • < 0: Short position open

For more granular details on individual trades composing the total position, strategy.opentrades and related functions can be used in Pine Script v5+.

Future Enhancements and Advanced Techniques

While strategy.position_size covers the core requirement, advanced strategies might need to combine this check with other information, such as the average entry price (strategy.position_avg_price) or the number of open trades (strategy.opentrades.size()), to implement complex scaling or exit logic. Understanding strategy.position_size is the essential foundation upon which such advanced techniques are built.


Leave a Reply