Skip to content

DSL Chart API

Chart API is available to indicator scripts.

plot

Draws a line series.

plot(ma, title="MA", color="#2962FF", width=2, style="line")

Options:

Option Description
title Display name
color Line color
width Line width
style "line" (default), "step", or "histogram"

hline

Draws a horizontal level.

hline(0, title="Zero", color="#999999", width=1)

plotText

Draws a text label anchored to a candle and a price. Available only in indicator scripts.

plotText(price, when=1, text="{price}", color="#2962FF", position="above", fontSize=12, closedOnly=1, style="text", background="#2962FF")

Exactly one positional argument is required; all other arguments are named. Arguments are evaluated for each candle.

Argument Default Description
price Required Finite numeric price used as the vertical anchor; missing or non-finite prices produce no label
when 1 Boolean or finite number; false or zero suppresses the label
text "{price}" Plain text, up to 256 UTF-16 code units; an empty string produces no label
color "#2962FF" Six-digit #RRGGBB color or "contrast" for the chart theme's contrast color
position "above" "above", "below", or "center", relative to the price anchor
fontSize 12 Numeric font size from 8 to 24
style "text" "label" draws a rounded badge with a pointer toward the candle
background "#2962FF" Six-digit hex badge background
closedOnly 1 1/true excludes the last candle; 0/false allows labels on the forming candle

The renderer replaces every {price} token with the anchor price formatted using the instrument's price precision. Text is not HTML. Line breaks are collapsed for single-line display; long labels are shortened with an ellipsis to fit the chart.

Use plotText as a standalone statement at top level or inside if. It cannot be assigned to a variable, nested in an expression, placed inside a loop, or used by robots. Invalid option values stop the calculation with a validation/runtime error.

Only the latest 200 labels per calculation are retained, across all plotText calls. Labels follow chart scrolling and zooming and are clipped to the chart viewport. Recalculation replaces the label set; removing or stopping the indicator releases its text rendering resources.

The last candle is treated as forming, including when viewing historical data. With the default closedOnly=1, a signal there appears only after another candle is available. Use closedOnly=0 for live labels that may change or disappear before the candle closes.

MA Crossover Labels

script("MA Cross Labels", kind="indicator")

input fastLength = 20
input slowLength = 50

fast = ta.sma(close, fastLength)
slow = ta.sma(close, slowLength)
crossUp = ta.crossover(fast, slow)
crossDown = ta.crossunder(fast, slow)

plot(fast, title="Fast MA", color="#2962FF", width=2)
plot(slow, title="Slow MA", color="#FF9800", width=2)
plotText(fast, when=crossUp, text="Cross up: {price}", color="#2962FF", position="below")
plotText(fast, when=crossDown, text="Cross down: {price}", color="#FF9800", position="above")

This example labels the fast MA value on the signal candle. It does not calculate an interpolated intersection price between candles. See signal functions for crossover conditions and examples.

Filled bands, backgrounds and line colors

These effects are rendered in the script pane, or on the main chart when no pane is declared. Except colorSeries on plot/fill, their named options must be literals or scalar input values. Register them at top level; they are registered once on the first bar. Assign conditions and boundaries to named series first.

script("Trend band", kind="indicator")
input shade = "#76F7B8"
upper = ta.highest(high, 14)
lower = ta.lowest(low, 14)
up = close > open
plot(upper, style="step")
plot(lower, style="step")
fill(upper, lower, color=shade, opacity=0.25, gradient=1, style="step")
bgcolor(up, color=shade, opacity=0.05)
color(upper, up, up="#76F7B8", down="#FF4422", neutral="#999999", mode="binary")

fill supports opacity 0..1, style="line"/"step", and gradient=1 for eight shaded bands. Missing boundaries break the fill. bgcolor fills candle strips when the named condition is truthy. color changes plotted series colors: binary mode uses truthiness; mode="ternary" uses positive/up, negative/down, zero/neutral. Missing plot values break lines. Histogram plots draw columns from zero with per-bar conditional colors and opacity. Area plots are not rendered. An independent pane is declared with pane(...) below.

plotShape

plotShape(low, when=close > open, shape="triangleUp", color="#76F7B8", position="below", size=10, closedOnly=1)

Exactly one positional price; other arguments are named. Shapes: triangleUp, triangleDown, circle, diamond, square; size 4..32. Price/condition/color/position and closed-bar checks follow plotText. Up to 200 shapes are retained per calculation. Standalone indicator statement, allowed in if, not in loops or expressions.

Keyed chart objects

Required positional arguments precede optional named options:

draw.line(id, x1, price1, x2, price2, color="#76F7B8", width=1, style="solid", extend="none", text="")
draw.box(id, left, top, right, bottom, color="#76F7B8", opacity=0.15, text="", midline=0)
draw.label(id, at, price, text, color="#76F7B8", position="above", fontSize=10)
draw.remove(id)

Use only as standalone indicator statements, including inside if and for; never assign their return value. Calling the same ID replaces its object, even if the type changes. Removing an absent ID is a no-op. IDs are nonempty strings up to 128 UTF-16 units.

X coordinates are bar indices, not timestamps: nonnegative safe integers, end >= start, and at most barIndex + 500. Prices must be finite and box top >= bottom. extend="right" extends a line/box to the viewport edge independently of its finite endpoint.

Shared named drawing options:

Option Default Allowed values
color "#76F7B8" Six-digit hex
width 1 0..8
opacity 0.15 0..1; box fill
style "solid" solid, dashed, dotted
extend "none" none, right
text "" Up to 128 UTF-16 units; label text is positional
midline 0 0/1; box midpoint line
fontSize 10 8..24
position "above" above, below, center

Object state is rebuilt from history on every evaluation. At most 500 objects are retained; a new ID at capacity evicts the oldest inserted object. Renderer clipping and label prioritization can hide overlapping/offscreen captions. Total rendered text is bounded to 200 labels, shared with plotText.

Candle colors

barcolor(isClosed and close > open, color="#76F7B8")

One positional condition (boolean or finite number), optional six-digit hex color. Standalone indicator statement, allowed in if, not loops. Overrides bodies, borders and wicks for candle/hollow-candle charts. For a candle, the last applicable visible script wins. It does not recolor other chart types. Up to 10,000 color records per calculation. Add isClosed when forming-candle recoloring is unwanted.

Local alert conditions

alertcondition(isClosed and close > open, title="Bullish candle", message="Closed above open")

One positional boolean/finite-number condition. Named title defaults to "Signal" (up to 128 UTF-16 units), message defaults to the title (up to 1000 units). Standalone indicator statement, allowed in if, not loops. Only the latest closed candle is considered, with up to 64 signal records per evaluation.

The terminal emits signals to the local script console only after its initial time watermark. Startup, historical backfill, repeated results and source/symbol/timeframe scope changes do not replay historical alerts. Signals do not execute trades and do not configure server alerts, email or push delivery.

Independent oscillator pane

script("Flow example", kind="indicator")
value = close - ta.ema(close, 20)
missingVolume = na(volume) or volume <= 0
pane(title="Flow example", height=28, note="No volume: price-only", noteWhen=missingVolume)
plot(value, style="histogram", color="#76F7B8", opacity=0.3)
hline(0, color="#999999", style="solid", opacity=0.5)

One pane() declaration is allowed at top level of an indicator, outside branches and loops. All visual output of that script uses the pane's scale; mixing price overlays with pane output in one script is not supported. Existing scripts without pane() remain price overlays.

Option Contract
title Optional title, up to 128 UTF-16 units
height Percentage of usable chart height, 10–50; default 25
min, max Both finite, min < max; omit both for visible-output autoscaling
note Optional status text, up to 256 UTF-16 units
noteWhen Optional named condition series; evaluated on the last visible candle

Except noteWhen, options must be literals or scalar inputs. Panes share the time axis with price and have independent numeric scales. Autoscaling considers plotted output, fill boundaries, levels and visible markers/objects; internal unplotted price/volume series do not affect it. Histograms include zero. Script pane heights are recomputed on resize and share a 70% chart-height budget including native panels. Runtime heights are not saved as chart settings. Script panes sit above native indicator panels.

hline supports style="solid", "dashed", "dotted" and opacity=0..1 in either mode.

Badges on confirmed pivots

script("Pivot badges", kind="indicator")
value = close - ta.ema(close, 20)
pivot = ta.pivotlow(value, 3, 3)
pane(title="Pivot badges", height=25)
plot(value)
if isClosed and not na(pivot) {
  draw.label("low" + barIndex, barIndex - 3, pivot, "R", color="#142820", background="#76F7B8", badge=1, position="below")
}

draw.label accepts badge=0/1 (default 0) and a six-digit hex background (defaults to color). Badge captions use the same clipping/resource limits as text labels. An anchor on a past bar does not backdate the object's confirmation time.

Confidence color gradients

math.colorGradient(value, min, max, fromHex, toHex) returns a six-digit RGB hex color by clamped linear interpolation. Value/min/max must be finite with min < max; colors must be six-digit hex. The returned string can be used in per-bar barcolor or drawing-object options. Once-registered plot options still require literals/scalar inputs.

script("RSI shade", kind="indicator")
strength = nz(ta.rsi(close, 14), 50) / 100
shade = math.colorGradient(strength, 0, 1, "#FF4422", "#76F7B8")
barcolor(isClosed, color=shade)

Dynamic line and fill colors

plot(..., colorSeries=shade) and fill(..., colorSeries=shade) accept a previously calculated named color series. Its values must be six-digit hex strings; null/na/undefined create gaps. Malformed colors fail in the worker before rendering. ColorSeries takes priority over static color and color() rules. Other once-registered options still use literals or scalar inputs.

script("Colored ribbon", kind="indicator")
fast = ta.ema(close, 5)
slow = ta.ema(close, 21)
shade = fast > slow ? "#24B8FF" : "#B06CFF"
plot(fast, colorSeries=shade)
fill(fast, slow, colorSeries=shade, opacity=0.3)

Cell bands

fill(upper, lower, style="cells", colorSeries=shade) renders one candle-width rectangle between current upper/lower values per bar. It can draw fixed ranking strips, power bars and matrices without allocating keyed objects. Missing bounds/colors suppress the cell. Line/step fills continue to interpolate between adjacent valid bars.

script("Strength band", kind="indicator")
strength = nz(ta.rsi(close, 14), 50) / 100
shade = math.colorGradient(strength, 0, 1, "#332724", "#76F7B8")
top = 110
bottom = 104
pane(title="Strength", min=-120, max=120)
fill(top, bottom, colorSeries=shade, style="cells")

plotShape also supports diamond and square, with the existing size 4–32, closedOnly and 200-record limits.