Pine Script labels and lines: write on your chart with label.new() and line.new()
plot() draws one value per candle. Labels and lines are different. They sit anywhere you like, carry text that changes, and reach into the future. Here's how to use them without clutter.
Why labels and lines?
plotshape() can mark a candle. But its text is fixed. It can't say "closed at 182.40".
Labels and lines are drawings. Your script makes them, places them, and can change them later.
- A label is a small tag with text. It can show any number your script works out.
- A line joins 2 points. It can stretch to the right edge of the chart, like a level you drew by hand.
New to Pine Script? Start with Pine Script for beginners. This page picks up from there.
Example 1: a label on every cross
This marks each candle that closes above its 20-candle average, with the closing price written on the tag:
//@version=6
indicator("Cross labels", overlay=true, max_labels_count=100)
avg = ta.sma(close, 20)
plot(avg, "Average", color=color.gray)
crossUp = ta.crossover(close, avg)
if crossUp
label.new(bar_index, low, "Up " + str.tostring(close, format.mintick), yloc=yloc.belowbar, style=label.style_label_up, color=color.green, textcolor=color.white)
Line by line:
- Line 1 says this is Pine Script version 6.
- Line 2 names the script and puts it on the price chart. max_labels_count=100 lets it keep up to 100 labels.
- Line 3 works out the average of the last 20 closes.
- Line 4 draws that average in gray.
- Line 5 is true on the candle where the close crosses from below the average to above it.
- Line 6 says "only on those candles…"
- Line 7 makes a new label. The parts are explained below.
The parts of label.new()
- bar_index is the candle's number, counting from the first candle on the chart. It tells the label which candle to sit on.
- low is the price where it sits. Here yloc=yloc.belowbar overrides that and parks it just under the candle.
- "Up " + str.tostring(close, format.mintick) is the text. str.tostring turns the price into text. format.mintick rounds it to the symbol's smallest price step.
- style=label.style_label_up is a tag pointing up at the candle.
- color and textcolor set the tag and the words.
The drawing limit
Every label and line uses up a slot. By default a script keeps about 50 of each. You can raise it with max_labels_count and max_lines_count, up to 500.
When the script goes past the limit, the oldest drawings are removed first. So on a long chart, early labels quietly disappear. That's normal, not a bug.
Example 2: one label you move
Often you only need one label, updated each candle. Making a new one every candle wastes slots. Make it once, then move it:
//@version=6
indicator("Last price tag", overlay=true)
var label tag = label.new(bar_index, close, "", style=label.style_label_left, color=color.blue, textcolor=color.white)
if barstate.islast
label.set_xy(tag, bar_index + 2, close)
label.set_text(tag, "Last: " + str.tostring(close, format.mintick))
- Line 3 makes the label. var means "do this once, on the first candle, then keep it". Without var, you'd get a new label on every candle.
- Line 4 says "only on the newest candle". barstate.islast is true there.
- Line 5 moves the label 2 candles to the right of the newest one, at the close.
- Line 6 changes its text to the latest price.
Notice bar_index + 2. Labels can sit in the empty space to the right, where no candle exists yet. plot() can't.
Example 3: yesterday's high as a line
A line is just as easy. This draws yesterday's high and stretches it to the right edge:
//@version=6
indicator("Yesterday's high", overlay=true)
prevHigh = request.security(syminfo.tickerid, "D", high[1], lookahead=barmerge.lookahead_on)
var line pdh = na
if barstate.islast
line.delete(pdh)
pdh := line.new(bar_index - 20, prevHigh, bar_index, prevHigh, extend=extend.right, color=color.orange, style=line.style_dashed, width=2)
- Line 3 fetches yesterday's high from the daily chart. high[1] with lookahead_on is the safe way to get a finished day. The full story is in Pine Script request.security.
- Line 4 makes an empty box that will hold the line. na means "nothing yet".
- Line 5 says "only on the newest candle".
- Line 6 deletes the old line, if there is one. Deleting na does nothing, so the first time is safe.
- Line 7 draws a new line from 20 candles back to now, at yesterday's high. extend=extend.right stretches it to the edge. line.style_dashed makes it dashed. width=2 makes it thicker.
Delete, then draw again. That's the second way to keep one drawing instead of hundreds. Moving with line.set_xy1() and line.set_xy2() works too.
Yesterday's high is a simple level many traders watch. More on why levels matter in support and resistance.
Useful styles and settings
| Setting | Choices | What it does |
|---|---|---|
| label style | label.style_label_up, label.style_label_down, label.style_label_left, label.style_none | The tag's shape and which way it points |
| yloc | yloc.price, yloc.abovebar, yloc.belowbar | Sit at a price, or just above or below the candle |
| line style | line.style_solid, line.style_dashed, line.style_dotted | How the line looks |
| extend | extend.none, extend.right, extend.left, extend.both | Whether the line runs on past its points |
| xloc | xloc.bar_index, xloc.bar_time | Place by candle number or by time |
The live-candle catch
A label made on a live candle can appear, then vanish. If price crosses the average mid-candle, then falls back before the close, the condition stops being true. The label goes with it.
When you reload the chart, only finished candles count. So the live chart can show labels that history won't. That's one kind of repainting.
To only label finished candles, change the "if" line to:
if crossUp and barstate.isconfirmed
barstate.isconfirmed is true only once a candle has closed. That matches a rule we use for any level: only a candle body closing past it counts. A Wick poking through doesn't.
A label is information, not an instruction. It can show where something happened. It can't tell you if the bigger chart agrees, where your stop goes, or how big to trade.
Try it today
- On a computer, paste Example 1 into the Pine Editor. Save and add it to a chart.
- Scroll back. Count the labels. Do they all sit where you expected?
- Add and barstate.isconfirmed to the "if" line. Watch a live chart for a few candles.
- Then try Example 3 on a 15-minute chart. Does price react near yesterday's high? Step through it with bar replay so you can't peek ahead.
Keep it clean. If your labels cover the candles, you'll stop reading them. Fewer, clearer marks beat many.
Learning from a real script
Labels and lines are how a finished indicator writes levels and notes on a chart. Our course includes the full source code of the StructureX chart tool to learn from and customize. It's source code, not a ready-made trading bot.
Common mistakes
- Forgetting var. Without it, the script makes a fresh label on every candle and hits the limit fast.
- Making a new drawing each candle. Move or delete-and-redraw one instead.
- Expecting old labels to stay forever. Past the limit, the oldest go first.
- Labelling the live candle. Add barstate.isconfirmed for closed candles only.
- Placing by price when you meant the candle. Use yloc.abovebar or yloc.belowbar to hug the candle.
Questions
How do I add a label in Pine Script?
Use label.new() with a candle (bar_index), a price and your text, for example label.new(bar_index, high, "Here"). Put it inside an "if" to only label some candles.
How do I draw a horizontal line in Pine Script?
Use line.new() with the same price for both points and extend=extend.right. For a fixed price on every candle, hline() is simpler.
Why do my Pine Script labels disappear?
Either the script went past its drawing limit, so the oldest were removed, or the label was made on a live candle whose condition was no longer true at the close.
What is the maximum number of labels in Pine Script?
By default about 50. Set max_labels_count in indicator() to raise it, up to 500. Lines work the same with max_lines_count.
Want the next step? We'll walk you through it.
Four free lessons by email, one every few days — each with a 10-minute exercise on a real chart.
Send Me the Free Lessons 4 short emails · No spam · Unsubscribe anytimeOr see the whole method, step by step:
See What’s Inside the Course Try everything free first. Decide when you're ready. · Open the free chart tool (works in the TradingView phone app)One chart idea a day, in plain English. Follow along: