Skip to main content

How to Plot Lines with Text in Pine Script: A Complete Guide

· 8 min read

Want to make your TradingView charts way more readable by adding text labels to your lines? You're in the right place. Sometimes a simple line isn't enough - you need to actually label what's happening so you (and anyone else looking at your chart) can understand what those lines represent.

Pine Script Chart with Text Labels on Lines

Whether you're marking support and resistance levels, showing entry and exit points, or just trying to make sense of complex indicator signals, adding text to your Pine Script lines can transform a confusing chart into something crystal clear.

Understanding Pine Script's Line and Text Functions

Before we dive into the code, let's get familiar with the main functions you'll be working with. Pine Script offers several ways to draw lines and add text, each with its own strengths:

plot() - The most basic function for drawing lines. It creates a continuous line across your entire chart, but you can't control where it starts or stops.

line.new() - This gives you complete control over your lines. You can specify exact start and end points, extend them infinitely, change colors, and adjust line styles.

label.new() - Your go-to function for adding text anywhere on the chart. You can attach labels to specific price levels, bar positions, or even to your custom lines.

The real magic happens when you combine these functions. Most professional-looking indicators use line.new() for precise line placement and label.new() for clear, informative text labels.

Creating Your First Line with Text Label

Let's start with something simple but useful - a horizontal line at the current closing price with a text label showing the exact value:

//@version=5
indicator("Price Line with Label", overlay=true)

if barstate.islast
current_price = close

// Draw the horizontal line
price_line = line.new(
x1=bar_index - 50,
y1=current_price,
x2=bar_index,
y2=current_price,
extend=extend.right,
color=color.blue,
width=2
)

// Add a text label
price_label = label.new(
x=bar_index,
y=current_price,
text="Current Price: " + str.tostring(current_price, "#.##"),
style=label.style_label_left,
color=color.white,
textcolor=color.blue
)

This code creates a blue line extending from the current bar to the right, with a label showing the exact price. The barstate.islast condition ensures the line only appears on the most recent bar, preventing your chart from getting cluttered with lines on every bar.

Advanced Text Positioning and Styling

Getting your text to appear exactly where you want it can be tricky. Pine Script offers several label styles that control text positioning relative to your anchor point:

label.style_label_up - Places text above the anchor point (great for resistance levels) label.style_label_down - Places text below the anchor point (perfect for support levels)
label.style_label_center - Centers text on the anchor point (ideal for mid-line labels) label.style_label_left/right - Positions text to the side of the anchor point

Here's an example showing different positioning styles:

//@version=5
indicator("Text Positioning Examples", overlay=true)

if barstate.islast
high_line = line.new(bar_index-20, high, bar_index, high, color=color.red)
low_line = line.new(bar_index-20, low, bar_index, low, color=color.green)
mid_line = line.new(bar_index-20, (high+low)/2, bar_index, (high+low)/2, color=color.gray)

// Different label positions
label.new(bar_index, high, "Resistance: " + str.tostring(high, "#.##"),
style=label.style_label_down, color=color.red, textcolor=color.white)

label.new(bar_index, low, "Support: " + str.tostring(low, "#.##"),
style=label.style_label_up, color=color.green, textcolor=color.white)

label.new(bar_index, (high+low)/2, "Midpoint",
style=label.style_label_center, color=color.gray, textcolor=color.white)

Dynamic Lines Based on Market Conditions

One of the coolest things about Pine Script is creating lines and labels that respond to market conditions. Let's build a simple trend line detector that draws lines with descriptive text:

//@version=5
indicator("Dynamic Trend Lines", overlay=true)

// Detect potential trend changes
bullish_signal = ta.crossover(ta.sma(close, 20), ta.sma(close, 50))
bearish_signal = ta.crossunder(ta.sma(close, 20), ta.sma(close, 50))

if bullish_signal
trend_line = line.new(bar_index, low, bar_index, high, color=color.green, width=3)
trend_label = label.new(bar_index, low, "Bullish Crossover\nPrice: " + str.tostring(close, "#.##"),
style=label.style_label_up, color=color.green, textcolor=color.white, size=size.normal)

if bearish_signal
trend_line = line.new(bar_index, high, bar_index, low, color=color.red, width=3)
trend_label = label.new(bar_index, high, "Bearish Crossover\nPrice: " + str.tostring(close, "#.##"),
style=label.style_label_down, color=color.red, textcolor=color.white, size=size.normal)

This creates vertical lines with detailed labels whenever the 20-period moving average crosses above or below the 50-period moving average - a classic trend change signal.

No-Code Alternative: Visual Pine Script Creation

If you find yourself spending more time debugging syntax than actually analyzing markets, you might want to check out visual Pine Script creation tools. Pineify lets you create complex indicators with lines and labels using a drag-and-drop interface - no coding required.

Pineify Visual Pine Script Editor

It's particularly useful when you're prototyping ideas or need to create indicators quickly without getting bogged down in code syntax. You can always export the generated Pine Script code and modify it later if needed.

The Best Pine Script Generator

Working with Multiple Lines and Text Management

As your indicators become more sophisticated, you'll often need to manage multiple lines and labels. Here's a pattern I use to keep everything organized:

//@version=5
indicator("Multi-Line Manager", overlay=true)

// Arrays to store our lines and labels
var line[] support_lines = array.new<line>()
var label[] support_labels = array.new<label>()

// Function to add new support level
add_support_level(price, bar_idx, description) =>
new_line = line.new(bar_idx, price, bar_idx + 100, price,
color=color.blue, style=line.style_dashed)
new_label = label.new(bar_idx + 50, price, description,
style=label.style_label_center, color=color.blue, textcolor=color.white)

array.push(support_lines, new_line)
array.push(support_labels, new_label)

// Detect support levels and add them
if ta.pivotlow(low, 5, 5)
add_support_level(low[5], bar_index[5], "Support: " + str.tostring(low[5], "#.##"))

This approach keeps your code clean and makes it easy to manage multiple visual elements without cluttering your chart.

Pro Tips for Better Line and Text Visualization

After working with Pine Script lines and text for a while, here are some techniques that have made my indicators much more professional-looking:

Use consistent color schemes - Pick a color palette and stick to it. Green for bullish signals, red for bearish, gray for neutral information.

Control text size and transparency - Large text can overwhelm your chart. Use size=size.small for less important labels and adjust transparency with color.new(color.blue, 70) for subtle effects.

Implement smart label management - Use conditions like barstate.islast or time-based logic to prevent your chart from becoming a cluttered mess of text.

Leverage line extensions - The extend=extend.right parameter is incredibly useful for showing where key levels extend into the future.

For more advanced Pine Script techniques, you might find our comprehensive Pine Script tutorial helpful, especially if you're just getting started with TradingView's scripting language.

Common Pitfalls and How to Avoid Them

When I first started adding text to lines in Pine Script, I made some classic mistakes that you can easily avoid:

Creating too many visual elements - Every call to line.new() or label.new() uses memory. If you're creating lines on every bar without cleaning up old ones, you'll hit TradingView's limits quickly.

Forgetting about different timeframes - Your lines and labels might look perfect on a 1-hour chart but become illegible when someone switches to a 5-minute view. Test your indicators across multiple timeframes.

Not handling edge cases - What happens when your price data is missing (na values)? Always include checks like if not na(close) before creating visual elements.

If you're working with more complex chart annotations, our guide on drawing lines with Pine Script covers advanced techniques for creating professional-looking chart markup.

Real-World Applications and Examples

Let me show you a practical example that combines everything we've covered - a script that marks significant price movements with annotated lines:

//@version=5
indicator("Price Movement Tracker", overlay=true)

// Settings
movement_threshold = input.float(2.0, "Movement Threshold %", minval=0.1, maxval=10.0)
show_percentages = input.bool(true, "Show Percentage Changes")

// Calculate price movement
price_change_pct = (close - close[1]) / close[1] * 100

// Detect significant movements
significant_up = price_change_pct > movement_threshold
significant_down = price_change_pct < -movement_threshold

if significant_up
movement_line = line.new(bar_index[1], close[1], bar_index, close,
color=color.green, width=2, style=line.style_arrow_right)

label_text = show_percentages ?
"↗ +" + str.tostring(price_change_pct, "#.##") + "%" :
"Significant Move Up"

label.new(bar_index, close, label_text,
style=label.style_label_lower_left, color=color.green, textcolor=color.white)

if significant_down
movement_line = line.new(bar_index[1], close[1], bar_index, close,
color=color.red, width=2, style=line.style_arrow_right)

label_text = show_percentages ?
"↘ " + str.tostring(price_change_pct, "#.##") + "%" :
"Significant Move Down"

label.new(bar_index, close, label_text,
style=label.style_label_upper_left, color=color.red, textcolor=color.white)

This script automatically identifies and labels significant price movements, making it easy to spot important market events at a glance.

Beyond Basic Lines: Advanced Visualization Techniques

Once you're comfortable with basic lines and text, you can explore more advanced visualization techniques. Pine Script's plotshape() function offers another way to add visual markers to your charts, while the box.new() function lets you create rectangular zones with text labels.

For traders who want to take their chart analysis to the next level, combining multiple visualization techniques creates incredibly informative displays that can significantly improve trading decisions.

Conclusion: Making Your Charts Tell a Story

Adding text to lines in Pine Script transforms static chart elements into informative, story-telling visualizations. Whether you're marking key price levels, annotating trade signals, or simply making your indicators more user-friendly, the combination of line.new() and label.new() functions gives you powerful tools for chart communication.

Remember, the goal isn't to create the most complex indicator possible - it's to make your charts clearer and more actionable. Start with simple line and text combinations, then gradually add sophistication as your needs grow.

The techniques we've covered here form the foundation for creating professional-grade Pine Script indicators. With practice, you'll find yourself naturally thinking about how to present information visually, making your trading analysis both more effective and more enjoyable.

For those ready to dive deeper into Pine Script development, our Pine Script v6 guide covers the latest features and improvements that can take your indicator development to the next level.