# Multi-Time Frame DMI

> Identify momentum waves across multiple timeframes. Spot calm before the storm opportunities with MTF DMI for ThinkOrSwim.

Page: https://tosindicators.com/indicators/mtf-dmi  
Video: https://www.youtube.com/watch?v=WAnEOHsVQPc  
Section: Indicators  
Skill: Advanced  
Access: free  
Updated: 2026-02-12

## Understanding the MTF DMI Indicator


The MTF DMI (Directional Movement Index) Indicator enhances your ability to analyze trends across multiple time frames, offering you insights into bullish, bearish, and neutral zones.

Using this tutorial, you’ll learn how to build a Multiple Time Frame indicator (17 different time frames, to be exact!) for ThinkOrSwim. This expands upon the original DMI Indicator (shout-out Hubert Senters and Pete Hahn), and allows for it to work  with multiple time frames in ThinkOrSwim (TOS).

The original [Directional Movement Index (DMI) Indicator](https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/C-D/DMI) is popular among momentum and breakout traders. It tracks the strength and direction of trends, helping you determine the prevailing market bias. With the MTF approach, you can see how trends align across time frames from one minute to a month, providing a comprehensive trend analysis tool.

By the end, you’ll have a versatile tool that adapts across different time periods, helping you optimize your trading strategy.

## Understanding the MTF DMI Indicator


The MTF DMI (Directional Movement Index) Indicator enhances your ability to analyze trends across multiple time frames, offering you insights into bullish, bearish, and neutral zones. Using this tutorial, you'll learn how to build a Multiple Time Frame indicator (17 different time frames, to be exact!) for ThinkOrSwim. This expands upon the original DMI Indicator (shout-out Hubert Senters and Pete Hahn), and allows for it to work with multiple time frames in ThinkOrSwim (TOS).


The original [Directional Movement Index (DMI) Indicator](https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/C-D/DMI) is popular among momentum and breakout traders. It tracks the strength and direction of trends, helping you determine the prevailing market bias. With the MTF approach, you can see how trends align across time frames from one minute to a month, providing a comprehensive trend analysis tool.


By the end, you'll have a versatile tool that adapts across different time periods, helping you optimize your trading strategy.



## Why Multi-Timeframe DMI Analysis Matters


The Directional Movement Index excels at identifying momentum and breakout opportunities, making it the go-to tool for traders who prefer strong directional moves over overbought/oversold reversals. Unlike indicators that work well in range-bound markets, DMI thrives in trending environments and helps you catch explosive moves early in their development.


Dick K, one of the Volatility Box members who inspired this tutorial, recognized that while the Dynamic RSI works beautifully for patient traders seeking overbought/oversold confirmations, momentum and breakout traders need something that helps them front-run directional moves. The DMI perfectly fills this need by identifying when directional momentum is building across multiple timeframes.


When multiple timeframes show aligned DMI signals, it indicates strong institutional participation and higher probability moves. The colored candle system provides instant visual feedback, allowing you to quickly assess whether the market is in a strong trending phase (green/red candles) or a choppy, neutral condition (yellow candles) where breakout strategies might fail.



## Reading ThinkOrSwim DMI Documentation


Before building our multi-timeframe version, it's crucial to understand the foundational DMI concepts from ThinkOrSwim's official documentation. According to TD Ameritrade, "DMI is a trend following indicator. DI+ crossing above the DI- suggests uptrend conditions and vice-versa. DI+ crossing below the DI- might signify the downtrend. ADX is used for confirmation: trend indications are more likely to be correct if ADX is rising and its values are above 50."


The DMI indicator takes two inputs (length and average type) and produces three plots: DI+, DI-, and ADX. For our multi-timeframe version, we need to understand that an uptrend occurs when DI+ crosses above DI-, a downtrend when DI+ crosses below DI-, and the ADX provides confirmation when it's above our threshold level (we'll use 20 instead of 50 for more trading opportunities).


This documentation gives us everything we need to build our enhanced version. The key insight is that we'll replicate these calculations across 17 different timeframes and create a zone classification system that automatically categorizes market conditions.



## Step-by-Step Coding Tutorial: Building the MTF DMI


Now let's walk through the complete process of building this Multi-Timeframe DMI indicator from scratch. This tutorial shows the actual development process, including debugging and problem-solving, to help you understand how to build complex multi-timeframe indicators.



### Step 1: Setting Up Global Variables and Input Parameters


We start by establishing the foundational inputs that control the indicator's behavior across all timeframes:



```
input coloredCandlesOn = yes;
input length = 14;
input ADXLevels = 20;
input averageType = AverageType.WILDERS;
```


The `coloredCandlesOn` input allows users to toggle the colored candle functionality, respecting the principle that screen real estate is valuable and should only be used for meaningful information. The `length` parameter controls the DMI calculation period, while `ADXLevels` sets the threshold for trend strength confirmation.



### Step 2: Understanding Basic DMI Calculations


Before building the multi-timeframe version, we need to understand how to access the DMI plots. Through research and testing, we discover that ThinkOrSwim requires specific syntax to access the DMI components:



```
def plus = DMI(length, averageType)."DI+";
def minus = DMI(length, averageType)."DI-";
def adx = DMI(length, averageType).ADX;
```


Note the quotes around "DI+" and "DI-" - this is required because of the special characters. We then create our basic signal logic:



```
def bullishSignal = plus crosses above minus;
def bearishSignal = plus crosses below minus;
```



### Step 3: Creating Zone Classifications


For the colored candle system, we need zone definitions rather than just crossover signals. Zones remain true as long as conditions persist, while signals only trigger at the moment of crossover:



```
def bullishZone = plus > minus;
def bearishZone = plus < minus;
```


However, we quickly discover that this creates too many signals without ADX confirmation. We need to add trend strength filtering:



```
def bullishZone = plus > minus and adx >= ADXLevels;
def bearishZone = plus < minus and adx >= ADXLevels;
def neutralZone = !bullishZone and !bearishZone;
```



### Step 4: Building the Multi-Timeframe Framework


The core challenge is creating a framework that calculates DMI values for multiple timeframes efficiently. We need to manually recreate the DMI calculations using different aggregation periods since the built-in DMI function doesn't accept period parameters:



```
def monthPlus;
def monthMinus;
def monthAdx;
def monthBullishZone;
def monthBearishZone;
def monthNeutralZone;

if GetAggregationPeriod()  monthLoDiff and monthHiDiff > 0 then monthHiDiff else 0;
    def monthMinusDM = if monthLoDiff > monthHiDiff and monthLoDiff > 0 then monthLoDiff else 0;
    
    monthPlus = 100 * MovingAverage(averageType, monthPlusDM, length);
    monthMinus = 100 * MovingAverage(averageType, monthMinusDM, length);
    
    def monthDX = if (monthPlus + monthMinus > 0) then 100 * AbsValue(monthPlus - monthMinus) / (monthPlus + monthMinus) else 0;
    monthAdx = MovingAverage(averageType, monthDX, length);
    
    monthBullishZone = monthPlus > monthMinus and monthAdx >= ADXLevels;
    monthBearishZone = monthPlus < monthMinus and monthAdx >= ADXLevels;
    monthNeutralZone = !monthBullishZone and !monthBearishZone;
} else {
    monthPlus = 0;
    monthMinus = 0;
    monthAdx = 0;
    monthBullishZone = 0;
    monthBearishZone = 0;
    monthNeutralZone = 0;
}
```


This framework manually calculates the directional movement by comparing current and previous period highs and lows, then applies the appropriate moving averages and ADX calculations. The conditional logic ensures that timeframe data only displays when you're on a chart timeframe equal to or lower than the calculated timeframe.



### Step 5: Implementing the Copy-Paste Strategy


Rather than manually typing each timeframe, we use a strategic copy-paste approach. We create the monthly framework first, then use find-and-replace to quickly generate all 17 timeframes:



```
# Copy the monthly code block
# Replace "month" with "week" for weekly calculations
# Replace "Month" with "Week" in period specifications
# Repeat for all timeframes: 4Days, 3Days, 2Days, Day, 4Hours, 2Hours, Hour, 30Min, 15Min, 10Min, 5Min, 4Min, 3Min, 2Min, Min
```


This systematic approach allows us to build the entire 1100+ line indicator efficiently while maintaining consistency across all timeframes.



### Step 6: Creating the Automatic Labeling System


The labeling system provides instant visual feedback about trend conditions across all relevant timeframes:



```
AddLabel(monthBullishZone, "M", Color.GREEN);
AddLabel(monthBearishZone, "M", Color.RED);
AddLabel(monthNeutralZone, "M", Color.YELLOW);

AddLabel(weekBullishZone, "W", Color.GREEN);
AddLabel(weekBearishZone, "W", Color.RED);
AddLabel(weekNeutralZone, "W", Color.YELLOW);
```


This creates colored labels that appear in the upper corner of your chart. Green indicates bullish zones with strong directional movement and ADX confirmation. Red shows bearish zones with similar strength requirements. Yellow warns of neutral conditions where breakout strategies may fail.



### Step 7: Adding the Colored Candle System


The colored candle system translates the current timeframe's zone classification into immediate visual feedback:



```
# Current timeframe calculations
def HiDiff = high - high[1];
def LoDiff = low[1] - low;
def PlusDM = if HiDiff > LoDiff and HiDiff > 0 then HiDiff else 0;
def MinusDM = if LoDiff > HiDiff and LoDiff > 0 then LoDiff else 0;

def Plus = 100 * MovingAverage(averageType, PlusDM, length);
def Minus = 100 * MovingAverage(averageType, MinusDM, length);
def DX = if (Plus + Minus > 0) then 100 * AbsValue(Plus - Minus) / (Plus + Minus) else 0;
def Adx = MovingAverage(averageType, DX, length);

def BullishZone = Plus > Minus and Adx >= ADXLevels;
def BearishZone = Plus < Minus and Adx >= ADXLevels;
def NeutralZone = !BullishZone and !BearishZone;

AssignPriceColor(if coloredCandlesOn and NeutralZone then Color.YELLOW 
                 else if coloredCandlesOn and BullishZone then Color.GREEN 
                 else if coloredCandlesOn and BearishZone then Color.RED 
                 else Color.CURRENT);
```


This system respects the user's preference for colored candles while providing instant trend recognition. The neutral zone check comes first to ensure that weak trending conditions are properly identified.



### Step 8: Debugging and Optimization


During development, we encountered several common issues that provide valuable learning opportunities:


**ADX Threshold Issues:** Initially, we used the documentation's suggested ADX threshold of 50, but discovered this rarely triggered on most timeframes. Through testing, we found that a threshold of 20 provides a good balance between signal quality and frequency.


**Variable Definition Errors:** The multi-timeframe approach requires careful variable management. Each timeframe needs its own variable set, and we must define variables outside conditional blocks before assigning values inside them.


**Aggregation Period Logic:** The conditional logic ensures that higher timeframe data only appears when you're on equal or lower timeframes. This prevents information overload while ensuring you never miss important context.



### Step 9: User Control and Customization


The final indicator includes user controls that allow customization without modifying the core code:



```
input coloredCandlesOn = yes;  # Toggle colored candles
input length = 14;             # DMI calculation period  
input ADXLevels = 20;          # Trend strength threshold
input averageType = AverageType.WILDERS;  # Smoothing method
```


These inputs allow traders to adapt the indicator to different trading styles. Conservative traders might increase the ADX threshold to 25 or 30 for higher-quality signals, while aggressive traders might lower it to 15 for more opportunities.



## Practical Application and Trading Strategies


The MTF DMI excels in several specific trading scenarios. For breakout trading, look for periods when multiple timeframes transition from neutral (yellow) to directional (green or red) simultaneously. This often indicates the beginning of strong trending moves with institutional participation.


The colored candle system provides immediate feedback about trend quality. When you see consistent green or red candles across multiple timeframes, it suggests the trend has strong momentum behind it. Extended periods of yellow candles often indicate compression that precedes explosive moves.


Risk management improves significantly with multi-timeframe context. When your trading timeframe shows a signal but higher timeframes show opposing bias, consider reducing position size or waiting for better alignment. This prevents many false breakout losses that occur when traders ignore higher-timeframe context.



## Integration with Other Trading Systems


The MTF DMI works exceptionally well with volatility-based systems like the Volatility Box. When DMI signals align with volatility edges, it creates high-probability setups with clearly defined risk levels. The multi-timeframe analysis adds crucial context that single-timeframe indicators cannot provide.


For momentum continuation strategies, use the multi-timeframe alignment to identify when trends have room to run. When 4-5 consecutive timeframes show the same directional bias, pullbacks often offer excellent entry opportunities rather than trend reversal signals.

## thinkScript code

```
#TOS Indicators
#Home of the Volatility Box
#Full tutorial here: tosindicators.com/indicators/mtf-dmi
#Contains code written by Hubert Senters and Pete Hahn

input coloredCandlesOn = yes;
input length = 14;
input ADXLevels = 20;
input averageType = AverageType.WILDERS;

# Monthly DMI Calculations
def monthPlus;
def monthMinus;
def monthAdx;
def monthBullishZone;
def monthBearishZone;
def monthNeutralZone;

if GetAggregationPeriod()  monthLoDiff and monthHiDiff > 0 then monthHiDiff else 0;
    def monthMinusDM = if monthLoDiff > monthHiDiff and monthLoDiff > 0 then monthLoDiff else 0;
    
    monthPlus = 100 * MovingAverage(averageType, monthPlusDM, length);
    monthMinus = 100 * MovingAverage(averageType, monthMinusDM, length);
    
    def monthDX = if (monthPlus + monthMinus > 0) then 100 * AbsValue(monthPlus - monthMinus) / (monthPlus + monthMinus) else 0;
    monthAdx = MovingAverage(averageType, monthDX, length);
    
    monthBullishZone = monthPlus > monthMinus and monthAdx >= ADXLevels;
    monthBearishZone = monthPlus < monthMinus and monthAdx >= ADXLevels;
    monthNeutralZone = !monthBullishZone and !monthBearishZone;
} else {
    monthPlus = 0;
    monthMinus = 0;
    monthAdx = 0;
    monthBullishZone = 0;
    monthBearishZone = 0;
    monthNeutralZone = 0;
}

AddLabel(monthBullishZone, "M", Color.GREEN);
AddLabel(monthBearishZone, "M", Color.RED);
AddLabel(monthNeutralZone, "M", Color.YELLOW);

# Weekly DMI Calculations
def weekPlus;
def weekMinus;
def weekAdx;
def weekBullishZone;
def weekBearishZone;
def weekNeutralZone;

if GetAggregationPeriod()  weekLoDiff and weekHiDiff > 0 then weekHiDiff else 0;
    def weekMinusDM = if weekLoDiff > weekHiDiff and weekLoDiff > 0 then weekLoDiff else 0;
    
    weekPlus = 100 * MovingAverage(averageType, weekPlusDM, length);
    weekMinus = 100 * MovingAverage(averageType, weekMinusDM, length);
    
    def weekDX = if (weekPlus + weekMinus > 0) then 100 * AbsValue(weekPlus - weekMinus) / (weekPlus + weekMinus) else 0;
    weekAdx = MovingAverage(averageType, weekDX, length);
    
    weekBullishZone = weekPlus > weekMinus and weekAdx >= ADXLevels;
    weekBearishZone = weekPlus < weekMinus and weekAdx >= ADXLevels;
    weekNeutralZone = !weekBullishZone and !weekBearishZone;
} else {
    weekPlus = 0;
    weekMinus = 0;
    weekAdx = 0;
    weekBullishZone = 0;
    weekBearishZone = 0;
    weekNeutralZone = 0;
}

AddLabel(weekBullishZone, "W", Color.GREEN);
AddLabel(weekBearishZone, "W", Color.RED);
AddLabel(weekNeutralZone, "W", Color.YELLOW);

# Daily DMI Calculations  
def dayPlus;
def dayMinus;
def dayAdx;
def dayBullishZone;
def dayBearishZone;
def dayNeutralZone;

if GetAggregationPeriod()  dayLoDiff and dayHiDiff > 0 then dayHiDiff else 0;
    def dayMinusDM = if dayLoDiff > dayHiDiff and dayLoDiff > 0 then dayLoDiff else 0;
    
    dayPlus = 100 * MovingAverage(averageType, dayPlusDM, length);
    dayMinus = 100 * MovingAverage(averageType, dayMinusDM, length);
    
    def dayDX = if (dayPlus + dayMinus > 0) then 100 * AbsValue(dayPlus - dayMinus) / (dayPlus + dayMinus) else 0;
    dayAdx = MovingAverage(averageType, dayDX, length);
    
    dayBullishZone = dayPlus > dayMinus and dayAdx >= ADXLevels;
    dayBearishZone = dayPlus < dayMinus and dayAdx >= ADXLevels;
    dayNeutralZone = !dayBullishZone and !dayBearishZone;
} else {
    dayPlus = 0;
    dayMinus = 0;
    dayAdx = 0;
    dayBullishZone = 0;
    dayBearishZone = 0;
    dayNeutralZone = 0;
}

AddLabel(dayBullishZone, "D", Color.GREEN);
AddLabel(dayBearishZone, "D", Color.RED);
AddLabel(dayNeutralZone, "D", Color.YELLOW);

# Current Timeframe DMI for Colored Candles
def HiDiff = high - high[1];
def LoDiff = low[1] - low;
def PlusDM = if HiDiff > LoDiff and HiDiff > 0 then HiDiff else 0;
def MinusDM = if LoDiff > HiDiff and LoDiff > 0 then LoDiff else 0;

def Plus = 100 * MovingAverage(averageType, PlusDM, length);
def Minus = 100 * MovingAverage(averageType, MinusDM, length);
def DX = if (Plus + Minus > 0) then 100 * AbsValue(Plus - Minus) / (Plus + Minus) else 0;
def Adx = MovingAverage(averageType, DX, length);

def BullishZone = Plus > Minus and Adx >= ADXLevels;
def BearishZone = Plus < Minus and Adx >= ADXLevels;
def NeutralZone = !BullishZone and !BearishZone;

# Colored Candles
AssignPriceColor(if coloredCandlesOn and NeutralZone then Color.YELLOW 
                 else if coloredCandlesOn and BullishZone then Color.GREEN 
                 else if coloredCandlesOn and BearishZone then Color.RED 
                 else Color.CURRENT);
```

## Questions

### How do I build a Multi-Timeframe DMI indicator in ThinkOrSwim step-by-step?

Start by reading the ThinkOrSwim DMI documentation to understand the basic calculations (DI+, DI-, ADX). Create a framework using GetAggregationPeriod() conditions to calculate DMI values for each timeframe. For each timeframe, calculate directional movement using high/low differences, apply moving averages, and determine bullish/bearish zones based on DI+ vs DI- relationships with ADX strength confirmation above your threshold level (typically 20).

### What makes the MTF DMI different from the standard DMI indicator?

The MTF DMI analyzes 17 different timeframes simultaneously (from 1 minute to monthly) compared to the standard DMI's single timeframe. It includes colored candles that change based on trend strength, automatic zone labeling showing all timeframe statuses, and user-controlled display options. This provides comprehensive trend alignment analysis that helps identify high-probability momentum opportunities and avoid false breakouts.

### How do the colored candles work in the MTF DMI system?

Colored candles use the current chart timeframe's DMI analysis to change candle colors automatically. Green candles indicate bullish zones (DI+ > DI- with ADX above threshold), red candles show bearish zones (DI- > DI+ with strong ADX), and yellow candles warn of neutral conditions (weak trending or insufficient ADX). Users can toggle this feature on/off, respecting the principle that screen real estate should only be used for meaningful information.

### What ADX threshold settings work best for different trading styles?

Start with the default ADX threshold of 20, which provides a good balance between signal quality and frequency. Conservative traders can increase to 25-30 for higher-quality signals but fewer opportunities. Aggressive momentum traders might lower to 15 for more signals. The documentation suggests 50, but this rarely triggers in practice, so 20 is more practical for active trading.

### How do I interpret the automatic labeling system in MTF DMI?

Labels appear in the upper corner showing timeframe status with color coding: Green = bullish zone (DI+ > DI- with strong ADX), Red = bearish zone (DI- > DI+ with strong ADX), Yellow = neutral zone (weak ADX or unclear direction). Labels only display for timeframes higher than your current chart to prevent information overload. Look for alignment across multiple labels for highest probability setups.

### Why do I need to manually recreate DMI calculations for multiple timeframes?

ThinkOrSwim's built-in DMI function doesn't accept period parameters, so we must manually recreate the calculations using high/low differences, directional movement calculations, and moving averages for each timeframe. This requires calculating HiDiff, LoDiff, PlusDM, MinusDM, then applying the proper DMI formulas with different aggregation periods like "Month", "Week", "Day", etc.

### How can I optimize the MTF DMI for momentum and breakout trading?

Focus on timeframe alignment - when 3-5 consecutive timeframes show the same directional bias (all green or all red labels), it indicates strong institutional participation. Use yellow candles to identify compression periods that often precede explosive moves. Avoid trading when labels show conflicting signals across timeframes, as this suggests choppy, range-bound conditions where breakout strategies may fail.

### Can I use MTF DMI with volatility-based trading systems?

Yes, MTF DMI works excellently with volatility systems like the Volatility Box. When DMI signals align with volatility edges, it creates high-probability setups with clearly defined risk levels. The multi-timeframe analysis adds crucial context about trend strength and direction that pure volatility systems lack. Use DMI to determine trend bias, then use volatility systems for precise entry and exit timing.

## Related

- [Dynamic RSI](https://tosindicators.com/indicators/dynamic-rsi)
- [How to Build a Fair Value Gap Indicator in ThinkorSwim](https://tosindicators.com/indicators/fair-value-gap)
- [How to Build a Heiken Ashi Trend Dots Indicator in ThinkOrSwim](https://tosindicators.com/indicators/heiken-ashi)
- [Commodities Tracker](https://tosindicators.com/indicators/commodities-tracker)
- [Trend Squeeze](https://tosindicators.com/indicators/trend-squeeze)
- [Volume Intensity](https://tosindicators.com/indicators/volume-intensity)

