Scripting Guide: Getting Started
How to write your own scripts in the Script Engine panel - draw indicators, signals, zones and labels on your chart, read live and historical market data, and trigger alerts. Scripts are plain JavaScript, and every feature is available through a single global object called TD.
Quick Start
Have a script drawing on your chart in under a minute
NIFTY 50 on a 5-minute timeframe.// A 20-period simple moving average, drawn on the chart const LENGTH = 20; const closes = []; TD.onChartBar = (bar, index, isHistory) => { closes.push(bar.close); if (closes.length > LENGTH) closes.shift(); if (closes.length < LENGTH) return; const sma = closes.reduce((a, b) => a + b, 0) / LENGTH; TD.Chart.plot("SMA20", sma, { color: "#2962FF" }); }; TD.onStart = () => { TD.log("SMA started on " + TD.Chart.getSymbol()); };
SMA started on NIFTY 50.The Script Engine Panel
What each control does, and how the editor helps you as you type
TD.onStop firstTD.log output, errors and engine notices, grouping repeated lines with a counterType TD. for autocomplete on every function, and hover one to read its description. Snippets cover common patterns like TD.onChartBar.
Each running script gets its own colour. Anything you don't colour yourself is drawn in it, and the chart shows a small badge naming each script drawing on it.
Symbol mismatch warning. If your code doesn't mention the symbol on the active chart, the panel asks you to confirm before running - a script fetching RELIANCE data would otherwise silently draw on a NIFTY 50 chart. Click Run Anyway if that's intended, or tick Do not ask again.
How a Script Runs
Knowing the order of events helps you avoid most mistakes
Run clicked
¦
+- 1. The top-level code runs once (declare variables, CONFIG, functions, hooks)
+- 2. TD.onChartBar is called once for EVERY bar already on the chart (isHistory = true)
+- 3. The chart's symbol is subscribed to live data automatically
+- 4. TD.onStart() runs
¦
+- … live: TD.onChartBar(bar, -1, false) for each new 1-minute bar
+- … live: TD.on("tick"), TD.on("greeks"), TD.on("bidAsk") and other event listeners fire
+- … user changes symbol/timeframe → TD.onReset(ctx) → history replayed again (step 2)
¦
Stop clicked → TD.onStop() → script ends
onChartBar, no listeners, no timers means it finishes and shows === Script N Finished ===await with them, anything that fetches data returns a PromiseStart from a template under Open rather than a blank tab - it wires up the lifecycle hooks correctly, and you only have to change the logic in the middle.