feature

Session OR break

Builds a session opening range from the first N bars after session open, then emits once when price breaks the high (or low) after the range is locked.

What it defines

Events or_break_up / or_break_dn with the OR high/low and break price — one break direction per session via oncePer.

Key decisions

Piece

Why it matters

ctx.session({…})

Definition session object (didOpen, key, …) — not indicator isStart.

OR state in ctx.accum

Remembers high/low/bar count across bars; resets on didOpen.

Emit only after range locked

Avoid firing during the building window.

Separate event ids + oncePer on session

One up and one down break max per session, no hand-rolled dedupe.

Full script

meta({
  name: "OR break",
  kind: "flow",
  slug: "or-break",
  shortName: "ORBreak",
});

events.declare({
  id: "or_break_up",
  intent: "Close breaks above session opening range",
  payload: {
    orHigh: { type: "number", description: "Opening range high" },
    orLow: { type: "number", description: "Opening range low" },
    close: { type: "number", description: "Break close" },
    sessionKey: { type: "string", description: "Session key" },
  },
  paint: "pin",
  oncePer: { keys: ["session"] },
});

events.declare({
  id: "or_break_dn",
  intent: "Close breaks below session opening range",
  payload: {
    orHigh: { type: "number", description: "Opening range high" },
    orLow: { type: "number", description: "Opening range low" },
    close: { type: "number", description: "Break close" },
    sessionKey: { type: "string", description: "Session key" },
  },
  paint: "pin",
  oncePer: { keys: ["session"] },
});

outputs.declare({ id: "or_high", kind: "line", name: "OR high", color: "#26a69a" });
outputs.declare({ id: "or_low", kind: "line", name: "OR low", color: "#ef5350" });

const OR_BARS = 5;

export function onBar(ctx) {
  const s = ctx.session({});

  const st = ctx.accum("or", null, (prev) => {
    if (s.didOpen || prev == null) {
      return {
        key: s.key,
        bars: 1,
        high: ctx.high,
        low: ctx.low,
        locked: false,
      };
    }
    if (prev.locked) return prev;
    const bars = prev.bars + 1;
    const high = Math.max(prev.high, ctx.high);
    const low = Math.min(prev.low, ctx.low);
    return {
      key: s.key,
      bars,
      high,
      low,
      locked: bars >= OR_BARS,
    };
  });

  if (!st.locked) return;

  ctx.plot("or_high", st.high);
  ctx.plot("or_low", st.low);

  const base = {
    orHigh: st.high,
    orLow: st.low,
    close: ctx.close,
    sessionKey: st.key,
  };

  if (ctx.close > st.high) {
    ctx.emit("or_break_up", base, {
      label: "OR break ↑",
      subtitle: `H ${st.high.toFixed(2)}`,
      price: ctx.close,
      timeStart: ctx.time,
    });
  } else if (ctx.close < st.low) {
    ctx.emit("or_break_dn", base, {
      label: "OR break ↓",
      subtitle: `L ${st.low.toFixed(2)}`,
      price: ctx.close,
      timeStart: ctx.time,
    });
  }
}

Tune SessionOpts in IntelliSense for your market (exchange RTH vs named London/NY sessions). See Sessions.

Next

  1. Examples

  2. Sessions

  3. First definition guide