Utility functions
Comprehensive reference for all built-in utility functions available in custom studies.
For a quick overview and examples, see the Custom Studies Guide or Quick Reference.
Moving Averages
sma()
Simple Moving Average
sma(value: number[] | ((index: number) => number), length: number, currentIndex: number): number
Calculates the arithmetic mean of values over a period.
Parameters:
value- Data series as array or accessor functionlength- Number of periods to averagecurrentIndex- Current candle index
Returns: Average value or NaN if insufficient data
Formula: SMA = (sum of last N values) / N
Example:
state.prices[index] = input.close(0);
// Using accessor function
const sma20 = utils.sma(function(i) {
return state.prices[i];
}, 20, index);
// Using array directly
const sma20 = utils.sma(state.prices, 20, index);
ema()
Exponential Moving Average
ema(
value: number[] | ((index: number) => number),
length: number,
currentIndex: number,
stateKey: string
): number
Calculates EMA with more weight on recent values. Requires state storage for previous EMA value.
Parameters:
value- Data series as array or accessor functionlength- Number of periodscurrentIndex- Current candle indexstateKey- Unique key for storing internal state (must be unique per EMA calculation)
Returns: EMA value or NaN if insufficient data
Formula:
alpha = 2 / (period + 1)EMA = value * alpha + previous_EMA * (1 - alpha)
Example:
state.prices[index] = input.close(0);
// Using accessor function
const ema9 = utils.ema(function(i) {
return state.prices[i];
}, 9, index, 'ema_fast');
// Using array directly
const ema21 = utils.ema(state.prices, 21, index, 'ema_slow');
Note: Use unique stateKey values for each EMA to avoid collisions.
wma()
Weighted Moving Average
wma(value: number[] | ((index: number) => number), length: number, currentIndex: number): number
Calculates WMA where more recent values have linearly increasing weights.
Parameters:
value- Data series as array or accessor functionlength- Number of periodscurrentIndex- Current candle index
Returns: WMA value or NaN if insufficient data
Formula: WMA = (n*v1 + (n-1)*v2 + ... + 1*vn) / (n + (n-1) + ... + 1)
Example:
// Using accessor function
const wma10 = utils.wma((i) => state.prices[i], 10, index);
// Using array
const wma10 = utils.wma(state.prices, 10, index);
rma()
Running Moving Average (Wilder's Moving Average)
rma(
value: number[] | ((index: number) => number),
length: number,
currentIndex: number,
stateKey: string
): number
Similar to EMA but with alpha = 1/period. Commonly used in RSI and ATR.
Parameters:
value- Data series as array or accessor functionlength- Number of periodscurrentIndex- Current candle indexstateKey- Unique key for storing internal state
Returns: RMA value or NaN if insufficient data
Formula:
alpha = 1 / periodRMA = value * alpha + previous_RMA * (1 - alpha)
Example:
// Using accessor functions
const avgGain = utils.rma(function(i) {
return state.gainValues[i];
}, 14, index, 'rma_gains');
// Using arrays
const avgLoss = utils.rma(state.lossValues, 14, index, 'rma_losses');
Statistical functions
stdev()
Standard Deviation
stdev(value: number[] | ((index: number) => number), length: number, currentIndex: number): number
Calculates population standard deviation over a period.
Parameters:
value- Data series as array or accessor functionlength- Number of periodscurrentIndex- Current candle index
Returns: Standard deviation or NaN if insufficient data
Formula: σ = sqrt(Σ(xi - mean)² / n)
Example:
// Using arrays
const basis = utils.sma(state.prices, 20, index);
const dev = utils.stdev(state.prices, 20, index);
const upperBand = basis + 2 * dev;
const lowerBand = basis - 2 * dev;
variance()
Variance
variance(value: number[] | ((index: number) => number), length: number, currentIndex: number): number
Calculates population variance over a period.
Parameters:
value- Data series as array or accessor functionlength- Number of periodscurrentIndex- Current candle index
Returns: Variance or NaN if insufficient data
Formula: σ² = Σ(xi - mean)² / n
Example:
// Using array
const var20 = utils.variance(state.prices, 20, index);
// Using accessor function
const var20 = utils.variance((i) => state.prices[i], 20, index);
correlation()
Correlation Coefficient
correlation(
value1: number[] | ((index: number) => number),
value2: number[] | ((index: number) => number),
length: number,
currentIndex: number
): number
Calculates Pearson correlation coefficient between two series.
Parameters:
value1- First data series as array or accessor functionvalue2- Second data series as array or accessor functionlength- Number of periodscurrentIndex- Current candle index
Returns: Correlation (-1 to 1) or NaN if insufficient data
Example:
// Using arrays
const corr = utils.correlation(state.prices, state.volume, 20, index);
// Using accessor functions
const corr = utils.correlation((i) => state.prices[i], (i) => state.volume[i], 20, index);
Price Analysis
highest()
Highest Value
highest(value: number[] | ((index: number) => number), length: number, currentIndex: number): number
Finds the maximum value over a period.
Parameters:
value- Data series as array or accessor functionlength- Number of periods to look backcurrentIndex- Current candle index
Returns: Highest value or NaN if insufficient data
Example:
// Using accessor function with direct input
const highestHigh = utils.highest(i => input.high(index - i), 14, index);
// Using array
const highestPrice = utils.highest(state.prices, 14, index);
lowest()
Lowest Value
lowest(value: number[] | ((index: number) => number), length: number, currentIndex: number): number
Finds the minimum value over a period.
Parameters:
value- Data series as array or accessor functionlength- Number of periods to look backcurrentIndex- Current candle index
Returns: Lowest value or NaN if insufficient data
Example:
// Using accessor function with direct input
const lowestLow = utils.lowest(i => input.low(index - i), 14, index);
// Using array
const lowestPrice = utils.lowest(state.prices, 14, index);
tr()
True Range
tr(currentIndex: number): number
Calculates True Range for volatility measurement.
Parameters:
currentIndex- Current candle index
Returns: Maximum of:
high - lowabs(high - previous_close)abs(low - previous_close)
Example:
const trueRange = utils.tr(index);
atr()
Average True Range
atr(
length: number,
currentIndex: number,
stateKey: string
): number
Calculates Average True Range using RMA smoothing. Automatically calculates True Range internally.
Parameters:
length- Number of periodscurrentIndex- Current candle indexstateKey- Unique key for storing internal state
Returns: ATR value or NaN if insufficient data
Example:
// ATR is calculated automatically from candle data
const atr14 = utils.atr(14, index, 'atr_main');
Utility Helpers
na()
Check Not Available
na(value: any): boolean
Checks if value is null, undefined, or NaN.
Parameters:
value- Value to check
Returns: true if value is N/A, false otherwise
Example:
const sma = utils.sma(function(i) {
return state.prices[i];
}, 20, index);
if (utils.na(sma)) {
return [NaN];
}
nz()
Null to Zero (Replace N/A)
nz(value: any, replacement?: number): number
Replaces N/A values with a default value.
Parameters:
value- Value to checkreplacement- Value to return if N/A (default: 0)
Returns: Original value or replacement
Example:
const safeValue = utils.nz(calculatedValue, 0);
const prevPrice = utils.nz(state.prices[index - 1], input.close(0));
change()
Value Change
change(value: number[] | ((index: number) => number), currentIndex: number, length?: number): number
Calculates difference in value over periods.
Parameters:
value- Data series as array or accessor functioncurrentIndex- Current candle indexlength- Number of periods to look back (default: 1)
Returns: value[index] - value[index - period] or NaN
Example:
// Using array
const priceChange = utils.change(state.prices, index, 1);
const change5 = utils.change(state.prices, index, 5);
// Using accessor function
const priceChange = utils.change((i) => state.prices[i], index, 1);
roc()
Rate of Change
roc(value: number[] | ((index: number) => number), length: number, currentIndex: number): number
Calculates rate of change as a percentage.
Parameters:
value- Data series as array or accessor functionlength- Number of periods to look backcurrentIndex- Current candle index
Returns: ((current - previous) / previous) * 100 or NaN
Example:
// Using array
const roc14 = utils.roc(state.prices, 14, index);
// Using accessor function
const roc14 = utils.roc((i) => state.prices[i], 14, index);
sum()
Sum Values
sum(value: number[] | ((index: number) => number), length: number, currentIndex: number): number
Calculates sum of values over a period.
Parameters:
value- Data series as array or accessor functionlength- Number of periodscurrentIndex- Current candle index
Returns: Sum of values or NaN if insufficient data
Example:
// Using array
const volumeSum = utils.sum(state.volume, 20, index);
// Using accessor function
const volumeSum = utils.sum((i) => state.volume[i], 20, index);
abs()
Absolute Value
abs(value: number | null | undefined): number
Returns absolute value.
Parameters:
value- Input value (returnsNaNif null or undefined)
Returns: |value| or NaN
Example:
const absChange = utils.abs(utils.change((i) => state.prices[i], index, 1));
max()
Maximum Value
max(...values: number[]): number
Returns the largest value from arguments.
Parameters:
values- Variable number of values
Returns: Maximum value
Example:
const maxValue = utils.max(value1, value2, value3);
min()
Minimum Value
min(...values: number[]): number
Returns the smallest value from arguments.
Parameters:
values- Variable number of values
Returns: Minimum value
Example:
const minValue = utils.min(value1, value2, value3);
Best Practices
Using State Keys
Functions that require stateKey (ema, rma, atr) store internal state. Always use unique keys:
// Good - unique keys
const ema9 = utils.ema(function(i) {
return state.prices[i];
}, 9, index, 'ema_fast');
const ema21 = utils.ema(function(i) {
return state.prices[i];
}, 21, index, 'ema_slow');
// Bad - collision!
const ema1 = utils.ema(function(i) {
return state.prices[i];
}, 9, index, 'ema');
const ema2 = utils.ema(function(i) {
return state.prices[i];
}, 21, index, 'ema'); // Overwrites previous
Array vs Accessor Functions
Most utility functions accept data as either an array or an accessor function:
// Using array directly
const sma = utils.sma(state.prices, 20, index);
// Using accessor function (same result)
const sma = utils.sma(function(i) {
return state.prices[i];
}, 20, index);
// Using accessor function for dynamic/computed values
const highest = utils.highest(i => input.high(index - i), 14, index);
Error handling
Always check for N/A values before using results:
const sma = utils.sma(function(i) {
return state.prices[i];
}, 20, index);
if (utils.na(sma)) {
return [NaN]; // Not enough data yet
}
const result = sma * 2;
return [result];
Combining functions
Utility functions can be chained and combined:
// EMA of EMA (DEMA component)
state.ema1Values[index] = utils.ema(function(i) {
return state.prices[i];
}, 9, index, 'ema1');
state.ema2Values[index] = utils.ema(function(i) {
const val = state.ema1Values[i];
return val !== undefined ? val : NaN;
}, 9, index, 'ema2');
// Bollinger Bands
const basis = utils.sma(function(i) {
return state.prices[i];
}, 20, index);
const dev = utils.stdev(function(i) {
return state.prices[i];
}, 20, index);
const upper = basis + 2 * dev;
const lower = basis - 2 * dev;
Performance considerations
- Initialize arrays in
init(): Pre-allocate state arrays to avoid resizing - Use built-in functions: They're optimized for performance
- Avoid redundant calculations: Store intermediate results
- Early returns: Exit early when data is insufficient
constructor: {
init: (ctx) => {
// Pre-allocate arrays
ctx.state.prices = [];
ctx.state.ema = [];
},
main: (ctx) => {
const { input, utils, parameters, state, index } = ctx;
// Early return
if (index < parameters.length - 1) {
return [NaN];
}
// Store once, use multiple times
const price = input.close(0);
state.prices[index] = price;
// Calculate
const result = utils.ema(function(i) {
return state.prices[i];
}, parameters.length, index, 'ema');
return [result];
}
}