True Range (TR)


The True Range (TR) is a volatility measure developed by J. Welles Wilder Jr., designed to provide a more comprehensive measure of daily price movement than the simple high-low range. It accurately accounts for market volatility by considering not only the current period’s high-low range but also any price gaps that may have occurred from the previous period’s close. While rarely used as a standalone indicator, True Range is the essential, foundational component used to calculate the Average True Range (ATR), one of the most widely used volatility indicators.

TR

=TR(data)

Example Usage

=TR(A2:F500)

Parameters

Parameter Type Description Status
data
Range
Range of columns containing the date, Open, high, Low, close, volume data.
Required

Returns

A two-column array of dates and their corresponding TR values.

True Range Formula Result in Google Sheets

Source Code

Copy the following code into your Apps Script editor (Extensions > Apps Script) to use the TR function in your spreadsheet.

tr.js
/**
 * Calculates the True Range (TR), a measure of volatility.
 * TR is the greatest of: current high - current low, absolute(current high - prev close), absolute(current low - prev close).
 *
 * @param {array} data - The input range. Must include at least 5 columns: Date, Open, High, Low, Close.
 * @returns {array} A two-column array with headers "Date" and "TR".
 * @customfunction
 */
function TR(data) {
  // Argument validation
  if (arguments.length !== 1) {
    throw new Error(`Wrong number of arguments. Expected 1, but got ${arguments.length}.`);
  }

  const processedData = getData(data);

  // --- NEW: Function-level validation ---
  const columnCount = processedData[0].length;
  if (columnCount < 5) {
    throw new Error(`Invalid data structure for TR. Expected at least 5 columns (Date, Open, High, Low, Close), but got ${columnCount}.`);
  }
  // --- END of validation ---

  const dates = processedData.slice(1).map(row => row[0]);
  const highs = processedData.slice(1).map(row => row[2]);
  const lows = processedData.slice(1).map(row => row[3]);
  const closes = processedData.slice(1).map(row => row[4]);

  if (highs.length < 2) {
    throw new Error("Insufficient data for TR. At least two data points are required.");
  }

  let trueRanges = [["Date", "TR"]];
  for (let i = 1; i < highs.length; i++) {
    let tr = Math.max(highs[i], closes[i - 1]) - Math.min(lows[i], closes[i - 1]);
    trueRanges.push([dates[i], tr]);
  }

  return trueRanges;
}