Directional Movement Index (dmi)

[[dmi]] is a trend indicator that compares the bullish and bearish components of price movement. It is built around two lines: +DI and −DI. The first measures the strength of recent upward directional movement, while the second measures the strength of recent downward directional movement.

Reading the DMI mainly means observing the relationship between these two lines. When +DI is above −DI, recent momentum is dominated by buyers. When −DI moves above +DI, momentum becomes dominated by sellers. The clearer the gap between the two lines, the more pronounced that directional dominance is.

The DMI block can also expose ADX as a complement. ADX is calculated from +DI and −DI, but it answers a different question: not which direction the market is moving in, but how strong that move is. This means you can use DMI to work with direction through +DI and −DI, and, when needed, qualify that direction with ADX.

Block declaration

A strategy can contain multiple [[dmi]] blocks. Each block can expose:

  • +DI only,
  • –DI only,
  • both +DI and –DI,
  • or +DI, –DI, and ADX together.

At least one output must be declared. If you expose ADX, you must also expose both +DI and –DI.

Examples

Minimal setup

This DMI block exposes only the +DI and –DI lines. ADX is not computed or stored. If you do not specify di_length, the block defaults to a 14‑period window.

[[dmi]]
plus_id  = "di_plus"
minus_id = "di_minus"

Full DMI (+DI, –DI, ADX)

This block exposes the three series: +DI, –DI, and ADX.
The di_length parameter controls the smoothing of the DI lines. The adx_length parameter controls the smoothing of the ADX line and is accepted only when adx_id is set.

[[dmi]]
plus_id  = "di_plus"
minus_id = "di_minus"
adx_id   = "adx"

Custom fixed lengths

This block uses custom di_length and adx_length values.

[[dmi]]
plus_id    = "di_plus"
minus_id   = "di_minus"
adx_id     = "adx"
di_length  = 12
adx_length = 18

Search for the optimal DI and ADX lengths

This block explores ranges of values for di_length and adx_length to identify the best-performing combination.

[[dmi]]
plus_id          = "di_plus"
minus_id         = "di_minus"
adx_id           = "adx"
di_length.start  = 7
di_length.stop   = 21
adx_length.start = 7
adx_length.stop  = 21

Confirmed bullish dominance filter

This example uses DMI to filter the phases where +DI dominates −DI and ADX stays above a minimum threshold. The [[dmi]] block exposes di_plus, di_minus, and adx. The [[constant]] block lets you optimise the adx_threshold value depending on the symbol, timeframe, and strategy.

A lower threshold makes the filter more permissive. A higher threshold makes it stricter and keeps only the clearest trends.

[[constant]]
id    = "adx_threshold"
start = 15
stop  = 30

[[dmi]]
plus_id    = "di_plus"
minus_id   = "di_minus"
adx_id     = "adx"
di_length  = 14
adx_length = 14

[[condition]]
id            = "long_trend_filter"
condition     = "di_plus > di_minus and adx > adx_threshold"
next_block_id = "..."

Bullish +DI / −DI crossover

This block uses DMI to detect the transition from bearish dominance to bullish dominance. The [[dmi]] block computes +DI and −DI without exposing ADX and varies the di_length window between 7 and 21 periods to search for the best balance between signal reactivity and crossover robustness. In this configuration, adx_length is not accepted and no <id>.adx_length variables are exposed. The condition tests a crossover: on the current bar, +DI is above −DI, while on the previous bar it was below or equal.

[[dmi]]
plus_id         = "di_plus"
minus_id        = "di_minus"
di_length.start = 7
di_length.stop  = 21

[[condition]]
id            = "bullish_dmi_cross"
condition     = "di_plus > di_minus and di_plus[1] <= di_minus[1]"
next_block_id = "..."

ADX weakening alert

In this example, DMI is configured to expose +DI, −DI, and ADX, but the condition only uses adx. The trend weakening threshold is not fixed: it is scanned between 15 and 30 to find a zone where exits occur neither too early nor too late.

[[dmi]]
plus_id    = "di_plus"
minus_id   = "di_minus"
adx_id     = "adx"
di_length  = 14
adx_length = 14

[[constant]]
id    = "adx_cutoff"
start = 15
stop  = 30

[[condition]]
id            = "trend_weakening"
condition     = "adx[1] > adx_cutoff and adx < adx_cutoff"
next_block_id = "..."

Parameters

ParameterDescription
plus_id
 String
 Optional
Identifier for the +DI series. If set, the block exposes a numeric series named by plus_id representing the positive directional indicator.
minus_id
 String
 Optional
Identifier for the –DI series. If set, the block exposes a numeric series named by minus_id representing the negative directional indicator.
adx_id
 String
 Optional
Identifier for the ADX series. If set, the block exposes a numeric series named by adx_id representing overall trend strength.

Constraint: adx_id requires both plus_id and minus_id to be present.
di_length
 Integer
 Optional
Window used to smooth +DM, –DM, and True Range before they are normalised into +DI/–DI; must be ≥ 1 when specified.
If di_length is omitted, the default value is used.

Usage:
• Fixed: di_length = value
• Grid search:
 – di_length.start = min_value
 – di_length.stop = max_value
 – di_length.step = value (optional, default 1)
adx_length
 Integer
 Optional
(required when adx_id is set)
Window used to smooth the DX series (difference between +DI and –DI) into ADX; must be ≥ 1 when ADX is exposed.

Constraint: adx_length is accepted only when adx_id is set.

Usage:
• Fixed: adx_length = value
• Grid search:
 – adx_length.start = min_value
 – adx_length.stop = max_value
 – adx_length.step = value (optional, default 1)
symbol
 String
 or Array
 Optional
Market symbol from which the DMI block reads its candles (high, low, and close prices). For symbol format and alignment rules, see Exchanges, Symbols and Timeframes.
timeframe
 String
 or Array
 Optional
Timeframe on which this indicator is computed.
If timeframe is omitted, the computation uses the grid’s main timeframe defined in [backtest].
For accepted formats and alignment rules, see Exchanges, Symbols and Timeframes.

Available variables

Use the identifiers below directly in your expressions.
The DMI block exposes up to three numeric series (+DI, –DI, ADX), the applicable smoothing lengths, and the usual metadata about sources, symbol, and timeframe.

Assume the block is configured as:

[[dmi]]
plus_id  = "di_plus"
minus_id = "di_minus"
adx_id   = "adx"

Then:

VariableDescription
di_plus or di_plus[0]
Decimal
Current +DI value (percentage of upward directional movement).
di_plus[n]
Decimal
+DI value from n candles ago.
di_minus or di_minus[0]
Decimal
Current –DI value (percentage of downward directional movement).
di_minus[n]
Decimal
–DI value from n candles ago.
adx or adx[0]
Decimal
Current ADX value (trend strength).
adx[n]
Decimal
ADX value from n candles ago.
<id>.di_length
Decimal
DI smoothing window used for the <id> series.
<id>.adx_length
Decimal
ADX smoothing window used for the <id> series. Available only when adx_id is set.
<id>.high_source
<id>.low_source
<id>.close_source
String
Names of the input sources used by that series (high, low, close). Available on each exposed series: di_plus, di_minus, and adx.
<id>.symbol
String
Symbol used by the block for that series.
<id>.timeframe
String
Timeframe used by the block for that series.