Lesson 8: Labels, lines and boxes
Place labels, lines and boxes at a bar and a price, move or delete a drawing you keep, draw only on the newest bar, and stay inside the drawing limits.
Lesson 8 of 18. A plot has one value on every bar. A drawing is a single object that you place where you want it: a label with a text, a line from one point to another, or a box. You place it with a bar number (bar.index, which counts the bars from 0 at the oldest) and a price.
A label where something happens#
indicator "Cross labels"
edition = 1
display = price
max_labels = 200
let fast = tech.ema(close, 10)
let slow = tech.ema(close, 30)
let up = tech.crosses_above(fast, slow)
let down = tech.crosses_below(fast, slow)
if up
label.new(bar.index, low, f"Up {close:price}", style = label_up, color = color.green)
if down
label.new(bar.index, high, f"Down {close:price}", style = label_down, color = color.red)
plot(fast, name = "Fast", color = color.green)
plot(slow, name = "Slow", color = color.red)label.new(x, y, text, ...)places a label at barxand pricey.label_uppoints up at the price from below,label_downpoints down from above.f"Up {close:price}"is a text with a value in it, written with the symbol's own decimals.- The chart keeps the newest 50 labels of a script unless the header says otherwise;
max_labels = 200keeps 200.
Drawing once, on the newest bar#
A drawing made on every bar is made again and again. When you want one set of drawings that describes the chart as it is now, draw on the newest bar only, where bar.is_last is true:
indicator "Recent high and low"
edition = 1
display = price
input length: int = 50, name = "Bars", min = 2, max = 500
let top = tech.highest(high, length)
let bottom = tech.lowest(low, length)
if bar.is_last
line.new(bar.index - length + 1, top, bar.index, top, color = color.green, extend = right)
line.new(bar.index - length + 1, bottom, bar.index, bottom, color = color.red, extend = right)
box.new(
bar.index - length + 1,
top,
bar.index,
bottom,
border_color = color.gray,
background = color.fade(color.gray, 92),
)
plot(close, name = "Close", color = color.gray)line.new(x1, y1, x2, y2, ...) joins two points; extend = right carries the line on to the right side of the chart. box.new(left, top, right, bottom, ...) draws a rectangle.
Keeping a drawing and changing it#
A drawing can be kept in a state name. Then you can change it later instead of making a new one. This script makes one line on the first bar and moves it on every bar to the latest 20-bar high:
indicator "Moving high line"
edition = 1
display = price
state high_line: line = na
let top = tech.highest(high, 20)
if bar.is_first
high_line = line.new(bar.index, high, bar.index, high, color = color.orange, width = 2)
line.set_xy1(high_line, bar.index - 19, top)
line.set_xy2(high_line, bar.index, top)
plot(close, name = "Close", color = color.gray)line.set_xy1 and line.set_xy2 move the two ends. The same idea works for labels (label.set_xy, label.set_text) and boxes (box.set_top, box.set_bottom, box.set_right). The other way is to delete the old drawing and make a new one:
indicator "Latest swing high"
edition = 1
display = price
state marker: label = na
let swing = tech.pivot_high(high, 5, 5)
if not is_na(swing)
label.delete(marker)
marker = label.new(
bar.index - 5,
swing,
f"{swing:price}",
style = label_down,
color = color.red,
)
plot(close, name = "Close", color = color.gray)Only the newest swing high has a label: each new one deletes the one before. A swing is known only five bars after it happened, which is why the label is placed five bars back.
Boxes around a pattern#
indicator "Inside bar boxes"
edition = 1
display = price
max_boxes = 200
let inside = high < high[1] and low > low[1]
if inside
box.new(
bar.index - 1,
high[1],
bar.index,
low[1],
border_color = color.purple,
background = color.fade(color.purple, 85),
)
plot(close, name = "Close", color = color.gray)An inside bar has its high below and its low above the bar before it; the box covers the bar before and the inside bar.
When there are too many#
A script that makes more drawings than it may keep still runs, but the chart drops the oldest and the engine says so with the warning W-OBJECT-LIMIT. A label on every bar is the classic case:
indicator "A label on every bar"
edition = 1
display = price
label.new(bar.index, high, "bar")
plot(close)Raise the number in the header (max_labels, max_lines, max_boxes, up to 500), or better, draw less: only where something happens, only on the newest bar, or one drawing that you move. This warning comes from a run, so the editor does not list it in this release; you see the drawings stop at the oldest end of the chart.
Try changing#
- In "Cross labels", change
lowtolow - (high - low): the up labels sit a little lower, away from the bar. - In "Recent high and low", remove
if bar.is_lastand indent the drawings one step less: the chart is filled with lines, and the oldest are dropped. - In "Moving high line", replace
tech.highest(high, 20)withtech.lowest(low, 20)and the colour withcolor.blue: the line follows the 20-bar low. - In "Inside bar boxes", set
max_boxes = 10: only the ten newest boxes remain.
Checkpoint#
- You can place a label, a line and a box at a bar number and a price.
- You can draw only once, on the newest bar, with
bar.is_last. - You can keep a drawing in a
statename and move it, or delete it and draw a new one. - You know the limits on drawings and what
W-OBJECT-LIMITmeans.