ChartnautDocs

Bull bar

Marks every bar that closes above its open. The payload carries the bar's range so a study can filter on it later.

What it defines

An event bull_bar on every bar where close > open.

Key decisions

Piece

Why it matters

kind: "flow"

Enables events.declare and ctx.emit.

events.declare with a payload schema

The contract studies read. Every field has a description.

label on ctx.emit

An emit without a label is dropped.

Early return on other bars

Keeps onBar cheap when the setup is false.

No ctx.accum

The script keeps no state, so it declares no warmup.

Full script

meta({
  name: "Bull bar",
  kind: "flow",
  slug: "bull-bar",
  shortName: "BullBar",
});

events.declare({
  id: "bull_bar",
  intent: "signal",
  payload: {
    range: { type: "number", description: "High minus low of the bar" },
    close: { type: "number", description: "Close of the bar" },
  },
  paint: "pin",
});

outputs.declare({
  id: "close_line",
  kind: "line",
  name: "Close",
  color: "#64b5f6",
});

export function onBar(ctx) {
  ctx.plot("close_line", ctx.close);

  if (ctx.close <= ctx.open) return;

  const range = ctx.high - ctx.low;
  ctx.emit(
    "bull_bar",
    { range, close: ctx.close },
    {
      label: `Bull · R=${range.toFixed(2)}`,
      subtitle: `close ${ctx.close.toFixed(2)}`,
      price: ctx.close,
    }
  );
}

timeStart and timeEnd default to the bar's time, so a one-bar event needs neither. Next, EMA cross reads another indicator.