Pine Script: Using [1] on ta.dmi, ta.macd and Other Tuples
Searching for "ta.dmi" "[1]" "tuple" usually means one thing: a Pine Script line like ta.dmi(14, 14)[1] refuses to compile. This short guide gives the rule behind the error, the fix, and the same fix for every built-in that returns several values at once.
Short answer: ta.dmi returns a tuple of three series. The history operator [1] works on a series, not on a function call that returns a tuple. Unpack the tuple into variables first, then use [1] on the variable you need.
The error and the fix
The line that fails:
//@version=5
indicator("ADX previous bar")
adxPrev = ta.dmi(14, 14)[1] // does not compile: [1] on a tuple-returning call
The version that works:
//@version=5
indicator("ADX previous bar")
[diPlus, diMinus, adx] = ta.dmi(14, 14)
adxPrev = adx[1]
plot(adx, "ADX")
plot(adxPrev, "ADX, previous bar")
Two details matter here:
- The order is fixed:
ta.dmi(diLength, adxSmoothing)returns[+DI, -DI, ADX]. If you write[adx, diPlus, diMinus], the script still compiles, because all three are numbers, and your strategy silently trades on the wrong line. - Every element gets a name. If you only need the ADX, still name all three, for example
[_dip, _dim, adx], and ignore the first two.
The same rule for every tuple
Several ta.* built-ins return more than one series. The fix is always the same: destructure, then index.
| Built-in | Returns, in order | Previous value of the last element |
|---|---|---|
ta.dmi(14, 14) |
+DI, -DI, ADX | [p, m, adx] = ta.dmi(14, 14) then adx[1] |
ta.macd(close, 12, 26, 9) |
MACD line, signal line, histogram | [m, s, h] = ta.macd(close, 12, 26, 9) then h[1] |
ta.bb(close, 20, 2) |
middle, upper, lower band | [mid, up, lo] = ta.bb(close, 20, 2) then lo[1] |
ta.kc(close, 20, 1.5) |
middle, upper, lower channel | [mid, up, lo] = ta.kc(close, 20, 1.5) then lo[1] |
ta.supertrend(3, 10) |
SuperTrend line, direction | [st, dir] = ta.supertrend(3, 10) then dir[1] |
Built-ins that return a single series accept [1] directly: ta.rsi(close, 14)[1], ta.ema(close, 20)[1] or ta.stoch(close, high, low, 14)[1] all compile.
SuperTrend: what does direction < 0 mean?
With [st, dir] = ta.supertrend(3, 10), a negative direction means the uptrend (the line sits below price) and a positive direction means the downtrend. That is why the usual plot reads plot(dir < 0 ? st : na, "Up direction"). A direction change is simply dir != dir[1], which again works only on the destructured variable.
request.security with a tuple
request.security accepts an expression that returns a tuple, so this works:
[dPlus, dMinus, adxD] = request.security(syminfo.tickerid, "D", ta.dmi(14, 14))
But that line behaves differently live and in the backtest: on historical bars the daily value only appears once the day is over, while in real time it updates during the day. To use the previous, finished daily bar without repainting, move the [1] inside a function and request it with lookahead_on:
//@version=5
indicator("Daily ADX, previous finished day")
dmiPrev() =>
[p, m, a] = ta.dmi(14, 14)
[p[1], m[1], a[1]]
[dPlusPrev, dMinusPrev, adxPrevD] = request.security(syminfo.tickerid, "D", dmiPrev(), lookahead = barmerge.lookahead_on)
plot(adxPrevD, "Daily ADX, previous day")
The [1] inside the function plus lookahead_on is the standard non-repainting pattern: each daily value is used only once that day is closed.
Two neighbours of the same error
ta.obv(close, volume)does not compile in Pine Script v5:ta.obvis a built-in variable, not a function. Writeta.obv, or its formulata.cum(math.sign(ta.change(close)) * volume)if you need another source.ta.vwapexists both as a variable (ta.vwap, based on hlc3) and as a function (ta.vwap(close)). Called with a standard-deviation multiplier, recent versions return a tuple[vwap, upper, lower], and the destructure-then-index rule applies again.
Also keep history-dependent built-ins such as ta.dmi or ta.ema out of if blocks: Pine Script warns about it, because a function skipped on some bars no longer computes the same series. Compute it on every bar, then use the result inside the condition.
Once it compiles: check the trades, not only the chart
A script that compiles can still trade on the wrong line, on a repainting value, or on a filter computed only on some bars. The Strategy Tester shows the result of the settings you chose; it does not tell you whether the rule holds on data you never looked at.
Strategy Arena Lab is a free Windows and Linux app that replays supported Pine on your PC and compares its trades one by one with TradingView's. Its supported subset includes ADX thresholds and +DI/-DI direction rules from ta.dmi, ta.mfi and ta.obv (details on backtesting Pine Script locally). It then judges the strategy on a period kept sealed during the search. For more ready-made scripts, see the free Pine Script library and 7 free Pine Script strategies.
Frequently asked questions
Why does ta.dmi(14, 14)[1] not compile in Pine Script? ta.dmi returns a tuple of three series (+DI, -DI, ADX). The history operator [1] applies to a series, not to a function call that returns a tuple. Destructure first, then index the variable: [diPlus, diMinus, adx] = ta.dmi(14, 14), then adx[1].
In which order does ta.dmi return its values? ta.dmi(diLength, adxSmoothing) returns [+DI, -DI, ADX], in that order. Swapping the names silently gives a wrong strategy, because all three are numbers.
How do I get the previous daily ADX with request.security without repainting? Wrap the calculation in a function that destructures ta.dmi and returns the [1] values, then call request.security on the daily timeframe with lookahead = barmerge.lookahead_on. The [1] offset makes the daily value final before it is used.
Is ta.obv(close, volume) valid Pine Script v5? No. In Pine Script v5, ta.obv is a built-in variable, not a function: write ta.obv. Its equivalent formula is ta.cum(math.sign(ta.change(close)) * volume).
Educational content on Pine Script syntax. Strategy Arena gives no investment advice, and the Lab places no order.
⚠️ Disclaimer — This article is for informational and educational purposes only. It does not constitute investment advice or a buy/sell recommendation. Past performance does not guarantee future results. Strategy Arena is an educational simulator with virtual capital. Always do your own research before making investment decisions.