Skip to content

DSL Technical Analysis API

The ta.* namespace contains common technical analysis helpers.

Moving Averages

ta.sma

ma = ta.sma(close, length)

Simple moving average.

ta.ema

ema = ta.ema(close, length)

Exponential moving average.

ta.rma

rma = ta.rma(close, length)

Wilder moving average.

Rolling Window

ta.sum

sum = ta.sum(volume, length)

Rolling sum.

ta.highest

highestHigh = ta.highest(high, length)

Highest value in a rolling window.

ta.lowest

lowestLow = ta.lowest(low, length)

Lowest value in a rolling window.

ta.stdev

dev = ta.stdev(close, length)

Rolling standard deviation.

Bollinger Bands

ta.bb_basis

basis = ta.bb_basis(close, length)

Bollinger basis.

ta.bb_upper

upper = ta.bb_upper(close, length, mult)

Bollinger upper band.

ta.bb_lower

lower = ta.bb_lower(close, length, mult)

Bollinger lower band.

Signals

ta.crossover

if ta.crossover(fast, slow) {
  signal = 1
}

Available in both indicators and robots. Returns true when the current first-series value is greater than the second-series value, and the previous first-series value was less than or equal to the previous second-series value.

ta.crossunder

if ta.crossunder(fast, slow) {
  signal = -1
}

Available in both indicators and robots. Returns true when the current first-series value is less than the second-series value, and the previous first-series value was greater than or equal to the previous second-series value.

Signal Arguments and Warmup

Both signal functions require exactly two positional named series, such as fast, slow, or close. Inputs, scalar constants, history offsets (fast[1]), inline expressions, and named arguments are not accepted. Calculate an intermediate series first when needed.

If any of the four current/previous values is missing, null, or non-finite, the result is false. This prevents signals during moving-average warmup. Signals on a forming candle may change before it closes; plotText excludes that candle by default.

For a complete indicator, see MA crossover labels.

Periods, warmup and independent state

Periods are finite safe integers from 1 to 10,000. Each static ta.* call site has independent state, even when two calls have the same period but different sources. State resets on every history evaluation.

SMA, sum, highest, lowest, standard deviation and Bollinger functions need a complete finite window; otherwise they return null. Standard deviation uses the population divisor (window length). EMA and RMA start from the first finite input, rather than an initial SMA. Missing input returns null and retains their previous smoothing state. This seed convention can produce different warmup values from Pine Script.

True range and ATR

  • ta.tr() = maximum of high-low, abs(high-previousClose), abs(low-previousClose); the first candle uses high-low.
  • ta.atr(length) applies RMA to true range, seeded from the first finite true range.
script("ATR envelope", kind="indicator")
input length = 14
input factor = 2
range = ta.atr(length)
upper = close + range * factor
lower = close - range * factor
plot(upper)
plot(lower)

Confirmed pivots

ta.pivothigh(source, left, right) and ta.pivotlow(source, left, right) return the price of a pivot only on the candle that confirms it, right bars after the pivot candle. Before confirmation, or with incomplete/non-finite data, they return null. left and right must be integers from 1 to 100. Equal extrema choose the rightmost occurrence.

script("Confirmed swing highs", kind="indicator")
input strength = 3
pivot = ta.pivothigh(high, strength, strength)
if isClosed and not na(pivot) {
  draw.label("high" + barIndex, barIndex - strength, pivot, "HH")
}

The label is anchored to the earlier candle but becomes known only at confirmation. On the forming confirmation candle a pivot may disappear; guard with isClosed for confirmed output.

Extreme offsets

ta.highestbars(source, length) and ta.lowestbars(source, length) return a nonnegative lookback offset, with 0 meaning the current candle. Ties select the rightmost extreme. A full finite window is required; otherwise the result is null. This sign convention must not be assumed to match Pine Script.

Classification features and kernels

Function Semantics
ta.rsi(source, length) RSI 0–100; Wilder gain/loss averages seeded by an initial SMA; loss=0 returns 100
ta.cci(source, length) CCI with mean absolute deviation; a flat window returns zero
ta.wt(source, channel, average) Raw WaveTrend difference WT1 - SMA(WT1,4); internal EMAs are SMA-seeded
ta.adx(length) ADX 0–100 from OHLC, Wilder sums and SMA-seeded RMA of DX
ta.normalize(value) Causal running min/max normalization to 0–1; a constant range returns zero
ta.kernelGaussian(source, bandwidth, window) Gaussian weighted past-only Nadaraya–Watson estimate
ta.kernelRQ(source, bandwidth, relativeWeight, window) Rational quadratic past-only Nadaraya–Watson estimate

All arguments are positional. Periods/window are integers 1..500. Bandwidth is (0,500], relativeWeight (0,100]. Each call site has isolated state. Changing RSI/CCI/WT/ADX periods restarts their warmup. Missing/incomplete feature input yields null. Running normalization never examines future values; its state resets on replay.

Kernels use the available past at startup, up to window samples including the current candle. Gaussian weights are exp(-offset²/(2*bandwidth²)); RQ weights are (1+offset²/(2*bandwidth²*relativeWeight))^(-relativeWeight). A missing value in the active kernel window returns null.

These feature seed conventions do not change legacy ta.ema/ta.rma. ADX uses previous OHLC=0 on the first candle, matching the public reference convention without tick quantization. Flat-window CCI and WT differences are zero; flat RSI is 100 when averaged losses are zero.

Component vectors are checked against the public AI Edge Python reference, commit 75569fa; this does not establish full Pine signal parity. See ML classifier.

Money flow and volume-weighted price

ta.mfi(length) returns MFI in 0–100. Typical price is (high+low+close)/3; abs(typical price*volume) is classified by comparison with the previous typical price. The first loaded bar contributes neutral flow. Positive/(positive+negative) flow is scaled by 100. A flat valid window returns 50.

ta.vwma(source, length) returns the volume-weighted mean of source. Zero-volume bars in a nonzero window contribute zero weight.

Both functions take positional arguments with integer length 1–500. They require a complete valid window. Missing/negative volume invalidates the window; zero-total-volume windows return null. They never substitute price for missing volume. Numeric overflow returns null. Changing length restarts warmup.

script("Money flow", kind="indicator")
value = ta.mfi(14)
pane(title="MFI", min=0, max=100)
plot(value)