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. Usebar_indexbuilt-in to reference the current bar.xloc.bar_time: x1 and x2 are UNIX timestamps in milliseconds. Use thetimebuilt-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:
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.newrequires explicit x/y coordinates for both endpoints; usebar_indexfor 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 pairline.newwithline.deleteon avar linereference to prevent uncontrolled accumulation. - Slope projection: The mathematical slope formula $m = (y_2 - y_1)/(x_2 - x_1)$ underpins every trendline;
extend.rightautomates the visual projection, but manual computation is needed for alert-level crossing detection.
Ideas for Script Advancement
- Alert on trendline cross: Compute the projected trendline price at
bar_indexusing the slope formula and triggeralert()whenclosecrosses it — combiningline.newvisuals with actionable signals. - Multi-timeframe support/resistance: Use
request.securityto 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
Post a Comment