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.
Source Code
Copy the following code into your Apps Script editor (Extensions > Apps Script) to use the TR function in your spreadsheet.
/**
* 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;
}