TrueData TrueData Sheets
search
Searching...
functions Formulas
menu_book Pages
manage_search Content Match
search_off

No results for ""

Loading Content
code

Ready-to-Use Scripts

Copy any script below directly into the editor and click Start. Each follows all the rules on the Strict Rules page: top-level TD.on(), awaited Feed/Sheet calls, try/catch everywhere, response.success checks, and — for REST-backed templates — a single one-shot call with no loop or timer.

help How to pick a template: match the request to the "Use when" column below, then copy the template and only change the constants at the top (SYMBOL, SYMBOLS, EXPIRY, top, etc.) — the structure shouldn't otherwise need to change.
# Template Use when... API family
1 Full multi-symbol watchlist Live watchlist with full touchline fields for several symbols TD.Feed + tick
2 Option chain → sheet Dump the full option chain to the sheet once getOptionChain
3 1-min bar streaming (append) Every new 1-min candle appended as a new row TD.Feed + bar1min
4 Last N historical bars One-time pull of recent past bars getLastNBars
5 Top N OI gainers Top open-interest gainers for CE or PE getOIGainers
6 Most active by volume Most actively traded symbols in an index getMostActiveByVolume
7 Industry gainers Top gainers within one sector/industry getIndustryGainers
8 Index gainers (top N) Top N gainers within an index getIndexGainers
9 Option chain with Greeks → sheet Greeks-enriched chain dumped to the sheet once getOptionChainWithGreeks
10 Tick-by-tick log (append) Every individual tick logged as a new row TD.Feed + tick

1. Full Multi-Symbol Watchlist (tick)

Live-updating watchlist with the complete touchline field set — LTP, OHLC, OI, change %, bid/ask — for multiple symbols, one fixed row per symbol.

const SYMBOLS = ["RELIANCE", "TCS", "NIFTY 50"];

let symbolMap = {}; // { symbolId: symbolName }
let rowMap = {
  "RELIANCE": 2,
  "TCS": 3,
  "NIFTY 50": 4,
};

TD.on("tick", async (data) => {
  try {
    const symbolName = symbolMap[data[0]];
    if (!symbolName) return;

    const row = rowMap[symbolName];
    if (!row) return;

    const ltp = parseFloat(data[2]);
    const prevClose = parseFloat(data[9]);
    const oi = parseFloat(data[10]);
    const prevOi = parseFloat(data[11]);

    const change = ltp - prevClose;
    const changePer = prevClose ? (change / prevClose) * 100 : 0;
    const oiChange = oi - prevOi;
    const oiChangePer = prevOi ? (oiChange / prevOi) * 100 : 0;

    await TD.Sheet.setCellRange("A" + row, [
      symbolName, data[1], ltp,
      parseFloat(data[3]), parseFloat(data[4]), parseFloat(data[5]),
      parseFloat(data[6]), parseFloat(data[7]), parseFloat(data[8]),
      prevClose, change, changePer, oi, prevOi, oiChange, oiChangePer,
      parseFloat(data[12]), data[14],
      parseFloat(data[15]), parseFloat(data[16]),
      parseFloat(data[17]), parseFloat(data[18]),
    ]);
  } catch (err) {
    TD.log("Tick error: " + err.message);
  }
});

TD.onStart = async () => {
  try {
    symbolMap = {};

    await TD.Sheet.setCellRange("A1", [
      "Symbol", "LTT", "LTP", "LTQ", "ATP", "Total Volume", "Open", "High",
      "Low", "Prev Close", "Change", "Change %", "Today OI", "Prev OI",
      "OI Change", "OI Change %", "Turnover", "Tick Seq No",
      "Bid", "Bid Qty", "Ask", "Ask Qty",
    ]);

    const response = await TD.Feed.addSymbols(SYMBOLS);
    if (!response.success) {
      TD.log("Subscribe failed: " + response.message);
      return;
    }

    for (const sym of response.symbollist) {
      symbolMap[sym[1]] = sym[0];
    }

    TD.log("Full watchlist started.");
  } catch (err) {
    TD.log("Start error: " + err.message);
  }
};

TD.onStop = async () => {
  await TD.Feed.removeSymbols(SYMBOLS);
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};

2. Option Chain → Sheet

One-shot dump of the full option chain (header + all strikes) to the sheet. Index display names must be mapped first (Rule 12).

const SYMBOL = "NIFTY"; // already mapped — NOT "NIFTY 50"
const EXPIRY = "07-07-2026"; // DD-MM-YYYY

TD.onStart = async () => {
  try {
    const data = await TD.OptionChain.getOptionChain({
      symbol: SYMBOL,
      expiry: EXPIRY,
    });

    if (!data.records || data.records.length <= 1) {
      TD.log("No option chain data found.");
      return;
    }

    // records[0] is the header row — write everything, header included
    for (let i = 0; i < data.records.length; i++) {
      await TD.Sheet.setCellRange("A" + (i + 1), data.records[i]);
    }

    TD.log("Option chain loaded.");
  } catch (err) {
    TD.log("Error: " + err.message);
  }
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};

3. 1-Min Bar Streaming (Append Rows)

Every new 1-minute bar is appended as a new row — builds a running candle history instead of overwriting one row.

const SYMBOLS = ["RELIANCE"];
let symbolMap = {};
let currentRow = 2;

TD.on("bar1min", async (data) => {
  try {
    const symbolId = data[0];
    const symbolName = symbolMap[symbolId] || symbolId;

    await TD.Sheet.setCellRange("A" + currentRow, [
      symbolName, data[1],
      parseFloat(data[2]), parseFloat(data[3]), parseFloat(data[4]),
      parseFloat(data[5]), parseFloat(data[6]), parseFloat(data[7]),
    ]);

    currentRow++;
  } catch (err) {
    TD.log("Bar write error: " + err.message);
  }
});

TD.onStart = async () => {
  try {
    currentRow = 2;
    symbolMap = {};

    await TD.Sheet.setCellRange("A1", [
      "Symbol", "Timestamp", "Open", "High", "Low", "Close", "Volume", "OI",
    ]);

    const response = await TD.Feed.addSymbols(SYMBOLS);
    if (!response.success) throw new Error(response.message);

    for (const sym of response.symbollist) {
      symbolMap[sym[1]] = sym[0];
    }

    TD.log("RELIANCE 1-min bar streaming started.");
  } catch (err) {
    TD.log("Start error: " + err.message);
  }
};

TD.onStop = async () => {
  await TD.Feed.removeSymbols(SYMBOLS);
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};
warning This grows the sheet by one row per bar with no upper bound. Only use append-style templates when a running log is explicitly wanted.

4. Last N Historical Bars

One-time pull of the most recent N bars for a symbol — no live updates, single REST call inside onStart.

TD.onStart = async () => {
  try {
    const data = await TD.Historical.getLastNBars({
      symbol: "RELIANCE",
      nbars: 20,
      interval: "1min",
    });

    if (!data.records || data.records.length <= 1) {
      TD.log("No bars received.");
      return;
    }

    await TD.Sheet.setCellRange("A1", data.records[0]);

    for (let i = 1; i < data.records.length; i++) {
      await TD.Sheet.setCellRange("A" + (i + 1), data.records[i]);
    }

    TD.log("Loaded last 20 one-minute bars for RELIANCE.");
  } catch (err) {
    TD.log("Error: " + err.message);
  }
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};

5. Top N OI Gainers

One-time pull of top open-interest gainers for a given option series ("CE" or "PE"). No segment parameter on this call.

TD.onStart = async () => {
  try {
    const data = await TD.Analytics.getOIGainers({
      series: "CE",
      top: 5,
    });

    if (!data.records || data.records.length <= 1) {
      TD.log("No OI gainers data received.");
      return;
    }

    await TD.Sheet.setCellRange("A1", data.records[0]);

    for (let i = 1; i < data.records.length; i++) {
      await TD.Sheet.setCellRange("A" + (i + 1), data.records[i]);
    }

    TD.log("Top 5 CE OI gainers loaded.");
  } catch (err) {
    TD.log("Error: " + err.message);
  }
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};

6. Most Active by Volume

One-time pull of the most actively traded symbols (by volume) within an index.

TD.onStart = async () => {
  try {
    const data = await TD.Analytics.getMostActiveByVolume({
      indexName: "NIFTY 50",
      segment: "EQ",
      top: 5,
    });

    if (!data.records || data.records.length <= 1) {
      TD.log("No data received.");
      return;
    }

    await TD.Sheet.setCellRange("A1", data.records[0]);

    for (let i = 1; i < data.records.length; i++) {
      await TD.Sheet.setCellRange("A" + (i + 1), data.records[i]);
    }

    TD.log("Top 5 most active by volume loaded.");
  } catch (err) {
    TD.log("Error: " + err.message);
  }
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};

7. Industry Gainers

One-time pull of top gainers within a specific industry. Swap industry for any value from the supported industries list on the Analytics page.

TD.onStart = async () => {
  try {
    const data = await TD.Analytics.getIndustryGainers({
      industry: "Telecommunication",
      segment: "EQ",
      top: 5,
    });

    if (!data.records || data.records.length <= 1) {
      TD.log("No Telecommunication industry gainers data received.");
      return;
    }

    await TD.Sheet.setCellRange("A1", data.records[0]);

    for (let i = 1; i < data.records.length; i++) {
      await TD.Sheet.setCellRange("A" + (i + 1), data.records[i]);
    }

    TD.log("Top 5 Telecommunication industry gainers loaded.");
  } catch (err) {
    TD.log("Error: " + err.message);
  }
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};

8. Index Gainers (Top N)

One-time pull of top N gainers within an index. top controls how many rows come back — keep the log message in sync with the actual value.

TD.onStart = async () => {
  try {
    const TOP_N = 25;

    const data = await TD.Analytics.getIndexGainers({
      indexName: "NIFTY 50",
      segment: "EQ",
      top: TOP_N,
    });

    if (!data.records || data.records.length <= 1) {
      TD.log("No NIFTY 50 gainers data received.");
      return;
    }

    await TD.Sheet.setCellRange("A1", data.records[0]);

    for (let i = 1; i < data.records.length; i++) {
      await TD.Sheet.setCellRange("A" + (i + 1), data.records[i]);
    }

    TD.log(`Top ${TOP_N} NIFTY 50 index gainers loaded.`);
  } catch (err) {
    TD.log("Error: " + err.message);
  }
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};

9. Option Chain with Greeks → Sheet

One-shot dump of the Greeks-enriched option chain to the sheet. Same index-mapping rule applies as template 2.

const SYMBOL = "NIFTY"; // already mapped — NOT "NIFTY 50"
const EXPIRY = "07-07-2026"; // DD-MM-YYYY

TD.onStart = async () => {
  try {
    const data = await TD.OptionChain.getOptionChainWithGreeks({
      symbol: SYMBOL,
      expiry: EXPIRY,
    });

    if (!data.records || data.records.length <= 1) {
      TD.log("No option chain data found.");
      return;
    }

    await TD.Sheet.setCellRange("A1", data.records[0]);

    for (let i = 1; i < data.records.length; i++) {
      await TD.Sheet.setCellRange("A" + (i + 1), data.records[i]);
    }

    TD.log("Option chain with Greeks loaded.");
  } catch (err) {
    TD.log("Error: " + err.message);
  }
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};

10. Tick-by-Tick Log (Append Rows)

Every incoming tick is appended as a new row — an audit-style log instead of a single overwritten row. Contrast with Template 1, which keeps one fixed row per symbol.

const SYMBOLS = ["RELIANCE"];

let symbolMap = {};
let currentRow = 2;

TD.on("tick", async (data) => {
  try {
    const symbolName = symbolMap[data[0]] || data[0];

    await TD.Sheet.setCellRange("A" + currentRow, [
      symbolName, data[1],
      parseFloat(data[2]), parseInt(data[3]),
      parseFloat(data[15]), parseInt(data[16]),
      parseFloat(data[17]), parseInt(data[18]),
    ]);

    currentRow++;
  } catch (err) {
    TD.log("Tick write error: " + err.message);
  }
});

TD.onStart = async () => {
  try {
    currentRow = 2;
    symbolMap = {};

    await TD.Sheet.setCellRange("A1", [
      "Symbol", "Time", "LTP", "LTQ", "Bid", "Bid Qty", "Ask", "Ask Qty",
    ]);

    const response = await TD.Feed.addSymbols(SYMBOLS);
    if (!response.success) {
      TD.log("Subscribe failed: " + response.message);
      return;
    }

    for (const sym of response.symbollist) {
      symbolMap[sym[1]] = sym[0];
    }

    TD.log("RELIANCE tick streaming started.");
  } catch (err) {
    TD.log("Start error: " + err.message);
  }
};

TD.onStop = async () => {
  await TD.Feed.removeSymbols(SYMBOLS);
};

TD.onError = (err) => {
  TD.log("Error: " + err.message);
};
warning Grows the sheet by one row per tick — can add hundreds of rows per minute on high-frequency symbols. Only use when an audit trail is explicitly wanted.
Truedata Icon Sheets by Truedata

Empowering traders and analysts with high-performance real-time market data directly within their spreadsheets.

© 2026 TrueData Market Data Services LLP. All rights reserved.