Entities
Create persistent chart entities (Line, Box, Label, Marker, Arrow) with mutable handles.
Entities are persistent chart objects that exist while your script is active. Each constructor returns a handle you can update or delete.
Limits: Max 2000 of each entity type per script.
Keys: In //@version=2, every entity requires a non-empty key string. The key identifies the entity per bar — only one entity of each type with a given key can exist per bar.
Versioning: Arrow() is available only in //@version=2. If a required key is missing, the constructor returns a no-op handle and logs an error.
Handle Lifetime
In //@version=2, keyed entities are matched by (entity type, key, current bar unix).
- Calling
Line("trend", ...)twice on the same bar updates that bar's"trend"line and returns the current live handle. - Calling
Line("trend", ...)again on a later bar creates or upserts that later bar's"trend"line. It does not make an older handle from a previous bar current again. .set(),.clone(), and.delete()only work while the underlying entity still exists.- After
.delete(), the handle is invalidated immediately. - A handle can also become stale if the underlying entity is removed later, such as after entity-limit eviction or a full runtime rebuild/replay (
setCode,updateInputs,updateContext).
Recommended pattern: call the constructor inside onBar on every bar where the entity should exist, then use the handle returned for that bar.
//@version=2
indicator("Safe Entity Handle Pattern", true)
const candles = subscribe(data.OHLCV)
let trend = null
function onBar(index) {
if (barIndex() < 20) return
trend = Line("trend", {
x1: unix(20),
y1: candles.low(20),
x2: unix(0),
y2: candles.high()
})
trend.set({
color: candles.close() >= candles.open() ? color.green : color.red,
width: 2
})
}If you keep a handle in a variable, reassign it from the constructor before calling .set(). Do not assume a handle from an earlier bar is still the current live entity for the same key.
Line
Line(key, options?) -> handleDraws a line between two coordinate points.
//@version=2
indicator("Line Example", true)
const candles = subscribe(data.OHLCV)
function onBar(index) {
if (barIndex() < 20) return
Line("trend", {
x1: unix(20),
y1: candles.low(20),
x2: unix(0),
y2: candles.high(),
width: 2,
color: color.green,
style: linestyle.dashed,
label: "Trend",
zIndex: 2
})
}| Option | Type | Required | Default | Description |
|---|---|---|---|---|
x1 | number | no | 0 | Start x coordinate (unix timestamp) |
y1 | number | no | 0 | Start y coordinate (price) |
x2 | number | no | 0 | End x coordinate (unix timestamp) |
y2 | number | no | 0 | End y coordinate (price) |
width | number | no | 1 | Line width in pixels |
color | color | no | color.white | Line color |
style | linestyle.* | no | linestyle.solid | Line style (solid, dotted, dashed, arrow.right, arrow.left, arrow.both) |
label | string | no | "" | Text label displayed on the line |
zIndex | number | no | 0 | Renderer z-order value |
forceOverlay | bool | no | false | Promote this line to the overlay chart. Sticky per key/handle identity. |
linestyle.arrow.* adds arrowheads to Line(...) without changing the separate Arrow() entity API:
linestyle.arrow.rightdraws the arrowhead atx2,y2linestyle.arrow.leftdraws the arrowhead atx1,y1linestyle.arrow.bothdraws arrowheads at both ends
Handle methods:
ln.set(options?) -> handle— update any options, returns the handle for chainingln.clone(newKey) -> handle— duplicate the entity under a new keyln.delete() -> boolean— remove from chart
Box
Box(key, options?) -> handleDraws a filled rectangle between two corner points.
//@version=2
indicator("Box Example", true)
const candles = subscribe(data.OHLCV)
function onBar(index) {
if (barIndex() < 10) return
Box("zone", {
x1: unix(10),
y1: candles.high(10),
x2: unix(0),
y2: candles.low(),
color: color.transp(color.blue, 75),
rounding: 4,
borderColor: color.white,
borderWidth: 2,
borderStyle: linestyle.dashed,
extend: [extend.left, extend.up],
text: "Zone",
textSize: size.md,
textColor: color.white,
textHAlign: text.align.left,
textVAlign: text.align.top,
textWrap: text.wrap.none,
zIndex: 3
})
}| Option | Type | Required | Default | Description |
|---|---|---|---|---|
x1 | number | no | 0 | Left x coordinate (unix timestamp) |
y1 | number | no | 0 | Top y coordinate (price) |
x2 | number | no | 0 | Right x coordinate (unix timestamp) |
y2 | number | no | 0 | Bottom y coordinate (price) |
color | color | no | color.white | Fill color |
rounding | number | no | 0 | Corner radius in pixels |
borderColor | color | no | fill color | Border color |
borderWidth | number | no | 0 | Border width in pixels |
borderStyle | linestyle.solid | linestyle.dotted | linestyle.dashed | no | linestyle.solid | Border style |
extend | extend.* or extend.*[] | no | extend.none | Extend the box left/right/up/down |
text | string | no | "" | Text rendered inside the box |
textSize | size.* | no | size.auto | Box text size |
textColor | color | no | color.white | Text color |
textHAlign | text.align.* | no | text.align.center | Horizontal text alignment |
textVAlign | text.align.* | no | text.align.center | Vertical text alignment |
textWrap | text.wrap.* | no | text.wrap.auto | Text wrapping mode |
zIndex | number | no | 0 | Renderer z-order value |
forceOverlay | bool | no | false | Promote this box to the overlay chart. Sticky per key/handle identity. |
Handle methods:
box.set(options?) -> handle— update any options, returns the handle for chainingbox.clone(newKey) -> handle— duplicate the entity under a new keybox.delete() -> boolean— remove from chart
Label
Label(key, options?) -> handlePlaces a text label at a position on the chart.
//@version=2
indicator("Label Example", true)
const candles = subscribe(data.OHLCV)
function onBar(index) {
Label("breakout", {
x: unix(0),
y: candles.high(),
text: "Breakout",
color: color.white,
size: 12,
textAlign: text.align.right,
zIndex: 4
})
}| Option | Type | Required | Default | Description |
|---|---|---|---|---|
x | number | no | 0 | X coordinate (unix timestamp) |
y | number | no | 0 | Y coordinate (price) |
text | string | no | "" | Label text content |
color | color | no | color.white | Text color |
size | number | no | 12 | Font size |
textAlign | text.align.* | no | text.align.center | Horizontal text alignment; labels are always vertically centered |
zIndex | number | no | 0 | Renderer z-order value |
forceOverlay | bool | no | false | Promote this label to the overlay chart. Sticky per key/handle identity. |
Handle methods:
tag.set(options?) -> handle— update any options, returns the handle for chainingtag.clone(newKey) -> handle— duplicate the entity under a new keytag.delete() -> boolean— remove from chart
Marker
Marker(key, options?) -> handlePlaces a shape marker at a position on the chart.
//@version=2
indicator("Marker Example", true)
const candles = subscribe(data.OHLCV)
function onBar(index) {
Marker("signal", {
x: unix(0),
y: candles.high(),
shape: shape.diamond,
size: 6,
color: color.yellow,
zIndex: 5
})
}| Option | Type | Required | Default | Description |
|---|---|---|---|---|
x | number | no | 0 | X coordinate (unix timestamp) |
y | number | no | 0 | Y coordinate (price) |
shape | shape.* | no | shape.circle | Marker shape (see Drawing Constants) |
size | number | no | 5 | Marker size in pixels |
color | color | no | color.white | Marker color |
zIndex | number | no | 0 | Renderer z-order value |
forceOverlay | bool | no | false | Promote this marker to the overlay chart. Sticky per key/handle identity. |
When updating via .set(), use marker instead of shape for the shape key:
m.set({ marker: shape.up, color: color.green })Handle methods:
m.set(options?) -> handle— update any options, returns the handle for chainingm.clone(newKey) -> handle— duplicate the entity under a new keym.delete() -> boolean— remove from chart
Arrow
Arrow(key, options?) -> handleDraws an arrow between two coordinate points.
//@version=2
indicator("Arrow Example", true)
const candles = subscribe(data.OHLCV)
function onBar(index) {
if (barIndex() < 10) return
Arrow("projection", {
x1: unix(10),
y1: candles.low(10),
x2: unix(0),
y2: candles.high(),
width: 2,
color: color.green,
style: linestyle.dashed,
headLengthPx: 10,
headWidthRatio: 0.75,
zIndex: 6
})
}| Option | Type | Required | Default | Description |
|---|---|---|---|---|
x1 | number | no | 0 | Start x coordinate (unix timestamp) |
y1 | number | no | 0 | Start y coordinate (price) |
x2 | number | no | 0 | End x coordinate (unix timestamp) |
y2 | number | no | 0 | End y coordinate (price) |
width | number | no | 1.5 | Arrow shaft width in pixels |
color | color | no | #466BE5 | Arrow color |
style | linestyle.solid | linestyle.dotted | linestyle.dashed | no | linestyle.solid | Arrow line style |
headLengthPx | number | no | 8 | Arrow head length in pixels |
headWidthRatio | number | no | 0.6 | Arrow head width relative to head length |
zIndex | number | no | 0 | Renderer z-order value |
forceOverlay | bool | no | false | Promote this arrow to the overlay chart. Sticky per key/handle identity. |
Handle methods:
a.set(options?) -> handle— update any options, returns the handle for chaininga.clone(newKey) -> handle— duplicate the entity under a new keya.delete() -> boolean— remove from chart
LineFill
LineFill(key, lineA, lineB, options?) -> handleFills the area between two live Line handles.
//@version=2
indicator("LineFill Example", true)
const candles = subscribe(data.OHLCV)
function onBar(index) {
if (barIndex() < 10) return
const top = Line("top", { x1: unix(10), y1: candles.high(10), x2: unix(0), y2: candles.high() })
const bottom = Line("bottom", { x1: unix(10), y1: candles.low(10), x2: unix(0), y2: candles.low() })
LineFill("band", top, bottom, { color: color.transp(color.blue, 85) })
}| Option | Type | Required | Default | Description |
|---|---|---|---|---|
color | color | no | color.white | Fill color |
LineFill() does not take forceOverlay. Both source lines must already use the same sticky forceOverlay value.
Invalid LineFill() mismatch:
//@version=2
indicator("Invalid LineFill Overlay Mix", false)
const candles = subscribe(data.OHLCV)
function onBar(index) {
const top = Line("top", { x1: unix(10), y1: candles.high(10), x2: unix(0), y2: candles.high(), forceOverlay: true })
const bottom = Line("bottom", { x1: unix(10), y1: candles.low(10), x2: unix(0), y2: candles.low() })
LineFill("band", top, bottom, { color: color.transp(color.blue, 85) }) // throws
}Handle methods:
fill.set(options?) -> handle— update source lines and colorfill.clone(newKey) -> handle— duplicate the entity under a new keyfill.delete() -> boolean— remove from chart
Global Delete
You can also delete any entity handle using the global helper:
entity.delete(handle) // -> booleanExample
//@version=2
indicator("Entity Handle Example", true)
const candles = subscribe(data.OHLCV)
function onBar(index) {
if (barIndex() < 10) return
const ln = Line("main", { x1: unix(10), y1: candles.low(10), x2: unix(0), y2: candles.high() })
// Update the handle returned for this bar.
ln.set({ x2: unix(0), y2: candles.high(), color: color.red })
// After delete(), do not call ln.set()/ln.clone()/ln.delete() again.
if (context.isRealtime) {
entity.delete(ln)
}
}