Pine Script v6 line.new: Draw Dynamic Trendlines and Support/Resistance Levels

In Pine Script v6, the line.new function allows you to programmatically draw line objects directly on the chart, connecting two specific coordinate points — making it ideal for rendering dynamic trendlines, support levels, and resistance levels that update bar-by-bar.

1. What Is line.new?

line.new creates a line drawing object on the chart by specifying two endpoints via their x-coordinates (bar index or time) and y-coordinates (price). Unlike plot(), which draws a continuous series, line.new draws a discrete segment between two explicit points. This makes it the correct tool for connecting pivot highs/lows, marking key price levels, or visualizing slope-based trendlines.

Reference: Official v6 Reference: line.new

2. Core Parameters (Individually Verified)

The following parameters are verified from the official v6 Reference Manual. For the complete signature, always consult the official docs.

Parameter Type Description
x1 series int Bar index or UNIX time of the first point
y1 series float Price value of the first point
x2 series int Bar index or UNIX time of the second point
y2 series float Price value of the second point
xloc series string xloc.bar_index (default) or xloc.bar_time
extend series string extend.none (default), extend.left, extend.right, extend.both
color series color Line color
width series int Line width in pixels
style series string line.style_solid, line.style_dashed, line.style_dotted, etc.

3. The Object Limit Rule

By default, Pine Script retains only the most recent 50 line objects. When this limit is exceeded, the oldest line is automatically garbage-collected. You can raise this limit up to a maximum of 500 by passing max_lines_count to indicator() or strategy().

//@version=6
indicator("Line Limit Demo", max_lines_count = 500)

4. Coordinate System: Bar Index vs. Bar Time

The xloc parameter controls how x-coordinates are interpreted:

  • xloc.bar_index (default): x1 and x2 are integer bar indices. Use bar_index built-in to reference the current bar.
  • xloc.bar_time: x1 and x2 are UNIX timestamps in milliseconds. Use the time built-in.

For most trendline use cases, xloc.bar_index is simpler and more predictable.

5. Logic Flow Diagram

The following diagram illustrates the decision flow for drawing a trendline using line.new on each new pivot detection:

graph TD A[Bar Executes] --> B{ta.pivotlow detected?} B -- No --> A B -- Yes --> C[Store bar_index minus rightBars as px2] C --> D[Store pivotLow price as py2] D --> E{px1 is not na?} E -- No --> F[Shift px2 to px1 on next pivot] E -- Yes --> G[Call line.delete on old line] G --> H[Call line.new with x1=px1 y1=py1 x2=px2 y2=py2] H --> I[Assign result to var line trendLine] I --> J[Line rendered on chart with extend.right]

6. Example 1 — Static Horizontal Support/Resistance Line

This example draws a horizontal line at the lowest low of the last 20 bars, extending to the right. The line is redrawn on every bar to stay current.

🔽 [Click to expand] View Full Pine Script Code
//@version=6
// Draws a dynamic horizontal support line at the 20-bar lowest low
indicator("Horizontal Support Line", overlay = true, max_lines_count = 50)

// --- Inputs ---
int lookback = input.int(20, title = "Lookback Period", minval = 1)

// --- Calculation ---
// Find the lowest low over the lookback period
float supportLevel = ta.lowest(low, lookback)

// --- Drawing ---
// Persist the line object across bars using var
var line supportLine = na

// Delete the previous line before drawing a new one to avoid accumulation
if not na(supportLine)
    line.delete(supportLine)

// Draw a new horizontal line from (lookback bars ago) to (current bar)
// x1 = bar index 'lookback' bars back, x2 = current bar index
supportLine := line.new(
     x1     = bar_index - lookback,  // starting bar index
     y1     = supportLevel,          // price at start
     x2     = bar_index,             // ending bar index (current)
     y2     = supportLevel,          // same price = horizontal
     extend = extend.right,          // extend line to the right
     color  = color.green,           // green for support
     style  = line.style_dashed,     // dashed style
     width  = 2                      // 2-pixel width
     )

7. Example 2 — Dynamic Trendline Connecting Two Pivot Lows

This example detects pivot lows using ta.pivotlow and connects the two most recent ones with a trendline, demonstrating how to store pivot coordinates and pass them to line.new.

🔽 [Click to expand] View Full Pine Script Code
//@version=6
// Connects the two most recent pivot lows with a dynamic trendline
indicator("Pivot Low Trendline", overlay = true, max_lines_count = 100)

// --- Inputs ---
int leftBars  = input.int(5, "Left Bars",  minval = 1)
int rightBars = input.int(5, "Right Bars", minval = 1)

// --- Pivot Detection ---
// ta.pivotlow returns the pivot price if bar is a pivot low, else na
float pivotLow = ta.pivotlow(low, leftBars, rightBars)

// --- State Variables (persist across bars) ---
// Store the bar index and price of the two most recent pivot lows
var int   px1 = na  // bar index of older pivot
var float py1 = na  // price of older pivot
var int   px2 = na  // bar index of newer pivot
var float py2 = na  // price of newer pivot

// --- Update pivot storage when a new pivot low is confirmed ---
// Note: pivotlow is confirmed 'rightBars' bars after the actual pivot bar
if not na(pivotLow)
    // Shift: newer pivot becomes older, new detection becomes newer
    px1 := px2
    py1 := py2
    // The actual pivot bar index is rightBars bars in the past
    px2 := bar_index - rightBars
    py2 := pivotLow

// --- Drawing ---
var line trendLine = na

// Only draw when both pivot points are available
if not na(px1) and not na(px2)
    // Delete old line
    if not na(trendLine)
        line.delete(trendLine)
    // Draw trendline connecting the two pivot lows
    trendLine := line.new(
         x1     = px1,              // older pivot bar index
         y1     = py1,              // older pivot price
         x2     = px2,              // newer pivot bar index
         y2     = py2,              // newer pivot price
         extend = extend.right,     // project the slope forward
         color  = color.blue,       // blue trendline
         style  = line.style_solid, // solid line
         width  = 2
         )

8. Example 3 — Resistance Line at Pivot High with Color Coding

This example draws a resistance line at the most recent pivot high and color-codes it based on whether the current close is below (respect) or above (breakout) the resistance level.

🔽 [Click to expand] View Full Pine Script Code
//@version=6
// Draws a resistance line at the most recent pivot high with breakout coloring
indicator("Pivot High Resistance", overlay = true, max_lines_count = 50)

// --- Inputs ---
int leftBars  = input.int(5, "Left Bars",  minval = 1)
int rightBars = input.int(5, "Right Bars", minval = 1)

// --- Pivot Detection ---
float pivotHigh = ta.pivothigh(high, leftBars, rightBars)

// --- State Variables ---
var int   rhx = na  // resistance bar index
var float rhy = na  // resistance price level

// Update when a new pivot high is detected
if not na(pivotHigh)
    rhx := bar_index - rightBars
    rhy := pivotHigh

// --- Drawing ---
var line resistanceLine = na

if not na(rhx)
    if not na(resistanceLine)
        line.delete(resistanceLine)

    // Color: red if price is below resistance (intact), orange if broken
    color lineColor = close < rhy ? color.red : color.orange

    resistanceLine := line.new(
         x1     = rhx,
         y1     = rhy,
         x2     = bar_index,
         y2     = rhy,
         extend = extend.right,
         color  = lineColor,
         style  = line.style_solid,
         width  = 2
         )

9. Key Mathematical Relationship: Slope of a Trendline

When connecting two points $(x_1, y_1)$ and $(x_2, y_2)$, the slope of the trendline is defined as:

$$m = \frac{y_2 - y_1}{x_2 - x_1}$$

And the projected price at any future bar index $x$ is:

$$y = y_1 + m \cdot (x - x_1)$$

Pine Script's line.new with extend = extend.right performs this projection automatically — you do not need to compute it manually. However, understanding this formula is essential when you need to calculate the projected price value programmatically (e.g., to trigger alerts when price crosses the projected trendline).

10. Common Pitfalls and How to Avoid Them

Pitfall Cause Fix
Lines accumulate and slow down the chart Calling line.new every bar without deleting old lines Use var line + line.delete before redrawing
CE10149 compile error Writing line myL = line.new(...) without var Use var line myL = na then assign with :=
Line drawn at wrong bar Forgetting that ta.pivotlow confirms rightBars bars late Use bar_index - rightBars for the actual pivot bar index
Line not visible on chart Missing overlay = true in indicator() Always set overlay = true for price-level drawings
x1 or y1 is na at runtime Passing uninitialized var variables to line.new Guard with if not na(px1) and not na(px2) before calling line.new

11. Conclusion

  • Coordinate precision: line.new requires explicit x/y coordinates for both endpoints; use bar_index for x and price series for y, and always account for the confirmation lag of pivot functions.
  • Memory management: The default object limit is 50 lines (max 500 via max_lines_count); always pair line.new with line.delete on a var line reference to prevent uncontrolled accumulation.
  • Slope projection: The mathematical slope formula $m = (y_2 - y_1)/(x_2 - x_1)$ underpins every trendline; extend.right automates the visual projection, but manual computation is needed for alert-level crossing detection.

Ideas for Script Advancement

  1. Alert on trendline cross: Compute the projected trendline price at bar_index using the slope formula and trigger alert() when close crosses it — combining line.new visuals with actionable signals.
  2. Multi-timeframe support/resistance: Use request.security to fetch pivot highs/lows from a higher timeframe and draw them as persistent horizontal lines on the current chart, creating a multi-timeframe S/R overlay system.

Comments

Popular posts from this blog

Pine Script v6: indicator() vs strategy() — Core Functional Differences Explained

Pine Script Variable Declaration: Mastering var, varip, and Proper Initialization Across Historical Bars

Pine Script v6 plot() Function: Complete Guide to Lines, Histograms, and Circles