Pine Script v6 plot() Function: Complete Guide to Lines, Histograms, and Circles
The plot() function is the most fundamental visualization tool in Pine Script v6, enabling developers to render numeric series data directly onto a TradingView chart as lines, histograms, circles, and more. Understanding its styling parameters — including color, linewidth, and style — is essential for building readable, professional-grade indicators. This article provides a rigorous, fact-checked walkthrough of the plot() function based strictly on the official Pine Script v6 Reference Manual.
1. What Does plot() Do?
The plot() function renders a series of numeric values as a visual element on the chart pane. It returns a plot object, which can later be used with the fill() function to shade areas between two plots. Every call to plot() creates one persistent visual layer on the chart.
Reference: https://www.tradingview.com/pine-script-reference/v6/#fun_plot
2. Core Parameters (Individually Verified)
Rather than reproducing the full function signature (which risks introducing errors), the following table documents each parameter used in this article, verified individually against the v6 Reference Manual.
| Parameter | Accepted Type | Description |
|---|---|---|
series |
series int / series float | The numeric data series to plot. This is the only required argument. |
title |
const string | Label shown in the chart legend and Data Window. |
color |
series color | Color of the plotted element. Accepts built-in color constants, color.new(), or conditional color expressions. |
linewidth |
input int | Thickness of the line in pixels. Applies to line-based styles. |
style |
input plot_style | Visual style of the plot. Accepts plot.style_* constants (see Section 3). |
offset |
series int | Shifts the plot left (negative) or right (positive) by the specified number of bars. |
display |
input display | Controls where the plot value is shown (e.g., display.all, display.none). Multiple locations combined with |. |
plot.style_* constants side by side (e.g., style_line, style_histogram, style_circles)3. Verified plot.style_* Constants
The style parameter accepts one of the following verified constants. Each constant changes the geometric representation of the series on the chart.
| Constant | Visual Output | Notes |
|---|---|---|
plot.style_line |
Continuous line | Default style. Bridges over na gaps. |
plot.style_linebr |
Line with breaks | Breaks the line at na values instead of bridging. |
plot.style_stepline |
Step-function line | Horizontal then vertical segments — useful for regime indicators. |
plot.style_stepline_diamond |
Step line with diamond markers | Adds diamond shapes at each data point on a step line. |
plot.style_histogram |
Vertical bars from zero | Each bar extends from the zero baseline to the series value. |
plot.style_area |
Filled area under line | Bridges over na gaps. |
plot.style_areabr |
Filled area with breaks | Breaks the filled area at na values. |
plot.style_circles |
Circle markers | Renders a circle at each bar's value. No connecting line. |
plot.style_cross |
Cross markers | Renders a cross/plus symbol at each bar's value. |
plot.style_columns |
Column bars | Similar to histogram but rendered as full-width columns. |
4. Logic Flow: How plot() Processes Each Bar
Because Pine Script executes bar-by-bar, the plot() function is called once per bar. On each execution, it reads the current value of the series argument and renders the corresponding visual element for that bar. The diagram below illustrates this execution model.
5. Practical Code Examples
Example 1: Basic Line Plot with Dynamic Color
This example plots a 20-period Simple Moving Average as a line, coloring it green when price is above the SMA and red when below. The color parameter accepts a series color, so conditional expressions are fully supported.
🔽 [Click to expand] View Full Pine Script Code — Example 1
//@version=6
indicator(
title = "SMA Line with Dynamic Color",
overlay = true // Draw on the price chart, not a separate pane
)
// --- Inputs ---
int smaLength = input.int(20, title = "SMA Length", minval = 1)
// --- Calculation ---
float smaValue = ta.sma(close, smaLength) // 20-period SMA of closing price
// --- Dynamic Color Logic ---
// color is series color, so a conditional expression is valid here
color lineColor = close >= smaValue ? color.green : color.red
// --- Plot ---
// style_line is the default; shown explicitly for clarity
// linewidth = 2 makes the line 2 pixels thick
plot(
series = smaValue,
title = "SMA(20)",
color = lineColor,
linewidth = 2,
style = plot.style_line
)
Example 2: Histogram Plot (MACD-style)
Histograms are ideal for oscillators. This example computes the difference between a fast and slow EMA and renders it as a histogram, with bars colored based on whether the value is positive or negative.
🔽 [Click to expand] View Full Pine Script Code — Example 2
//@version=6
indicator(
title = "EMA Difference Histogram",
overlay = false // Draw in a separate pane below the chart
)
// --- Inputs ---
int fastLen = input.int(12, title = "Fast EMA Length", minval = 1)
int slowLen = input.int(26, title = "Slow EMA Length", minval = 1)
// --- Calculation ---
float fastEMA = ta.ema(close, fastLen) // Fast Exponential Moving Average
float slowEMA = ta.ema(close, slowLen) // Slow Exponential Moving Average
float diff = fastEMA - slowEMA // Difference series (oscillator)
// --- Dynamic Color for Histogram Bars ---
// Positive diff → teal, Negative diff → red
color barColor = diff >= 0.0 ? color.teal : color.red
// --- Plot as Histogram ---
// Each bar extends vertically from 0 to the diff value
plot(
series = diff,
title = "EMA Diff",
color = barColor,
style = plot.style_histogram
)
// --- Zero baseline reference ---
hline(0, "Zero", color = color.gray, linestyle = hline.style_dashed)
Example 3: Circles and Transparency with color.new()
The plot.style_circles style renders a discrete marker at each bar. Combining it with color.new() allows per-bar transparency control, which is useful for highlighting specific conditions without cluttering the chart.
🔽 [Click to expand] View Full Pine Script Code — Example 3
//@version=6
indicator(
title = "RSI Circle Markers",
overlay = false
)
// --- Inputs ---
int rsiLen = input.int(14, title = "RSI Length", minval = 1)
// --- Calculation ---
float rsiValue = ta.rsi(close, rsiLen) // RSI series (0–100)
// --- Conditional Transparency ---
bool isExtreme = rsiValue > 70.0 or rsiValue < 30.0
int transp = isExtreme ? 0 : 80 // 0 = fully opaque, 100 = invisible
// color.new() accepts a base color and a transparency (0–100)
color circleColor = color.new(color.purple, transp)
// --- Plot as Circles ---
// linewidth controls the size of the circle markers
plot(
series = rsiValue,
title = "RSI",
color = circleColor,
linewidth = 3,
style = plot.style_circles
)
// --- Reference lines ---
hline(70, "Overbought", color = color.red, linestyle = hline.style_dashed)
hline(30, "Oversold", color = color.green, linestyle = hline.style_dashed)
hline(50, "Midline", color = color.gray, linestyle = hline.style_dotted)
6. Using fill() with Two plot() Objects
The plot() function returns a plot object. Two such objects can be passed to fill() to shade the area between them. This is a common pattern for Bollinger Bands or channel indicators.
🔽 [Click to expand] View Full Pine Script Code — fill() Example
//@version=6
indicator(
title = "SMA Channel with Fill",
overlay = true
)
// --- Inputs ---
int len = input.int(20, title = "Length", minval = 1)
float mult = input.float(2.0, title = "Multiplier", minval = 0.1)
// --- Calculation ---
float basis = ta.sma(close, len) // Middle band: SMA
float dev = mult * ta.stdev(close, len) // Standard deviation scaled by multiplier
float upper = basis + dev // Upper band
float lower = basis - dev // Lower band
// --- Plot bands and capture return values ---
// plot() returns a plot object used by fill()
upperPlot = plot(upper, title = "Upper", color = color.blue, linewidth = 1)
lowerPlot = plot(lower, title = "Lower", color = color.blue, linewidth = 1)
plot(basis, title = "Basis", color = color.orange, linewidth = 1)
// --- Fill the area between upper and lower bands ---
// color.new() adds transparency so the fill doesn't obscure candles
fill(upperPlot, lowerPlot, color = color.new(color.blue, 90))
7. The display Parameter
The display parameter controls where the plot's value appears in the TradingView UI. Multiple display locations are combined using the + operator (add a location) or removed using the `-` operator.
//@version=6
indicator("Display Demo", overlay = true)
// Show value in the price scale AND the status line, but NOT the Data Window
plot(
series = ta.sma(close, 20),
title = "SMA",
color = color.blue,
display = display.all - display.data_window
)
Using display.all shows the value everywhere. Using display.none hides it from all locations (useful for intermediate series passed to fill()).
Note: The `|` (bitwise OR) operator does NOT work with `display.*` constants — use `+` and `-` instead.
8. Key Mathematical Relationships
When using plot() with oscillators, it is important to understand the mathematical domain of the series being plotted. For example:
- RSI is bounded: $RSI \in [0, 100]$
- MACD histogram is unbounded: $\text{MACD}_{hist} = EMA_{fast} - EMA_{slow} \in (-\infty, +\infty)$
- Bollinger Band width: $\text{Width} = \text{Upper} - \text{Lower} = 2 \times k \times \sigma$, where $k$ is the multiplier and $\sigma$ is the rolling standard deviation.
Choosing the correct plot.style_* constant should reflect the mathematical nature of the series: bounded oscillators suit style_line or style_circles, while zero-centered oscillators suit style_histogram or style_columns.
9. Conclusion
- The
plot()function renders a numeric series bar-by-bar using a verified set ofplot.style_*constants; thecolorparameter acceptsseries color, enabling fully dynamic, conditional coloring per bar. - The
displayparameter uses `+` to add locations and `-` to remove them. Never use `|` with `display.*` constants. plot()returns aplotobject that can be passed directly tofill()to shade areas between two series, enabling channel and band visualizations.
Ideas for Further Development
- Multi-timeframe plot overlay: Use
request.security()to fetch a higher-timeframe SMA and plot it alongside the current-timeframe SMA usingplot.style_steplineto visually distinguish the two resolutions. - Adaptive transparency engine: Build a system where the
color.new()transparency argument is computed from a normalized volatility measure (e.g., ATR percentile), making the plot visually fade during low-volatility regimes and become opaque during high-volatility periods.
Comments
Post a Comment