MMTMMT Docs

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?) -> handle

Draws 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
  })
}
OptionTypeRequiredDefaultDescription
x1numberno0Start x coordinate (unix timestamp)
y1numberno0Start y coordinate (price)
x2numberno0End x coordinate (unix timestamp)
y2numberno0End y coordinate (price)
widthnumberno1Line width in pixels
colorcolornocolor.whiteLine color
stylelinestyle.*nolinestyle.solidLine style (solid, dotted, dashed, arrow.right, arrow.left, arrow.both)
labelstringno""Text label displayed on the line
zIndexnumberno0Renderer z-order value
forceOverlayboolnofalsePromote 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.right draws the arrowhead at x2,y2
  • linestyle.arrow.left draws the arrowhead at x1,y1
  • linestyle.arrow.both draws arrowheads at both ends

Handle methods:

  • ln.set(options?) -> handle — update any options, returns the handle for chaining
  • ln.clone(newKey) -> handle — duplicate the entity under a new key
  • ln.delete() -> boolean — remove from chart

Box

Box(key, options?) -> handle

Draws 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
  })
}
OptionTypeRequiredDefaultDescription
x1numberno0Left x coordinate (unix timestamp)
y1numberno0Top y coordinate (price)
x2numberno0Right x coordinate (unix timestamp)
y2numberno0Bottom y coordinate (price)
colorcolornocolor.whiteFill color
roundingnumberno0Corner radius in pixels
borderColorcolornofill colorBorder color
borderWidthnumberno0Border width in pixels
borderStylelinestyle.solid | linestyle.dotted | linestyle.dashednolinestyle.solidBorder style
extendextend.* or extend.*[]noextend.noneExtend the box left/right/up/down
textstringno""Text rendered inside the box
textSizesize.*nosize.autoBox text size
textColorcolornocolor.whiteText color
textHAligntext.align.*notext.align.centerHorizontal text alignment
textVAligntext.align.*notext.align.centerVertical text alignment
textWraptext.wrap.*notext.wrap.autoText wrapping mode
zIndexnumberno0Renderer z-order value
forceOverlayboolnofalsePromote this box to the overlay chart. Sticky per key/handle identity.

Handle methods:

  • box.set(options?) -> handle — update any options, returns the handle for chaining
  • box.clone(newKey) -> handle — duplicate the entity under a new key
  • box.delete() -> boolean — remove from chart

Label

Label(key, options?) -> handle

Places 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
  })
}
OptionTypeRequiredDefaultDescription
xnumberno0X coordinate (unix timestamp)
ynumberno0Y coordinate (price)
textstringno""Label text content
colorcolornocolor.whiteText color
sizenumberno12Font size
textAligntext.align.*notext.align.centerHorizontal text alignment; labels are always vertically centered
zIndexnumberno0Renderer z-order value
forceOverlayboolnofalsePromote this label to the overlay chart. Sticky per key/handle identity.

Handle methods:

  • tag.set(options?) -> handle — update any options, returns the handle for chaining
  • tag.clone(newKey) -> handle — duplicate the entity under a new key
  • tag.delete() -> boolean — remove from chart

Marker

Marker(key, options?) -> handle

Places 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
  })
}
OptionTypeRequiredDefaultDescription
xnumberno0X coordinate (unix timestamp)
ynumberno0Y coordinate (price)
shapeshape.*noshape.circleMarker shape (see Drawing Constants)
sizenumberno5Marker size in pixels
colorcolornocolor.whiteMarker color
zIndexnumberno0Renderer z-order value
forceOverlayboolnofalsePromote 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 chaining
  • m.clone(newKey) -> handle — duplicate the entity under a new key
  • m.delete() -> boolean — remove from chart

Arrow

Arrow(key, options?) -> handle

Draws 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
  })
}
OptionTypeRequiredDefaultDescription
x1numberno0Start x coordinate (unix timestamp)
y1numberno0Start y coordinate (price)
x2numberno0End x coordinate (unix timestamp)
y2numberno0End y coordinate (price)
widthnumberno1.5Arrow shaft width in pixels
colorcolorno#466BE5Arrow color
stylelinestyle.solid | linestyle.dotted | linestyle.dashednolinestyle.solidArrow line style
headLengthPxnumberno8Arrow head length in pixels
headWidthRationumberno0.6Arrow head width relative to head length
zIndexnumberno0Renderer z-order value
forceOverlayboolnofalsePromote this arrow to the overlay chart. Sticky per key/handle identity.

Handle methods:

  • a.set(options?) -> handle — update any options, returns the handle for chaining
  • a.clone(newKey) -> handle — duplicate the entity under a new key
  • a.delete() -> boolean — remove from chart

LineFill

LineFill(key, lineA, lineB, options?) -> handle

Fills 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) })
}
OptionTypeRequiredDefaultDescription
colorcolornocolor.whiteFill 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 color
  • fill.clone(newKey) -> handle — duplicate the entity under a new key
  • fill.delete() -> boolean — remove from chart

Global Delete

You can also delete any entity handle using the global helper:

entity.delete(handle) // -> boolean

Example

//@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)
  }
}

On this page