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 | Volatility band width tracks true range. |
State object in | 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);
}