feature

Supertrend

Public library indicator Supertrend (supertrend). Same source as the Chartnaut-owned row in the live indicator table.

What it plots

One overlay trail that flips between ATR-based support and resistance as trend direction changes.

Key decisions

Piece

Why it matters

ATR via ctx.accum

Volatility band width tracks true range.

State object in accum

Remembers final upper/lower and whether trend is up.

Flip rules on close vs bands

Close through upper → uptrend (plot lower); through lower → downtrend (plot upper).

Full script

meta({
  shortName: "Supertrend",
  kind: "overlay",
  dataSource: "candles",
  category: "custom",
});

dialog({
  title: "Supertrend Configuration",
  description: "Configure Supertrend indicator settings",
  width: 400,
  height: 400,
  resizable: false,
  showEnabledCheckbox: true,
  resetToDefaults: {
    enabled: true,
    confirmationMessage: "Are you sure you want to reset all Supertrend settings to their default values?",
  },
});

const atrPeriod = input.number({
  id: "atrPeriod",
  label: "ATR Period",
  default: 10,
  min: 1,
  step: 1,
});

const multiplier = input.number({
  id: "multiplier",
  label: "Multiplier",
  default: 3.0,
  min: 0.1,
  step: 0.1,
});

const lineColor = input.color({
  id: "lineColor",
  label: "Line Color",
  default: "#2962FF",
  allowAlpha: true,
});

const lineStyle = input.lineStyle({
  id: "lineStyle",
  label: "Line Style",
  default: LineStyle.Solid,
});

const labelsEnabled = input.boolean({
  id: "labelsEnabled",
  label: "Show Labels",
  default: true,
});

layout(
  tab({ id: "general", title: "General" },
    section({ id: "parameters", title: "Parameters" }, atrPeriod, multiplier),
    section({ id: "display", title: "Display Options" }, labelsEnabled),
  ),
  tab({ id: "appearance", title: "Appearance" },
    section({ id: "line", title: "Line", columns: 2 }, lineColor, lineStyle),
  ),
);

output.line({
  id: "supertrend",
  lineWidth: 2,
  colorFrom: lineColor,
  lineStyleFrom: lineStyle,
  labelFrom: labelsEnabled,
  titleWhenLabeled: "Supertrend",
});

/** @param {ScriptedCtx} ctx */
export function onBar(ctx) {
  var period = ctx.params.atrPeriod || 10;
  var mult = ctx.params.multiplier || 3.0;

  var buf = ctx.accum("buf", [], function (prev) {
    prev.push({ high: ctx.high, low: ctx.low, close: ctx.close });
    return prev;
  });

  if (buf.length < 2) return;

  var i = buf.length - 1;
  var tr = Math.max(
    buf[i].high - buf[i].low,
    Math.abs(buf[i].high - buf[i - 1].close),
    Math.abs(buf[i].low - buf[i - 1].close)
  );

  var atr = ctx.accum("atr", 0, function (prev) {
    if (buf.length <= period) {
      var sum = 0;
      for (var j = 1; j < buf.length; j++) {
        sum += Math.max(
          buf[j].high - buf[j].low,
          Math.abs(buf[j].high - buf[j - 1].close),
          Math.abs(buf[j].low - buf[j - 1].close)
        );
      }
      return sum / (buf.length - 1);
    }
    return (prev * (period - 1) + tr) / period;
  });

  if (buf.length <= period) return;

  var hl2 = (ctx.high + ctx.low) / 2;
  var basicUpper = hl2 + mult * atr;
  var basicLower = hl2 - mult * atr;

  var state = ctx.accum("state", null, function (prev) {
    if (prev === null) {
      var up = buf[i - 1].close > hl2;
      return {
        finalUpper: basicUpper,
        finalLower: basicLower,
        isUp: up,
        supertrend: up ? basicLower : basicUpper,
      };
    }

    var finalUpper = (basicUpper < prev.finalUpper || buf[i - 1].close > prev.finalUpper)
      ? basicUpper : prev.finalUpper;
    var finalLower = (basicLower > prev.finalLower || buf[i - 1].close < prev.finalLower)
      ? basicLower : prev.finalLower;

    var isUp = prev.isUp;
    if (!isUp && ctx.close > finalUpper) {
      isUp = true;
    } else if (isUp && ctx.close < finalLower) {
      isUp = false;
    }

    return {
      finalUpper: finalUpper,
      finalLower: finalLower,
      isUp: isUp,
      supertrend: isUp ? finalLower : finalUpper,
    };
  });

  ctx.plot("supertrend", state.supertrend);
}

Next

  1. Indicator examples

  2. Indicator series types

  3. Declaring indicator dependencies