home Scripting Guide

Drawing & Indicators

Everything under TD.Chart for putting lines, markers, shapes, boxes and text on the chart - plus how to read the same values the built-in indicators use.

Chart Context

What symbol and timeframe your script is drawing on

const ctx = TD.Chart.getContext();
// { symbol:"NIFTY 50", underlying:"NIFTY", exchange:"NSE", symbolType: ..., interval: 5 }

const sym = TD.Chart.getSymbol(); // "NIFTY 50"

underlying is the option-chain name for the chart's instrument - NIFTY 50, NIFTY-I and NIFTY26100622600CE all give NIFTY. Don't store the context in a variable at the start of your script, since the user can change the symbol while it runs - call getContext() each time you need it.

Lines and Histograms

TD.Chart.plot(name, value, options)

TD.Chart.plot("EMA 21", emaValue, { color: "#FF9800" }); // on the price chart
TD.Chart.plot("Momentum", mom, { color: "#26A69A", overlay: false }); // separate pane
TD.Chart.plot("Delta", d, { overlay: false, style: "histogram", color: "#888" }); // histogram
TD.Chart.plot("Level", lvl, { style: "stepline" }); // step line
Option · Values · Default
color Any CSS colour. Defaults to the script's own colour.
overlay true for the price chart, false for a separate pane. Defaults to true.
style "histogram", "stepline", or omit for a line.
time Bar time. Set automatically inside onChartBar, where it defaults to the current bar.
info

Series names: only letters and digits count, so "EMA 21" and "EMA-21" are the same series. Give each series a clearly different name.

Buy / Sell Markers

TD.Chart.plotMarker(price, side, options)

TD.Chart.plotMarker(bar.low, "buy"); // green up-arrow
TD.Chart.plotMarker(bar.high, "sell", { color: "#FF00FF" }); // custom colour
TD.Chart.plotMarker(bar.low, "buy", { id: "entry_" + bar.time }); // stable id

side is "buy" (green up-arrow) or "sell" (red down-arrow). Options are color, shape ("arrowUp", "arrowDown" and similar), time and id. Without an id, a bar can have only one buy marker and one sell marker - plotting again on the same bar moves the existing marker.

Shapes

TD.Chart.plotShape(type, price, options)

Shape types
Single-point arrowUp, arrowDown, arrowLeft, arrowRight, circle, square, diamond, dot, triangle, ellipse, text
Lines horizontalLine, verticalLine
Multi-point trendLine, rectangle, polygon, polyline - these need options.points
// Horizontal support line
TD.Chart.plotShape("horizontalLine", 22450, {
 id: "support", color: "#16A34A", lineWidth: 2, lineStyle: "dash"
});

// Trend line between two bars
TD.Chart.plotShape("trendLine", 0, {
 id: "tl1",
 points: [{ time: t1, price: 22300 }, { time: t2, price: 22520 }],
 lineColor: "#3B82F6", lineWidth: 1
});

// Dot above a bar
TD.Chart.plotShape("dot", bar.high * 1.001, { color: "orange" });
Styling option · Meaning
id Stable identifier. Plotting again with the same id updates the shape in place instead of adding a new one.
color Base colour, used for both line and fill.
lineColor / lineWidth / lineStyle lineWidth: 0 means no border. Style is "solid", "dash" or "dot".
fillColor / fillOpacity Fill colour and opacity (0-1).
textColor / fontSize Text styling.
time Anchor time. Set automatically inside onChartBar.
Behaviour option · Meaning
savable: false Leaves the shape out of the saved chart layout - recommended for generated drawings.
selectable: false The user can't select or move the shape.
hoverable: false The shape doesn't react to the mouse.
locked: true Locks the shape in place.
tips_and_updates

For drawings your script generates in large numbers - profiles, zones, labels - pass { savable: false, selectable: false, hoverable: false }. With all three set, the chart stays responsive even with hundreds of shapes.

warning_amber

Always use an id for horizontalLine and verticalLine. Without one, each script can draw only one of each, and every new call moves it.

Boxes and Zones

TD.Chart.plotBox(id, box, options) - a filled rectangle between two prices

// A. Anchored to time — the box moves with the candles
TD.Chart.plotBox("demand_zone", { from: startTime, to: endTime, low: 22300, high: 22350 },
 { fillColor: "#16A34A", fillOpacity: 0.15, lineWidth: 0, savable: false });

// B. Anchored to the screen edge — box stays put while you scroll/zoom
TD.Chart.plotBox("oi_22500_call", {
 anchor: "right", offset: 0.004, width: 0.4,
 low: 22500, high: 22510, heightPx: 10, heightAnchor: "low"
}, { fillColor: "#E05252", fillOpacity: 0.35, lineWidth: 0 });
Field · Meaning
low, high Price range (required).
from, to Start and end times (option A).
anchor "right" or "left" - the chart edge to pin to (option B).
offset Gap from that edge, as a fraction of chart width (0-1).
width Box length, as a fraction of chart width (0-1).
heightPx Maximum drawn thickness in pixels, so bands don't turn into thick blocks when zoomed in.
heightAnchor "low", "high" or "center" - which edge stays fixed under heightPx.
crop_free

Every box needs either from/to or anchor/width. A box with neither has zero width and doesn't appear - the console shows a notice.

Text Labels

TD.Chart.plotText(id, text, price, options)

TD.Chart.plotText("lbl_" + bar.time, "BUY", bar.low, {
 textColor: "#16A34A", fontSize: 10,
 offsetYPx: 14, // push down 14px (negative = up)
 savable: false, selectable: false, hoverable: false
});

// A label pinned to the right edge at a price level
TD.Chart.plotText("pcr", "PCR 1.12", 22600, { anchor: "right", offset: 0.01, textColor: "#999" });

The label's left edge sits at its anchor point, centred vertically on the price. Use offsetXPx and offsetYPx to move it by pixels. Calling it again with the same id updates the text and position.

Removing Drawings

TD.Chart.removeShapes(ids)

TD.Chart.removeShapes("support");
TD.Chart.removeShapes(["lbl_1", "lbl_2", "zone_A"]);

This removes only shapes your script created with those ids. Your own manual drawings and other scripts' drawings are never touched.

Adding a Built-in Indicator

TD.Chart.addBuiltInIndicator(name, options)

TD.onStart = () => {
 TD.Chart.addBuiltInIndicator("FastEMA", { periods: 50, color: "#FF9800" });
 TD.Chart.addBuiltInIndicator("FastRSI", { periods: 14 });
};

If the chart already has the same indicator with the same parameters, no duplicate is added.

Reading Built-in Indicators

TD.Chart.getIndicatorValues(name, parameters, options) returns the same values the chart draws

const adx = await TD.Chart.getIndicatorValues("FastADX", { periods: 14 });
// {
// status:"Success",
// indicator:"FastADX",
// names: ["FastADX","DI+","DI-"],
// times: [ ...epoch ms, oldest first... ],
// values: {"FastADX": [...],"DI+": [...],"DI-": [...] } // null where no value
// }
const last = adx.times.length - 1;
TD.log("ADX", adx.values["FastADX"][last], "+DI", adx.values["DI+"][last]);
Indicator · Line names · Typical parameters
FastADX FastADX, DI+, DI- · { periods: 14 }
FastSuperTrend Up, Down - one is null each bar · { periods: 10, multiplier: 3 }
FastATR FastATR · { periods: 14 }
FastEMA FastEMA · { periods: 14 }
Others FastRSI, FastSMA and the rest - read result.names to see their line names.
Options
count { count: 200 } returns only the newest 200 bars.
add { add: false } returns an error instead of adding the indicator when it isn't already on the chart. By default a missing indicator is added to the chart.
Naming Use the Fast… names, which match what the chart toolbar adds.
Recommended pattern

This call is asynchronous, so don't call it for every bar inside onChartBar. Collect the bars and read the indicator once, a moment after the history replay finishes.

const bars = [];
let timer = null;

TD.onChartBar = (bar) => {
 bars.push(bar);
 clearTimeout(timer);
 timer = setTimeout(analyse, 300); // runs once after the replay settles
};

async function analyse() {
 const rsi = await TD.Chart.getIndicatorValues("FastRSI", { periods: 14 });
 if (rsi.error) { TD.log("RSI not available: " + rsi.error); return; }
 const line = rsi.values[rsi.names[0]];
 const byTime = new Map(bars.map(b => [b.time, b]));
 rsi.times.forEach((t, i) => {
 const b = byTime.get(t);
 if (b && line[i] !== null && line[i] < 30) {
 TD.Chart.plotShape("dot", b.low, { id: "os_" + t, time: t, color: "#16A34A", savable: false });
 }
 });
}