How to Plot Boolean Variables in TradingView Pine Script?

Boolean variables are fundamental in programming, representing simple true or false states. In the context of TradingView Pine Script, they are indispensable for evaluating conditions such as whether a price is above a moving average, if an indicator is in an overbought region, or if specific entry criteria have been met.

While Pine Script’s primary plot() function is designed for numerical series, effectively visualizing boolean outcomes directly on the chart is crucial for debugging logic, confirming signal generation, and building intuitive visual indicators.

Understanding Boolean Variables in TradingView

In Pine Script, a boolean variable or expression evaluates to either true or false. These are not implicitly numerical 1 or 0 in all contexts, though Pine Script often coerces them when necessary, particularly in arithmetic operations or when used in functions expecting a numeric input.

is_price_above_ma = close > ta.sma(close, 20)

is_overbought = ta.rsi(close, 14) > 70

buy_condition = is_price_above_ma and is_overbought

These boolean variables (is_price_above_ma, is_overbought, buy_condition) represent a state at each bar, forming a boolean series over time.

Why Plotting Booleans is Useful

Plotting boolean states directly on the chart provides immediate visual feedback on when specific conditions are met. This is invaluable for:

  • Debugging: Quickly see if your logical conditions are triggering exactly when and where you expect them to.
  • Validation: Visually confirm that indicator signals or strategy entry/exit criteria align with price action.
  • Readability: Make complex logic easier to understand by displaying key intermediate or final boolean states.
  • Signal Visualization: Clearly mark bars where significant events (like crossovers, breakouts, or condition triggers) occur.

Limitations and Considerations

While powerful, plotting booleans directly using standard methods has limitations:

  • plot() expects a numeric series. Direct plotting of a boolean series results in 1.0 for true and 0.0 for false. This can clutter price panes if not handled carefully.
  • Representing a simple true/false state as a line fluctuating between 0 and 1 isn’t always the most intuitive visualization.
  • Boolean series inherently represent discrete states (on or off) rather than continuous values, making shapes or character plots often more suitable than line plots.

Understanding these points helps choose the most appropriate plotting method for your specific needs.

Basic Techniques for Plotting Boolean Values

The simplest ways to visualize boolean logic involve leveraging functions designed for plotting or explicitly converting the boolean to a numeric type that plotting functions accept.

Using the plot() Function with Boolean Conditions

The plot() function, primarily for numeric series, will automatically cast a boolean expression or variable to a number: true becomes 1.0, and false becomes 0.0. You can plot the boolean variable directly.

// Example: Plotting if close is above a 20-period Simple Moving Average
ma_length = 20
ma_value = ta.sma(close, ma_length)
is_above_ma = close > ma_value

// Plot the boolean state (will show as 1.0 or 0.0)
plot(is_above_ma, title='Is Above MA (0/1)', color=color.blue)

// Often, you might plot the MA itself for context
plot(ma_value, title='SMA', color=color.red)

This method is straightforward but results in a line plot fluctuating between 0 and 1, which might be visually distracting or confusing in the price pane unless placed in a separate pane.

Converting Booleans to Numerical Values for Plotting (0 and 1)

While Pine Script implicitly converts booleans for plot(), you can be explicit using int(). This doesn’t fundamentally change the outcome for plot(), but reinforces the concept of the numerical representation.

// Same MA example
ma_length = 20
ma_value = ta.sma(close, ma_length)
is_above_ma = close > ma_value

// Explicitly convert boolean to integer (0 or 1) for plotting
plot(int(is_above_ma), title='Is Above MA (int)', color=color.fuchsia)

This yields the same 0/1 line plot as before. This technique is more relevant when you need to perform arithmetic with the boolean state before plotting or pass it to functions strict about types.

Plotting as shapes using plotshape() function

For discrete events indicated by a boolean true value, plotshape() is often a much cleaner and more intuitive method than plot(). It draws a shape on the bar where the series argument is true (or non-zero).

// Example: Plot a shape when close crosses above MA
ma_length = 20
ma_value = ta.sma(close, ma_length)

// Check for a crossover: did it cross UP on THIS bar?
crossover_up = ta.crossover(close, ma_value)

// Plot an upward triangle shape on bars where crossover_up is true
plotshape(crossover_up, title='MA Crossover Up', style=shape.triangleup, color=color.green, location=location.belowbar)

// Plot MA for context
plot(ma_value, title='SMA', color=color.red)

plotshape() automatically interprets true as a trigger to plot the shape and false as no shape. The location argument allows placing the shape above or below the bar, or directly on the bar (location.absolute). This is a very common and effective way to visualize boolean signals.

Advanced Plotting Techniques and Customization

Beyond simple 0/1 lines or basic shapes, you can use boolean logic to customize the appearance of plots or display more specific characters.

Conditional Plotting: Changing Colors and Styles Based on Boolean Values

Boolean logic excels at controlling visual attributes conditionally. You can use a boolean expression directly in the color argument of plotting functions.

// Example: Plotting MA and coloring it based on whether price is above/below
ma_length = 20
ma_value = ta.sma(close, ma_length)

is_above_ma = close > ma_value

// Plot the MA, color it green if price is above, red if below
plot(ma_value, title='Colored SMA', color=is_above_ma ? color.green : color.red, linewidth=2)

// You can also use conditions for linewidth, style, etc., although less common directly with booleans.

This uses the ternary operator condition ? value_if_true : value_if_false. The boolean is_above_ma directly dictates the color. This technique can be applied to any plot type (plot, plotshape, plotbar, plotcandle) where attributes accept a series argument that can be controlled by a boolean or a conditional expression evaluating to different values based on a boolean.

Plotting Boolean Arrays and Series

Pine Script V5 introduced arrays, and while you can create array<bool>, plotting them directly as a single line series like plot(my_boolean_array) isn’t supported as plot() expects a series, not an array. However, the values contained within an array can be plotted individually or processed to derive a plottable series.

A boolean series is the natural outcome of applying a boolean condition across bars (e.g., close > open creates a boolean series). The basic techniques described earlier (plot(boolean_series), plotshape(boolean_series)) are the primary ways to visualize boolean series data.

For working with arrays, you’d typically iterate through the array (if its size is fixed or small) or convert relevant array data into a plottable series or use it to control shape/char plots. For instance, you might calculate a boolean state per bar based on array processing and then plot that per-bar boolean series.

Using plotchar() to Display Custom Characters based on Booleans

Similar to plotshape(), plotchar() is excellent for marking bars based on a boolean condition. Instead of standard shapes, it plots a specified character.

// Example: Mark bars where RSI is overbought with a character
rsi_value = ta.rsi(close, 14)
is_overbought = rsi_value > 70

// Plot the character 'O' (for Overbought) on bars where is_overbought is true
plotchar(is_overbought, title='Overbought Signal', char='O', color=color.red, location=location.top)

// Plot RSI itself for context (in a separate pane usually)
// plot(rsi_value, title='RSI', color=color.blue)
// hline(70)

plotchar() requires a series argument which is interpreted as a boolean trigger (non-zero means true). You specify the character using the char argument (a single character string). location works similarly to plotshape(). This offers more flexibility in the visual marker used.

Practical Examples and Use Cases

Here are concrete examples demonstrating how to apply these plotting techniques in common trading scenarios.

Plotting Overbought/Oversold Conditions with Boolean Logic

Visualizing when an oscillator enters extreme regions is a classic use case for boolean logic and plotshape or plotchar.

//@version=5
indicator('RSI Extreme Conditions', shorttitle='RSI Extremes', overlay=true)

rsi_length = input.int(14, 'RSI Length')
overbought_level = input.int(70, 'Overbought Level')
oversold_level = input.int(30, 'Oversold Level')

rsi_value = ta.rsi(close, rsi_length)

is_overbought = rsi_value > overbought_level
is_oversold = rsi_value < oversold_level

// Plot shapes on the main price chart
plotshape(is_overbought, title='Overbought Signal', style=shape.circle, color=color.red, location=location.top)
plotshape(is_oversold, title='Oversold Signal', style=shape.circle, color=color.green, location=location.bottom)

// Optional: Plot RSI in a separate pane (requires removing overlay=true and adjusting plot calls)
// plot(rsi_value, title='RSI', color=color.blue)
// hline(overbought_level)
// hline(oversold_level)

This script calculates boolean states is_overbought and is_oversold and uses them directly to trigger plotshape() calls, marking the bars where these conditions are true with circles above or below the price.

Visualizing Trend Changes Based on Moving Average Crossovers (Boolean)

MA crossovers are fundamental trend-following signals. Plotting the crossover event using plotshape clearly indicates potential trend shifts.

//@version=5
indicator('MA Crossover Signals', shorttitle='MA XO', overlay=true)

fast_length = input.int(10, 'Fast MA Length')
slow_length = input.int(30, 'Slow MA Length')

fast_ma = ta.sma(close, fast_length)
slow_ma = ta.sma(close, slow_length)

// Check for crossovers using built-in functions returning boolean series
bullish_crossover = ta.crossover(fast_ma, slow_ma)
bearish_crossover = ta.crossunder(fast_ma, slow_ma)

// Plot shapes for bullish and bearish crossovers
plotshape(bullish_crossover, title='Bullish Crossover', style=shape.triangleup, color=color.green, location=location.belowbar)
plotshape(bearish_crossover, title='Bearish Crossover', style=shape.triangledown, color=color.red, location=location.abovebar)

// Plot MAs for context
plot(fast_ma, title='Fast MA', color=color.blue)
plot(slow_ma, title='Slow MA', color=color.red)

The ta.crossover and ta.crossunder functions are built-in utilities that return a boolean series, true only on the bar where the crossover occurs. These boolean series are perfect inputs for plotshape().

Displaying Entry/Exit Signals with Boolean Flags

Complex trading strategies often boil down to boolean conditions for entry and exit. Visualizing these final signals is critical for strategy backtesting and analysis.

//@version=5
indicator('Simple Strategy Signals', shorttitle='Signals', overlay=true)

ma_length = input.int(20, 'MA Length')
rsi_length = input.int(14, 'RSI Length')
rsi_entry_level = input.int(50, 'RSI Entry Level')

ma_value = ta.sma(close, ma_length)
rsi_value = ta.rsi(close, rsi_length)

// Define boolean entry/exit conditions
long_entry_condition = close > ma_value and rsi_value > rsi_entry_level
short_entry_condition = close < ma_value and rsi_value < (100 - rsi_entry_level)

// Plot character signals based on boolean conditions
plotchar(long_entry_condition, title='Buy Signal', char='B', color=color.green, size=size.small, location=location.belowbar)
plotchar(short_entry_condition, title='Sell Signal', char='S', color=color.red, size=size.small, location=location.abovebar)

// Plot MA for context
plot(ma_value, title='MA', color=color.gray)

Here, long_entry_condition and short_entry_condition are boolean variables combining multiple criteria. These final boolean signals are plotted using plotchar to display ‘B’ or ‘S’ on the chart, marking potential trade entry points.

Troubleshooting and Best Practices

Effectively using and plotting boolean logic involves understanding potential pitfalls and adhering to good coding practices.

Common Errors When Plotting Booleans and How to Fix Them

  • Plotting bool with Functions Expecting float/int: While plot() and plotshape/plotchar handle boolean to numeric conversion, other functions might not. If you pass a boolean series to a function strictly requiring a numeric type, you might get a compilation error. Fix: Explicitly convert using int(boolean_variable) or float(boolean_variable).
  • Runtime Errors with Conditional Logic: Complex if or ternary structures involving series and booleans can sometimes lead to runtime errors if not all code paths are valid on every bar (e.g., referencing a past value [1] when at the first bar). Fix: Use na checks or ensure conditions handle edge cases, especially at the start of the chart data. Pine Script’s type system and implicit na propagation help, but complex interactions can still cause issues.
  • Misinterpreting plot() Output: Expecting a clean signal marker from plot(boolean_series) instead of a 0/1 line. Fix: Use plotshape() or plotchar() for discrete signals. Use plot() with conditional colors for coloring existing plots based on boolean states.

Optimizing Code for Performance

Performance is key, especially in complex scripts or during backtesting.

  • Avoid Redundant Calculations: Calculate boolean conditions once and store them in a variable if used multiple times.

    // Less efficient (calculating condition twice)
    // plotshape(close > open, ...)
    // plotchar(close > open, ...)
    
    // More efficient (calculating condition once)
    is_up_bar = close > open
    plotshape(is_up_bar, ...)
    plotchar(is_up_bar, ...)
    
  • Use Built-ins: Pine Script’s built-in functions like ta.crossover(), ta.crossunder(), ta.change(), ta.falling(), ta.rising() are highly optimized for detecting boolean states based on series changes. Use them instead of writing manual comparisons for these specific patterns.

Best Practices for Readability and Maintainability

Well-structured code is easier to debug and modify.

  • Meaningful Variable Names: Use descriptive names for your boolean variables (e.g., is_in_uptrend, buy_signal_triggered) instead of generic ones.
  • Comments: Add comments explaining complex boolean logic, especially when combining multiple conditions.
  • Structure Complex Conditions: Break down very complex boolean expressions into smaller, named boolean variables. This makes the logic flow clearer and easier to debug if a signal isn’t firing as expected.
  • Consistent Plotting Style: Choose a consistent way to represent signals (e.g., always use plotshape for entry signals, plotchar for exits) across your scripts.

By following these guidelines, you can leverage the power of boolean logic to create clear, efficient, and robust visual indicators and signals in your TradingView Pine Script projects.


Leave a Reply