Skip to main content

Two phases of execution

Every custom indicator script has two distinct execution phases:
Top-level code runs once. Per-bar computation goes inside onBar. Mixing them up is the most common mistake new authors make.

The i argument

onBar receives a single argument i - the current bar index (0 = oldest bar in the window, ctx.length - 1 = newest). It is equivalent to calling ctx.i() inside the callback.

What belongs where

Side-effect ordering

  1. All input.* values are resolved from the Inputs panel (or defaults).
  2. All plot(name, null, opts) calls register plot series.
  3. onBar callback is registered but not yet invoked.
  4. The runtime replays all historical bars, calling onBar(i) for each in ascending bar-index order.
  5. On each realtime update, onBar(i) is called again for the current bar.
Calling input.* inside onBar throws a RuntimeError. Always declare parameters at the top level.

Minimal template

Inputs

All input types and the form controls they produce.

Bar context

ctx.open, ctx.close, ctx.i, ctx.isLast and friends.

Series

Persistent indexed storage across bars.

Plot basics

How to register and emit plot values.