ChartnautDocs

Overlay vs pane

meta({...}) is the first call in every indicator. It names the indicator, decides where it draws and what data it reads. Call it exactly once: a second call is an error, and an unknown key is an error that lists the valid ones.

Signature

meta({
  shortName: string;                       // required: the legend label
  kind: "overlay" | "pane" | "chart";      // required
  dataSource?: { type: "candles" }
             | { type: "volume-candles"; settings: { purgeStrategy: "floor-aware" | "max-bars" | "session-daily" } }
             | "candles" | "volume_candles";
  category?: string;                       // library grouping, e.g. "custom"
  runOn?: string[];                        // allowed chart timeframes
  runOnReason?: string;                    // shown when the chart timeframe is blocked
  window?: { on?: ["barClose"] };          // when the script runs
  mode?: "continuous" | "once";
  runWindow?: "visible" | "loaded" | { lookback: string } | { bars: number } | { from: number; to: number };
}): void

kind

kind

Draws

"overlay"

On the price pane, over the candles (moving averages, VWAP, bands)

"pane"

In the indicator's own subpane (RSI, MACD, ATR)

"chart"

As the chart itself: the candles are hidden and the indicator appears in the chart type picker. Needs at least one output.layer with paint or paintGL. See Layers.

kind only sets the default. pane({ id }) declares named subpanes that any output can be sent to, so an overlay indicator can own subpanes too. Routing, pane options and price scales are on Panes & scales.

meta({ shortName: "RSI", kind: "pane" });

How much history the script needs

History is declared with two top-level calls placed after the inputs, so they can read input handles. meta holds none of it.

warmup(...) is how far back the script's state remembers. The runtime walks that much history before the range you look at, so accumulated state has settled by the first visible bar and does not change as you scroll.

State

Warmup

A lookback of N bars (SMA, Donchian, rolling max)

warmup((w) => w.window(length))

An EMA

warmup((w) => w.ema(length))

Wilder smoothing (RSI, ATR, ADX, RMA)

warmup((w) => w.wilder(length))

Resets every session or day (a session VWAP)

warmup((w) => w.day())

Never forgets (a running sum, a count, a trend flag)

warmup((w) => w.forever())

meta({ shortName: "RSI", kind: "pane" });

const length = input.number({ id: "length", label: "Length", default: 14, min: 1 });
warmup((w) => w.wilder(length));

A script that keeps state in ctx.accum and declares no warmup fails lint with window/warmup-required. A script that keeps no state declares nothing. Declaring more than your plan's indicator memory is clamped, with a window/clamped-to-cap warning. Every term, and how each resolves per timeframe, is on Warmup and memory.

retain(...) is how many buckets stay readable through a timeframe handle's bars(n) (64 by default). Raise it when the script reads a span rather than accumulating over one, for example retain({ "1d": 250 }) or retain((r) => r.span("20d")). The full rules are in Timeframe handles and runOn.

dataSource

Candles (OHLCV) by default. Footprint and volume profile scripts that read ctx.volumePriceLevels declare the volume-at-price tape:

meta({
  shortName: "Footprint",
  kind: "overlay",
  dataSource: { type: "volume-candles", settings: { purgeStrategy: "floor-aware" } },
});

Without it ctx.volumePriceLevels is an empty array. The object form needs settings.purgeStrategy, or lint fails with meta/volume-candles-purge-required. Write "floor-aware": the three values behave the same today. See Price and bar data.

runOn

runOn: ["5m", "15m"] limits the chart timeframes the indicator runs on; runOnReason is the message shown on any other timeframe. It is a timeframe list, not a cadence. See Timeframe handles and runOn.

mode: "once"

mode: "once" runs an onRun(ctx) function one time over a fixed bar window chosen by runWindow (default "visible"), then freezes. It never recalculates and never appears in the indicator legend. The Agent uses it for one-off analysis on a chart. It requires kind: "overlay", and a script exports either onBar or onRun, never both.

Not definition meta

Definitions use kind: "flow" and their own fields. See Meta.