No results for ""
Strict Rules
Read this once before writing any script. Violating these rules causes silent failures or wrong data — not crashes you'll notice immediately. Rule 17, covering REST call usage, lives on the Best Practices page alongside the Do/Avoid checklist.
All values from Feed / tick are strings
All values in the addSymbols response and tick/bar events arrive as strings, not numbers. Always use parseFloat() or parseInt() before doing math or comparisons.
const ltp = data[2]; // "1332.9" — math/comparison fails
const ltp = parseFloat(data[2]); // 1332.9
addSymbols takes symbol names, not IDs
Always pass the symbol name string, e.g. "RELIANCE", "NIFTY 50". Never pass numeric symbolIds.
await TD.Feed.addSymbols([100001262]);
await TD.Feed.addSymbols(["RELIANCE"]);
Always await Feed and Sheet calls
addSymbols, removeSymbols, setCell, setCellRange, getCell, getCellRange are all async. Missing await causes race conditions and unpredictable behavior.
TD.Feed.addSymbols(["RELIANCE"]);
await TD.Feed.addSymbols(["RELIANCE"]);
tick data[0] is a symbolId string, not the symbol name
In the tick event, data[0] is the symbolId (e.g. "100001262"), NOT the symbol name. To match by name, build a lookup map during onStart.
if (data[0] === "RELIANCE") { ... }
// data[0] is "100001262", not the name
const symbolMap = {}; // { symbolId: symbolName }
TD.onStart = async () => {
const response = await TD.Feed.addSymbols(["RELIANCE"]);
for (const sym of response.symbollist) {
symbolMap[sym[1]] = sym[0];
}
};
TD.on("tick", (data) => {
const name = symbolMap[data[0]]; // "RELIANCE"
});
addSymbols response is an object, not an array
The response has the shape { success, message, symbollist }. Access response.symbollist[0], not response[0].
const data = response[0]; // undefined
const data = response.symbollist[0];
Always check response.success before using symbollist
If the symbol name is invalid or the feed fails, success is false and symbollist is empty. Accessing symbollist[0] without checking will crash.
const response = await TD.Feed.addSymbols(["RELIANCE"]);
if (!response.success) {
TD.log("Subscribe failed: " + response.message);
return;
}
const data = response.symbollist[0];
Register TD.on() handlers outside all hooks
Event listeners must be at the top level of the script — not inside onStart, onStop, or any function.
TD.onStart = async () => {
TD.on("tick", (data) => { ... });
// inside a hook — wrong
};
TD.on("tick", (data) => { ... }); // top level
TD.onStart = async () => {
await TD.Feed.addSymbols(["RELIANCE"]);
};
Always unsubscribe in onStop
Every symbol subscribed in onStart must be unsubscribed in onStop to avoid memory leaks.
TD.onStop = async () => {
await TD.Feed.removeSymbols(["RELIANCE", "NIFTY 50"]);
};
Only four Sheet methods exist
Do not use or invent other Sheet methods. The only available ones are setCell, setCellRange, getCell, getCellRange. See Sheet Read / Write for full usage.
Analytics and Historical calls go inside TD.onStart
TD.Analytics.* and TD.Historical.* are async and must be awaited inside TD.onStart, or an async function called from it.
greeks needs a full option symbol string
Subscribe using the full TD option symbol format: "NIFTY26062323500CE" (symbol + YYMMDD + strike + CE/PE). Do not pass the base symbol like "NIFTY" or "NIFTY 50".
await TD.Feed.addSymbols(["NIFTY"]); // base symbol won't produce greeks
await TD.Feed.addSymbols(["NIFTY26062323500CE"]);
Option chain index symbols must be mapped first
The option chain API needs the mapped short symbol, not the display name. This mapping applies only to these five indices — every other symbol (e.g. "RELIANCE") passes through unchanged.
| Display name | Pass as symbol |
|---|---|
| NIFTY 50 | "NIFTY" |
| NIFTY BANK | "BANKNIFTY" |
| NIFTY MID SELECT | "MIDCPNIFTY" |
| NIFTY NEXT 50 | "NIFTYNXT50" |
| NIFTY FIN SERVICE | "FINNIFTY" |
await TD.OptionChain.getOptionChain({
symbol: "NIFTY 50",
expiry: "23-06-2026",
});
// "NIFTY BANK" / "BANK NIFTY" also wrong
await TD.OptionChain.getOptionChain({
symbol: "NIFTY",
expiry: "23-06-2026",
});
Expiry date format is "DD-MM-YYYY"
Always pass expiry in "DD-MM-YYYY" format, e.g. "23-06-2026".
getTopNGainers / getTopNLosers use "NSEEQ" or "BSEEQ"
These Historical functions use different segment strings than Analytics functions. Do not use "EQ" here.
await TD.Historical.getTopNGainers({
segment: "EQ", topn: 5
});
await TD.Historical.getTopNGainers({
segment: "NSEEQ", topn: 5
});
Wrap all async calls in try/catch
Always wrap async calls in try/catch and log errors via TD.log().
TD.onStart = async () => {
try {
const response = await TD.Feed.addSymbols(["RELIANCE"]);
if (!response.success) throw new Error(response.message);
} catch (err) {
TD.log("Error: " + err.message);
}
};
records[0] is always the header row
In Historical, Analytics, and Option Chain responses, records[0] is always the header row. Data rows start at records[1]. Never process records[0] as data.
const records = data.records;
const headers = records[0]; // header row — skip this
for (let i = 1; i < records.length; i++) {
const row = records[i]; // actual data
}
Empowering traders and analysts with high-performance real-time market data directly within their spreadsheets.
Resources
Support
© 2026 TrueData Market Data Services LLP. All rights reserved.