Skip to main content

Multi-Timeframe Squeeze Indicator for ThinkOrSwim (Free Download)

IndicatorFreeBeginner21 min video531 lines of codeMay 16, 2020Updated Oct 21, 2026

A free multi-time frame (MTF) Squeeze indicator for ThinkOrSwim: 18 labels from monthly to 1-minute turn red when that timeframe is in a squeeze.

Multi-Time Frame (MTF) Squeeze Indicator on a ThinkOrSwim chart
  • Red label: that timeframe is in a squeeze
  • Dark green label: no squeeze

18 labels run from monthly (M) down to 1-minute (1m).

General Dynamics, 1-minute chart, at 4:00 in the video. Watch this moment

On this page

What you'll build

Multi-Time Frame (MTF) Squeeze Indicator in ThinkOrSwim: The multi-time frame code block in the thinkScript editor
The multi-time frame code block in the thinkScript editor, at 12:00 in the video.
On real data
  • In a squeeze
  • No squeeze (label)
  • No squeeze (dot)
720740760780JunJulAugSepOctMW4D3D2DD
SPY at the Oct 19, 2026 close. Labels from monthly (M) to daily (D), computed from SPY daily bars with the default squeeze settings (20, 1.5, 2.0): 2D is in a squeeze. The dots under the chart are the daily squeeze. The intraday labels need intraday bars, so they are left out here.
Type
Indicator
Runs as
Chart labels
Code
531 lines
Video
21 minutes
Level
Beginner

In this tutorial I build a multi-time frame (MTF) Squeeze indicator for ThinkOrSwim that shows the default Squeeze on every timeframe at a glance. Each timeframe gets a label on the chart, from M for monthly down to 1m, red when that timeframe is in a squeeze and dark green when it isn't.

The indicator rebuilds the Squeeze from Bollinger Band and Keltner Channel source code, because the built-in function tends to give false squeeze signals inside multi-time frame code. It's for Squeeze traders who check several timeframes, and for anyone who wants a reusable multi-time frame template in thinkScript.

Key takeaways

  • The MTF Squeeze indicator for ThinkOrSwim plots 18 labels, from monthly (M) down to 1-minute (1m). A label is red when that timeframe is in a squeeze and dark green when it isn't.
  • It uses ThinkOrSwim's default Squeeze settings: length 20, nK 1.5, nBB 2 and an alert line of 1.
  • A timeframe is in a squeeze when nBB times the standard deviation, divided by nK times the average true range, is below 1. That means the Bollinger Bands are inside the Keltner Channels.
  • The indicator rebuilds the Squeeze from source code because the built-in Squeeze function tends to give false squeeze signals inside an if/else block that uses aggregation periods.
  • ThinkOrSwim can only read timeframes equal to or higher than your chart's, so on a 5-minute chart the 1m to 4m labels don't appear.

What it shows

What the MTF Squeeze Indicator Shows

The MTF Squeeze indicator is a row of chart labels, one per timeframe, that shows whether each timeframe is in a squeeze. It saves you from flipping through charts: one glance tells you which timeframes have the default squeeze.

Each label is red when that timeframe has a squeeze and dark green when it doesn't. The free download covers 18 timeframes. The table lists each label with the aggregation period and the period string the code uses for it.

LabelTimeframeAggregation checkPrice period
MMonthlyAggregationPeriod.Monthperiod="Month"
WWeeklyAggregationPeriod.weekperiod="week"
4D4-dayAggregationPeriod.four_daysperiod="4 days"
3D3-dayAggregationPeriod.three_daysperiod="3 days"
2D2-dayAggregationPeriod.two_daysperiod="2 days"
DDailyAggregationPeriod.dayperiod="day"
4h4-hourAggregationPeriod.four_hoursperiod="4 Hours"
2h2-hourAggregationPeriod.two_hoursperiod="2 Hours"
1h1-hourAggregationPeriod.hourperiod="1 Hour"
30m30-minuteAggregationPeriod.Thirty_Minperiod="30 Min"
20m20-minuteAggregationPeriod.Twenty_Minperiod="20 Min"
15m15-minuteAggregationPeriod.Fifteen_Minperiod="15 Min"
10m10-minuteAggregationPeriod.Ten_Minperiod="10 Min"
5m5-minuteAggregationPeriod.Five_Minperiod="5 Min"
4m4-minuteAggregationPeriod.Four_Minperiod="4 Min"
3m3-minuteAggregationPeriod.Three_Minperiod="3 Min"
2m2-minuteAggregationPeriod.Two_Minperiod="2 Min"
1m1-minuteAggregationPeriod.Minperiod="1 Min"

Labels only appear for timeframes equal to or higher than your chart's. ThinkOrSwim can read higher timeframes from the chart you're on, but nothing lower. On a 5-minute chart you'll see 5m and up, and you won't know whether the 1, 2, 3 or 4-minute charts have a squeeze. The higher labels also need enough candle data on your chart to calculate.

How to Read the Labels

A red MTF Squeeze label tells you that timeframe is in a squeeze with the default settings. It doesn't tell you which way price breaks or when. Open the red timeframes and read the setup on those charts.

Before you trade a squeeze, decide where your stop goes and size the position so a stop-out costs a small, fixed share of your account. To find squeezes across many stocks instead of one chart, use our free Squeeze dots scan or build a Squeeze dashboard for a watchlist.

The MTF Squeeze on real charts

Drawn from real intraday bars with the code on this page, through the Oct 20, 2026 close. The labels use the indicator's own math (length 20, nK 1.5, nBB 2, alert line 1) on each timeframe our data has: monthly, weekly, daily, 4-hour, 2-hour, 1-hour, 30, 20, 15, 10 and 5-minute. Hourly and longer intraday bars are built from 30-minute bars starting at 9:30; 10 and 20-minute bars from 5-minute bars. The 4D, 3D, 2D and 1 to 4-minute labels are gray because those bars are not in our data.

XLI: the most timeframes in a squeeze on Oct 20

MTF Squeeze labels on a XLI daily chart in ThinkOrSwim at the Oct 20, 2026 close: red labels for timeframes in a squeeze, dark green for the rest
XLI at the Oct 20, 2026 close: 7 of the 11 timeframes in our data were in a squeeze. The dots under the chart are the daily Squeeze.

Of the 44 stocks and ETFs we checked, XLI had the most timeframes in a squeeze at the Oct 20, 2026 close: D, 4h, 2h, 1h, 30m, 15m, 5m. Not in a squeeze: M, W, 20m, 10m. A stack of red labels says the stock is coiled on several clocks at once; it says nothing about which way it breaks.

The 14 ETFs on one screen

MTF Squeeze labels for SPY, QQQ, IWM, DIA and 10 sector ETFs at the Oct 20, 2026 close, red where each timeframe is in a squeeze
The same labels for 14 ETFs at the Oct 20, 2026 close, one row each.

By the numbers

4 of 44In a daily squeeze on Oct 20
27 of 44In a squeeze on the 15m, the most of any timeframe
3 of 44On the 4h, the fewest
8Names with 6 or more timeframes in a squeeze

30 well-known stocks and 14 ETFs at the Oct 20, 2026 close, 11 timeframes each.

Install it in ThinkOrSwim

MTF Squeeze

Download the Multi-Time Frame Squeeze indicator for ThinkOrSwim. The download is a .zip with one study file, TI_MTF_SqueezeSTUDY.ts, the same code as the Code tab on this page. It plots 18 labels from monthly to 1-minute using the default Squeeze settings. If you haven't added a custom study before, here's how to import an indicator into your ThinkOrSwim platform.

Download free

How to Build It in ThinkOrSwim

Building the MTF Squeeze takes one monthly block of code, then a copy of that block for every other timeframe.

  1. Click the Studies icon, click Create, and give the study a name.
  2. Add a header comment that credits the Blogspot source code with its link.
  3. Define the global variables: length, alert line, nK, nBB and the rest.
  4. Write the monthly block: the declarations, the if/else, and 2 labels.
  5. Click Apply, then check the M label against the built-in Squeeze on a monthly chart.
  6. Copy the block into a text editor, replace month with the next timeframe, fix the label text and the period string, and paste it back. Repeat down to 1 minute.

If you'd rather start from the finished file, download it and follow our guide on how to import a study into ThinkOrSwim.

How the code works

Why the Indicator Rebuilds the Squeeze From Source Code

The built-in Squeeze function in ThinkOrSwim tends to give false squeeze signals inside multi-time frame code. That happens when you reference it inside an if/else block that also uses aggregation periods. It doesn't return the squeeze alert value you'd expect, so the indicator doesn't work the way you want.

ThinkOrSwim's own documentation describes the Squeeze as a measure of two indicators and their relationship: the Bollinger Bands and the Keltner Channels. The squeeze is on when the Bollinger Bands fall inside the Keltner Channels. The Squeeze's source code is hidden, but the Bollinger Band and Keltner Channel source code isn't, so you can rebuild it from those pieces.

To speed things along, I used code that a member sent us from another thinkScript author's Blogspot, which recreates the Squeeze. If you use that code, leave the author's credit and Blogspot link in your header. Our download keeps it on the first lines.

The math comes down to one ratio. Bollinger Band width is a multiple of the standard deviation (nBB), and Keltner Channel width is a multiple of the average true range (nK). The code divides the first by the second and compares the result with the alert line of 1. Below 1, the Bollinger Bands are inside the Keltner Channels, and that timeframe is in a squeeze.

The Multi-Time Frame Framework

The MTF Squeeze is built on the drag-and-drop multi-time frame module from our MTF DMI indicator. Because that code was written to be reusable, I could lift the same framework and drop in the squeeze math. You could do the same for EMA crossovers or your own set of indicators.

  • Declare first. Each timeframe's variables are declared above its if/else block.
  • Check the timeframe. The if tests whether the chart's aggregation period is less than or equal to the timeframe you want to measure, then assigns the values.
  • Default to 0. The else sets every variable to 0 to keep things simple.
  • Prefix every name. Each variable starts with its timeframe, like monthPrice, so a find-and-replace turns the monthly block into the weekly one.

If you only need one higher timeframe, such as a daily level on an intraday chart, our tutorial on plotting higher time frame indicators with aggregation periods covers that simpler case.

How the Code Works

The MTF Squeeze code is a short global section followed by 18 blocks that each follow the same pattern. Once you understand the monthly block, you understand all of them.

Step 1: Global Variables

Global variables are the settings that don't change from one timeframe to the next. These are the default values of the built-in Squeeze.

This step’s code is free with an account. Create one or sign in.

To change the compression, change nk here. To set a value from the studies menu, change its def to input.

I renamed the source's nBB factor to nBB so the code is easier to copy and paste later.

Step 2: Declare the Monthly Variables

Each monthly variable is declared once, above the if/else, so both branches can assign it.

This step’s code is free with an account. Create one or sign in.

The download adds monthAggregationPeriod, a flag that hides the label on charts that can't read the monthly timeframe.

Step 3: The Monthly If Block

The if block checks that the chart is monthly or lower, then calculates the squeeze on monthly bars. Inside it, you assign values without def, because the variables already exist.

This step’s code is free with an account. Create one or sign in.

period="Month" makes each price read monthly bars.

The source code called an average true range function, and ThinkOrSwim reported no such function. My workaround was to break it out as the average of TrueRange over the length, with the monthly high, close and low.

Step 4: The Else Block

The else block gives every monthly variable a value of 0. Until each one has a value here, ThinkOrSwim shows an error.

This step’s code is free with an account. Create one or sign in.

With that done, one error is left: at least one plot should be defined. The labels fix that.

Step 5: The Labels

AddLabel takes a condition, the text and a color. One label shows when there's a monthly squeeze and the other shows when there isn't.

This step’s code is free with an account. Create one or sign in.

In the video I used black for no squeeze. Dark green, which the download uses, is easier to see on a black chart background.

Our AddLabel tutorial covers static and dynamic labels in more depth.

Step 6: Copy the Block to Every Timeframe

Copying the monthly block is where the naming pays off. I paste it into Sublime Text, press Ctrl+H, and replace month with week.

Then change the label text from "M" to "W". That's the one piece that's easy to forget: in the video, my weekly label showed up as a second M until I fixed it.

Some timeframes need a different period string. The aggregation check uses AggregationPeriod.four_days, but inside period I use "4 days" with the number.

This step’s code is free with an account. Create one or sign in.

That's how ThinkOrSwim's own examples write it, and it tends to work without glitches. I've had problems with other spellings there in the past.

Full thinkScript code

Multi-Time Frame (MTF) Squeeze Indicator.tsthinkScript · 531 lines
The full code is free with an account

Create a free account or sign in to copy all 531 lines and download the file.

Examples

Testing It Against the Built-in Squeeze

The MTF Squeeze labels should match the built-in Squeeze study on each timeframe's own chart, so I checked them that way as I built them in the video.

  • Monthly, no squeeze. The first chart had no monthly squeeze, and the built-in Squeeze on the monthly chart agreed. Coca-Cola had no monthly squeeze either.
  • Monthly squeeze. On a symbol that did have a monthly squeeze, the M label turned red.
  • Weekly. After I added the weekly block, that chart showed a squeeze on the monthly and none on the weekly.
  • 4-day. The 4D label showed no squeeze, and the 4-day chart confirmed it.

Customize and troubleshoot

Free Download vs the Member Version

The free MTF Squeeze indicator tracks one compression, the default mid compression that the built-in Squeeze uses. Volatility Box members have a second version in Module 9 of the Squeeze Course that takes the code one step further.

FeatureFree download (built in this tutorial)Member version (Module 9)
Compressions1, the default mid compression3, fast, mid and slow
Squeeze colorsRedGray for fast, red for mid, yellow for slow
No squeezeDark greenBlack in the video
Changing colorsEdit the AddLabel linesPick colors in the studies menu

In the video, I changed the member version's no-squeeze color from black to dark green in the studies menu, clicked Apply, and every label without a squeeze turned dark green. Colors you can set from the menu also help if you're colorblind.

Customizing and Stacking the Labels

The MTF Squeeze code is straightforward to extend because every timeframe block has the same shape.

Add the Fast and Slow Compressions

  • More compressions. Add an nK factor 2 and an nK factor 3, then repeat the squeeze code with a 2 and a 3 version of each variable.
  • Inputs instead of fixed values. Change any global def to input to set it from the studies menu.
  • Your own colors. Change color.red and color.dark_green in the AddLabel lines.

Stack Them With the MTF Squeeze Histogram

Volatility Box members who also have the MTF Squeeze Histogram indicator, from Module 8 of the Squeeze Course, can load both indicators, and the two sets of labels plot side by side. The fastest way I know to stack them is to click the hamburger menu on the chart, choose Detach, and shrink the window until the two sets of labels stack on top of one another.

If that makes the chart too skinny, a flex grid gives you more control over how wide each chart is.

Common Problems

Most MTF Squeeze problems come from the chart's timeframe, a missing value in the else block, or a label name.

  • Lower-timeframe labels are missing. That's by design. On a 5-minute chart, labels below 5 minutes can't calculate. Drop to a 1-minute chart to see all 18, and load enough days of data for the higher timeframes to calculate.
  • "At least one plot should be defined." The study needs output. Add the AddLabel lines.
  • "No such function" on the ATR line. Use Average(TrueRange(high, close, low), length) with the timeframe's period on each price.
  • Two labels with the same letter. You copied a block and didn't change the label text.
  • Errors on variables in a new block. Every declared variable needs a value in both the if and the else.

For other errors, our tutorial on how to debug thinkScript code walks through tracking them down.

Video: Multi-Time Frame (MTF) Squeeze Indicator, built line by line

21 minutes on YouTube.

Watch on YouTube

Questions

What is a multi-time frame Squeeze indicator?

It shows whether the Squeeze is on for several timeframes at once, so you don't have to flip through charts. Our free MTF Squeeze indicator plots 18 labels on a ThinkOrSwim chart, from monthly down to 1-minute. Each label is red when that timeframe is in a squeeze and dark green when it isn't.

How do I add the MTF Squeeze indicator to ThinkOrSwim?

Download the study file or copy the code from the Code tab. In ThinkOrSwim, click the Studies icon, click Create, paste in the code, name the study, and click OK, then Apply. The labels appear on the chart. Use a 1-minute chart to see all 18 timeframes, with enough candle data loaded for the higher ones to calculate.

Why don't I see the lower timeframe labels on my chart?

ThinkOrSwim can only read timeframes equal to or higher than the chart you're on. On a 5-minute chart, the indicator shows 5m and every higher timeframe, and it hides the 1, 2, 3 and 4-minute labels. Higher timeframes also need enough candle data on the chart to calculate.

Why not use the built-in Squeeze function for multiple timeframes?

When you reference the built-in Squeeze function inside an if/else block that uses aggregation periods, it tends to give false squeeze signals because it doesn't return the squeeze alert you'd expect. The MTF Squeeze rebuilds the squeeze from standard deviation and average true range instead, which works the way you'd expect.

What settings does the MTF Squeeze indicator use?

It uses the built-in Squeeze defaults: a length of 20, an nK factor of 1.5, an nBB factor of 2 and an alert line of 1. They're global variables at the top of the code. Change def to input on any of them if you want to set it from the studies menu.

How does the indicator decide a timeframe is in a squeeze?

For each timeframe it multiplies the standard deviation of the close by nBB and the average true range by nK, then divides the first by the second. If the result is below the alert line of 1, the Bollinger Bands are inside the Keltner Channels, and that timeframe's label turns red.

How do I add the fast and slow compressions?

Add an nK factor 2 and an nK factor 3 to the global variables, then repeat the squeeze code with a 2 and a 3 version of each variable. Volatility Box members have a finished version in Module 9 of the Squeeze Course, with all 3 compressions and label colors you can change in the studies menu.

Can I use this code for other multi-time frame indicators?

Yes. The framework comes from our MTF DMI indicator and works for things like EMA crossovers or your own indicators. Declare the variables above an if/else, check the aggregation period in the if, set everything to 0 in the else, and prefix each name with its timeframe so find-and-replace builds the next block.

Goes with

Get each new indicator by email

One email on Sundays with the week's new tool and its code. A free account also unlocks every .txt download.

No credit card. Unsubscribe anytime.