Technical Analysis (ta)
All technical analysis functions live in the ta namespace. Functions that accept a source parameter work with any Series (close, open, high, low, volume, or a computed Series). Functions without a source parameter use OHLCV internally.
Moving Averages
| Function | Description |
|---|---|
ta.sma(source, period) | Simple Moving Average |
ta.ema(source, period) | Exponential Moving Average |
ta.wma(source, period) | Weighted Moving Average |
ta.dema(source, period) | Double Exponential Moving Average |
ta.tema(source, period) | Triple Exponential Moving Average |
ta.hma(source, period) | Hull Moving Average |
ta.vwma(source, period) | Volume Weighted Moving Average |
All return Series. Parameters:
- source
Series— input data (e.g.close,high,ta.sma(close, 10)) - period
number— lookback length
const sma20 = ta.sma(close, 20)
const emaHigh = ta.ema(high, 10)
const hull = ta.hma(close, 9)Oscillators
| Function | Description |
|---|---|
ta.rsi(source, period) | Relative Strength Index (0–100) |
ta.roc(source, period) | Rate of Change (%) |
ta.momentum(source, period) | Momentum (price difference) |
ta.cci(period) | Commodity Channel Index |
ta.mfi(period) | Money Flow Index (0–100) |
rsi, roc, and momentum accept a custom source. cci and mfi use OHLCV internally.
const rsi = ta.rsi(close, 14)
const cci = ta.cci(20)Multi-Output Functions
These return an object with multiple named Series:
ta.bollinger(source, period, mult)
Returns { middle: Series, upper: Series, lower: Series }
const bb = ta.bollinger(close, 20, 2)
plot(bb.middle, 'Middle', '#2962ff')
plot(bb.upper, 'Upper', '#f44336')
plot(bb.lower, 'Lower', '#4caf50')
fill(bb.upper, bb.lower, 'rgba(33,150,243,0.1)')ta.macd(source, fastPeriod, slowPeriod, signalPeriod)
Returns { macd: Series, signal: Series, histogram: Series }
const m = ta.macd(close, 12, 26, 9)
plot(m.macd, 'MACD', '#2962ff')
plot(m.signal, 'Signal', '#ff6d00')ta.stochastic(kPeriod, dPeriod, smooth)
Returns { k: Series, d: Series }
Uses OHLCV data internally (no source parameter).
const stoch = ta.stochastic(14, 3, 3)
plot(stoch.k, '%K', '#2962ff')
plot(stoch.d, '%D', '#ff6d00')ta.adx(diLength, adxSmoothing)
Returns { adx: Series, plusDI: Series, minusDI: Series }
const { adx, plusDI, minusDI } = ta.adx(14, 14)
plot(adx, 'ADX', '#7E57C2')
plot(plusDI, '+DI', '#26A69A')
plot(minusDI, '-DI', '#EF5350')Volume Indicators
| Function | Description |
|---|---|
ta.obv() | On-Balance Volume |
ta.cmf(period) | Chaikin Money Flow |
These use OHLCV internally — no source parameter.
const obv = ta.obv()
plot(obv, 'OBV', '#2962ff')Volatility
| Function | Description |
|---|---|
ta.atr(period) | Average True Range |
Uses OHLCV internally.
const atr = ta.atr(14)Pivot Detection
| Function | Returns | Description |
|---|---|---|
ta.pivotHigh(source, leftBars, rightBars) | Series | Pivot high price at detection bar, NaN elsewhere |
ta.pivotLow(source, leftBars, rightBars) | Series | Pivot low price at detection bar, NaN elsewhere |
Detects swing highs/lows using left and right bar confirmation. Handles forward-filled multi-timeframe data by de-duplicating runs of equal values before detection.
- source
Series— input data (e.g.high,low, or MTF series) - leftBars
number— bars to the left that must be lower (high) or higher (low) - rightBars
number— bars to the right that must be lower (high) or higher (low)
The pivot price is placed at the bar where rightBars confirmation completes (i.e. with a delay of rightBars).
// Detect 5m swing highs/lows on a 15s chart
const tf5 = request.timeframe('5m')
const pivHigh = ta.pivotHigh(tf5.high, 5, 5)
const pivLow = ta.pivotLow(tf5.low, 5, 5)
plot(pivHigh, 'Pivot High', '#EF5350')
plot(pivLow, 'Pivot Low', '#26A69A')
// RSI pivots for divergence detection
const rsi = ta.rsi(close, 14)
const rsiPivH = ta.pivotHigh(rsi, 3, 3)
const rsiPivL = ta.pivotLow(rsi, 3, 3)Utilities
| Function | Returns | Description |
|---|---|---|
ta.crossover(a, b) | boolean | True when a crosses above b on the current bar |
ta.crossunder(a, b) | boolean | True when a crosses below b on the current bar |
ta.highest(source, period) | Series | Highest value over the last period bars |
ta.lowest(source, period) | Series | Lowest value over the last period bars |
ta.change(source, length?) | Series | Change in value over length bars (default: 1) |
const fast = ta.ema(close, 9)
const slow = ta.ema(close, 21)
if (ta.crossover(fast, slow)) strategy.entry('Long', 'long')
if (ta.crossunder(fast, slow)) strategy.close('Long')
const highestHigh = ta.highest(high, 20)
const momentum = ta.change(close, 5)