Docs·Delta DSL Script·Language

Inputs & directives

@version, @name, @pane, and @input — the four header directives that wire your script to the chart engine. Plus every input.* builder, its parameters, and the settings widget it produces.

The first few lines of every Delta DSL script are directives — declarative metadata the engine reads at script-load time to decide which language version the script targets, where the indicator lives, what it's called, and which knobs the user can tweak. Directives start with @, MUST sit on their own line, and conventionally cluster at the top of the file.

Four directives exist:

  • @version — pin the script to a specific Delta DSL language version (optional but recommended for new scripts).
  • @name — display name in the indicator catalog and legend.
  • @pane — where the indicator renders (overlay on candles, sub-pane below, or a custom aux pane).
  • @input — declare a user-tunable parameter and pick its widget.

@version

Delta DSL
@version 1          // pin to Delta DSL v1 — current language version
  • Optional. Defaults to v1 when omitted, so legacy scripts keep working unchanged.
  • Must be the first non-blank line if present (apart from comments and other directives — order among directives doesn't matter, but @version must precede every executable statement).
  • Accepts a positive integer. Bare integer form (@version 1) is canonical and matches Pine-style //@version=5. The quoted form (@version "1") is also accepted as an alias.
  • One per script. Declaring it twice is rejected.
  • Cannot exceed the platform's currently shipped version. Writing @version 9 against a v1 runtime surfaces an editor error.

The directive's job is to freeze your script's language semantics at the version you wrote it for. When the platform ships a future Delta DSL version with breaking changes, your @version 1 script keeps running under v1 rules — bullet-proof against semantic drift. New scripts adopting newer language versions opt in by bumping the value.

For the full migration story, see Versioning & Migration.

@name

Delta DSL
@name "RSI Divergence"
  • One per script (additional @name declarations override earlier ones).
  • The string becomes the legend label, the catalog title, and the alert builder section header.
  • Plain text only — emoji and HTML render literally and look wrong on the dark trading surface. Stick to ASCII / Unicode glyphs (·, , , ).
  • If omitted, the script falls back to "Untitled script" in the catalog.

@pane

Delta DSL
@pane "overlay"     // default — draw on the candle pane in price space
@pane "below"       // legacy single shared sub-pane at the bottom
@pane "rsi"         // independent aux pane keyed by id
@pane "macd"        // a second independent pane stacked below "rsi"

The pane id determines:

  • Which drawing primitives are available (overlay → plot*, sub-pane → pane* + panePlot*).
  • Whether the indicator's Y axis is price or its own value space.
  • Whether multiple scripts share a band (same id) or each get their own.

Pane id rules:

  • Lowercase letters, digits, _, and - only. Max 32 characters.
  • "overlay" and "below" are reserved (see below).
  • Any other id allocates an independent aux pane. Multiple scripts with the same id share the band; different ids stack vertically in registration order.

"overlay" (default)

Every plotLine / plotHline / plotBand / plotShape call renders on the candle pane via the engine's world_to_screen_y(price). Right mode for moving averages, Bollinger Bands, support/resistance, anchored VWAPs — anything in price space.

For oscillators (0-100 RSI, MACD histogram) drawn on the candle pane, you have to map the series into the visible price range or the line draws at the bottom of the chart and is invisible when price is in the thousands:

Delta DSL
@pane "overlay"

r = rsi(close, 14)

priceLow  = lowest(low,  200)
priceHigh = highest(high, 200)

rsiLine = normalize(r, 0, 100, priceLow, priceHigh)
plotLine(rsiLine, color="#F0B90B", width=1.5)

normalize(src, fromMin, fromMax, toMin, toMax) accepts series for toMin / toMax, so the overlay tracks price as you pan / zoom.

"below"

@pane "below" reserves a band at the bottom of the candle area, masks the candles behind it opaque so they don't bleed through, and remaps every pane* call into the band. Use it for momentum indicators with their own Y axis.

Delta DSL
@pane "below"
@name "RSI"
@input period = input.int(14, "Period")

paneHeight(0.25)        // 25 % of the candle area (0.10..0.50)
paneRange(0, 100)       // lock the Y axis (omit to auto-fit)

r = rsi(close, period)

paneBand(70, 30, color="rgba(240,185,11,0.06)")
paneLine(r, color="#F0B90B", width=1.5)
paneHline(70, color="#F23645", width=1)
paneHline(30, color="#0ECB81", width=1)
paneLabel(70, "70", align="left")
paneLabel(30, "30", align="left")

The pane Y axis prints three labels automatically (min / mid / max) on the right edge, plus the script's @name in the top-left of the band so users can tell which script owns the band.

See Panes for the full pane reference.

Custom aux pane (any other id)

Any id other than "overlay" / "below" allocates a dedicated aux pane that stacks below the "below" pane in registration order. Two scripts with the same id share one pane — useful for compound indicators (e.g. @pane "macd" for histogram + signal line + MACD line in the same band).

Delta DSL
@pane "rsi"
@name "RSI"
@input period = input.int(14, "Period")

paneHeight(0.18)
paneRange(0, 100)
r = rsi(close, period)
paneBand(70, 30, color="rgba(240,185,11,0.06)")
paneLine(r, color="#F0B90B", width=1.5)

A second script with @pane "macd" opens its own pane below the RSI pane, with its own Y range and crosshair tag.

Limitations (not blockers — things to know):

  • Aux pane order is registration order. To reorder, disable + re-enable scripts.
  • The candle pane's last price-axis tick may peek behind the topmost aux pane border by 1 px on Retina displays.

@input

Delta DSL
@input <name> = <default-or-builder> [, "Label"]

Two accepted shapes:

  1. Literal default — shorthand. The settings widget is inferred from the literal type.
    Delta DSL
    @input length = 20                    // → number stepper, no clamp
    @input use_ema = false                // → toggle
    @input mode = "standard"              // → text field
    @input lineColor = "#F0B90B"          // → color picker (recognises hex / rgba)
    @input title = 50, "Period"           // → number stepper labelled "Period"
    
  2. Typed builder — full control over the widget. Use this when you need clamps, dropdown options, or a label that doesn't fit on the same line.
    Delta DSL
    @input length = input.int(20, "Length", minval=2, maxval=500, step=1)
    @input mode   = input.string("standard", "Mode", options="standard,smooth,exp")
    @input src    = input.source("close", "Source")
    

Rules:

  • The identifier name (length, mode, src above) becomes a variable in the script's scope, bound to the current user value of that input.
  • Each @input declaration must sit on its own line.
  • Convention: cluster all @input declarations at the top, after @name / @pane. The order in the file is the order in the settings panel.
  • The optional "Label" after a comma overrides the builder's label argument when both are present (rare — usually you pick one).

The settings panel auto-builds itself from these declarations. No UI code anywhere.

Input builders

Seven typed builders, each rendering as a specific widget:

BuilderWidgetUsed for
input.intInteger stepperLookback periods, lengths
input.floatDecimal stepperMultipliers, thresholds
input.boolToggleFeature flags
input.stringText field or dropdownMode names, free text
input.sourceSource dropdownopen / high / low / close / hl2 / hlc3 / ohlc4
input.colorColor pickerHex / rgba colors
input.priceNumber stepper (price-formatted)Absolute price thresholds

input.int

Delta DSL
input.int(default, label, minval=…, maxval=…, step=1)
  • default — initial integer.
  • label (positional or label="…") — displayed in the settings panel.
  • minval, maxval — clamp the UI; the user cannot set values outside this range.
  • step — increment when clicking up/down on the stepper. Default 1.

Returns: the user's current int value (a scalar number).

Delta DSL
@input length = input.int(50, "Length", minval=2, maxval=500, step=1)

input.float

Delta DSL
input.float(default, label, minval=…, maxval=…, step=…)

Same as input.int but accepts decimals. Default step is 0.1.

Delta DSL
@input mult = input.float(2.0, "Std Dev", minval=0.1, maxval=10.0, step=0.1)

Returns: the user's current float value (a scalar number).

input.bool

Delta DSL
input.bool(default, label)

Renders a toggle. No clamp options.

Delta DSL
@input showSignals = input.bool(true, "Show signal markers")

Returns: true / false.

input.string

Delta DSL
input.string(default, label, options="a,b,c")
  • Without options= — renders as a free-text field. The user can type anything.
  • With options= — renders as a dropdown of comma-separated values. The default MUST be one of the options.
Delta DSL
@input mode = input.string("standard", "Mode",
                            options="standard,smoothed,exponential")
@input note = input.string("", "Note")             // free-text

Returns: the current string.

input.source

Delta DSL
input.source(default, label)

Dropdown of the eight pre-bound series: open / high / low / close / volume / hl2 / hlc3 / ohlc4. The runtime resolves the user's pick and binds the actual series to the variable — your script can call sma(src, 14) directly without dereferencing.

Delta DSL
@input src = input.source("close", "Source")

ma = sma(src, 20)
plotLine(ma, color="#F0B90B")

Returns: a series.

input.color

Delta DSL
input.color(default, label)

Renders a color picker. Default must be a #RRGGBB, #RRGGBBAA, or rgba(...) string.

Delta DSL
@input upColor = input.color("#0ECB81", "Bull color")
@input dnColor = input.color("#F6465D", "Bear color")

Returns: a color string suitable for any color= / bg= / border= argument.

input.price

Delta DSL
input.price(default, label, step=0.01)

Same shape as input.float but with finer-grained step defaults appropriate for price levels. Use for absolute price thresholds (a hard support level the user wants to monitor, a take-profit target, …).

Delta DSL
@input target = input.price(50000, "Target price", step=0.01)

isAboveTarget = close > target
plotBgColor(isAboveTarget, color="rgba(14, 203, 129, 0.04)")

Returns: a scalar number.

Common patterns

The settings panel renders inputs in declaration order. Group them by topic by ordering them deliberately:

Delta DSL
@input length    = input.int(50, "Length", minval=2, maxval=500)
@input src       = input.source("close", "Source")

@input upColor   = input.color("#0ECB81", "Bull color")
@input dnColor   = input.color("#F6465D", "Bear color")

@input showAlert = input.bool(true, "Enable alert")

The visual gap is implicit — there is no group= argument.

Validate a typed input

Builder clamps catch most bad inputs. For non-trivial validation (cross-input invariants — e.g. fast < slow), do a script-eval-time if and pick a safe fallback:

Delta DSL
@input fast = input.int(12, "Fast EMA", minval=2, maxval=200)
@input slow = input.int(26, "Slow EMA", minval=2, maxval=400)

if fast >= slow
  fast := 12
  slow := 26
end

The user sees the clamp take effect on the next redraw — the indicator just keeps working with sane defaults instead of flatlining.

Branch on a string mode

Combine input.string(options=...) with if blocks at the top of the script:

Delta DSL
@input mode = input.string("rsi", "Mode", options="rsi,stoch,cci")

if mode == "rsi"
  v := rsi(close, 14)
elseif mode == "stoch"
  v := stoch_k(close, high, low, 14)
else
  v := cci(high, low, close, 14)
end

paneLine(v, color="#F0B90B", width=1.5)

Source picker with custom default

input.source accepts the eight pre-bound names as defaults; pass any of them:

Delta DSL
@input src = input.source("hlc3", "Source")

Default "hlc3" is (high + low + close) / 3 — a smoother input than close for moving averages.

Order of operations at script-load time

When the engine loads your script:

  1. The analyzer scans all @name / @pane / @input declarations.
  2. The settings dialog is built from the ordered list of @input entries.
  3. The user's saved values for each @input are read; defaults fill in for inputs the user hasn't touched.
  4. The script body runs with each @input name bound to its current value.

This means an @input declaration's default is only used the first time the user enables your script. Subsequent loads use whatever the user set in the settings panel.

Next

  • Built-in variables — what close, time, bar_index actually contain.
  • Panes — the pane drawing primitives.
  • Recipes — full scripts with realistic input shapes.