Squeeze_Break
Download scriptOverview
This trading tool is designed to identify specific market conditions where price action shifts from a period of "compression" (low volatility/sideways movement) to "expansion" (high volatility/trending movement). By monitoring these transitions, the script helps traders spot potential breakout opportunities.
Core Logic and Methodology
The logic is built upon a strategy that compares two different types of moving averages: Bollinger Bands and Keltner Channels.
- Bollinger Bands: These are highly sensitive to price volatility. They expand and contract quickly as market activity changes.
- Keltner Channels: These are generally more stable and provide a broader "envelope" of normal price movement.
The script analyzes the relationship between these two indicators to determine the market's current state:
1. Market Consolidation (The Squeeze) When the Bollinger Bands contract and fit inside the Keltner Channels, it indicates that the market is in a "squeeze." This suggests that price action is becoming very tight and volatility is low.
- Visual Representation: The script displays a Red Histogram. The taller the red bars, the tighter the market is squeezing.
2. Market Breakout (The Expansion) When the Bollinger Bands expand and push outside of the Keltner Channels, it indicates that the market is breaking out of its consolidation phase and moving into a trending state.
- Visual Representation: The script displays a Green Histogram. The taller the green bars, the stronger the current price trend or volatility.
Trading Signals and Bias
To improve accuracy, the tool incorporates a Momentum Indicator, which acts as a "directional filter." While the squeeze tells you when the market might move, Momentum tells you which way it is likely to go:
- Bullish Signal (Potential Buy): The script triggers an alert when the price breaks out of the squeeze (Green Histogram appears) while the Momentum is above zero.
- Bearish Signal (Potential Sell): The script triggers an alert when the price breaks out of the squeeze (Green Histogram appears) while the Momentum is below zero.
Key Features for the User
- Automated Alerts: When a breakout occurs that meets the specific criteria, the tool can trigger an audible alert and place visual markers (arrows) on the chart to notify you instantly.
- On-Screen Dashboard: The script includes an optional information panel that displays several key market metrics simultaneously—such as ATR (volatility), ADX (trend strength), RSI (overbought/oversold levels), and MACD—giving you a comprehensive snapshot of the market health at a glance.
- Visual Clarity: By separating "Squeeze" states from "Breakout" states into distinct colors (Red vs. Green), the tool allows for quick visual scanning of historical and current price action.
//+------------------------------------------------------------------+
//| Des_Squeeze_Play.mq4 |
//| DesO'Regan |
//| mailto: oregan_des@hotmail.com |
//+------------------------------------------------------------------+
// ===========================================================================================================
// This indicator is based on a strategy mentioned in John Carter's book, Mastering the Trade. The basic idea
// behind the strategy is that markets tend to move from periods of low volatility to high volatility and
// visa versa. The strategy aims to capture moves from low to high volatility. For gauging this he uses two
// common indicators - Bollinger Bands and Keltner Channels (ok, not so common!). He also uses the Momentum
// indicator to provide a trade bias as soon as the Bollinger Bands come back outside the Keltner Channels.
//
// The Squeeze_Break indicator combines this into a signal indicator and has the following components:
// 1. A positive green histogram means that the Bollinger Bands are outside the Keltner Channels
// and the market is lightly to be trending or volatile. The stronger the histogram the stronger
// the directional price move.
// 2. A negative red histogram means that the Bollinger Bands are inside the Keltner Channels
// and the market is lightly to be consolidating. The stronger the red histogram the tighter
// price action is becoming.
// 3. Incorporated into the indicator is a Momentum indicator. According to the strategy J. Carter
// goes long when the Bollinger Bands break outside the Keltner Bands and the Momentum indicator
// is above the zero line. He goes short when the Momentum indicator is below the zero line on the
// break.
// 4. I've also added other indicator info in the top left hand corner to give a broader idea
// of current market conditions.
// 5. The indicator provides audio alerts when a potential breakout is occurring.
//
// This indicator tends to be better with the larger timeframes. Personally I don't trade on an alert
// signal alone. It's just a handy tool for warning me of potential breakout trades.
// ===========================================================================================================
#property copyright "DesORegan"
#property link "mailto: oregan_des@hotmail.com"
// ====================
// indicator properties
// ====================
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 ForestGreen
#property indicator_color2 Red
#property indicator_color3 White
// ===================
// User Inputs
// ===================
extern int Boll_Period=20;
extern double Boll_Dev=2.0;
extern int Keltner_Period=20;
extern double Keltner_Mul=1.5;
extern int Momentum_Period=12;
extern int Back_Bars=1000;
extern bool Alert_On=false;
extern bool On_Screen_Info=false;
// =========================
// Buffer Array Declarations
// =========================
double Pos_Diff[]; // Pos Histogram
double Neg_Diff[]; // Neg Histogram
double Momentum[]; // Momentum Indicator
// ===========================
// Internal Array Declarations
// ===========================
double Squeeze[]; // Used to track which "i" (index value) is above
// and below zero line. 0 followed by 1 triggers alert
// =========================
// Internal Global Variables
// =========================
datetime Last_Alert_Time = 0; // Used to prevent continuous alerts on current bar
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
IndicatorDigits(4); // indicator value precision
//======================
// Indicator Setup
//======================
SetIndexStyle(0,DRAW_HISTOGRAM,EMPTY,2);
SetIndexBuffer(0,Pos_Diff);
SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,2);
SetIndexBuffer(1,Neg_Diff);
SetIndexStyle(2,DRAW_LINE,STYLE_SOLID);
SetIndexBuffer(2,Momentum);
// ===================
// Indicator Labels
// ===================
IndicatorShortName("Squeeze_Break (Boll:"+Boll_Period+","+DoubleToStr(Boll_Dev,1)+";Kelt:"+Keltner_Period+","+DoubleToStr(Keltner_Mul,1)+";Mom:"+Momentum_Period+")");
// ====================
// Array Initialization
// ====================
ArrayResize(Squeeze, Back_Bars); // Stores whether histogram is above/below zero line
ArrayInitialize(Squeeze, 0); // initialises array with 0's
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
ObjectsDeleteAll();
Comment(" ","\n",
" ","\n",
" ","\n",
" ","\n",
" ");
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
//=======================
// Indicator Optimization
//=======================
int Counted_Bars = IndicatorCounted();
if(Counted_Bars < 0) return;
if(Counted_Bars > 0) Counted_Bars = Counted_Bars - Keltner_Period;
int limit = Bars - Counted_Bars;
//=======================
// On-Screen Information
//=======================
if (On_Screen_Info == true)
{
double ATR =iATR(Symbol(),PERIOD_D1,14,0);
double Todays_Range = iHigh(Symbol(),PERIOD_D1,0) - iLow(Symbol(),PERIOD_D1,0);
double ADX = iADX(Symbol(),0,14,PRICE_CLOSE,MODE_MAIN,0);
double RSI = iRSI(Symbol(),0,14,PRICE_CLOSE,0);
double MACD_Main = iMACD(Symbol(),0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
double MACD_Signal = iMACD(Symbol(),0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
double Sto_Main = iStochastic(Symbol(),0,14,3,3,MODE_SMA,1,MODE_MAIN,0);
double Sto_Signal = iStochastic(Symbol(),0,14,3,3,MODE_SMA,1,MODE_SIGNAL,0);
Comment("-----------------------------------------------------------------",
"\nDaily ATR(14): ",ATR," Todays Range: ",Todays_Range,
"\nADX(14): ",NormalizeDouble(ADX,2)," RSI(14): ",NormalizeDouble(RSI,2),
"\nMACD(12,26,9): ",MACD_Main,", ",MACD_Signal,
"\nStochastic(14,3,3): ",NormalizeDouble(Sto_Main,2),", ",NormalizeDouble(Sto_Signal,2),
"\n-----------------------------------------------------------------");
}
//======================
// Main Indicator Loop
//======================
for(int i = limit; i >= 0; i--) //main indicator FOR loop
{
// ======================
// Indicator Calculations
// ======================
double MA_Hi = iMA(Symbol(),0,Keltner_Period,0,MODE_SMA,PRICE_HIGH,i);
double MA_Lo = iMA(Symbol(),0,Keltner_Period,0,MODE_SMA,PRICE_LOW,i);
double Kelt_Mid_Band = iMA(Symbol(),0,Keltner_Period,0,MODE_SMA,PRICE_TYPICAL,i);
double Kelt_Upper_Band = Kelt_Mid_Band + ((MA_Hi - MA_Lo)*Keltner_Mul);
double Kelt_Lower_Band = Kelt_Mid_Band - ((MA_Hi - MA_Lo)*Keltner_Mul);
double Boll_Upper_Band = iBands(Symbol(),0, Boll_Period,Boll_Dev,0,PRICE_CLOSE, MODE_UPPER,i);
double Boll_Lower_Band = iBands(Symbol(),0, Boll_Period,Boll_Dev,0,PRICE_CLOSE, MODE_LOWER,i);
// ======================
// Buffer Calculations
// ======================
Momentum[i] = (Close[i] - Close[i+Momentum_Period]);
if (Boll_Upper_Band >= Kelt_Upper_Band || Boll_Lower_Band <= Kelt_Lower_Band)
{
Pos_Diff[i] = (MathAbs(Boll_Upper_Band - Kelt_Upper_Band)+MathAbs(Boll_Lower_Band - Kelt_Lower_Band));
Squeeze[i] = 1;
}
else
{
Pos_Diff[i] = 0;
}
if (Boll_Upper_Band < Kelt_Upper_Band && Boll_Lower_Band > Kelt_Lower_Band)
{
Neg_Diff[i] = -(MathAbs(Boll_Upper_Band - Kelt_Upper_Band)+MathAbs(Boll_Lower_Band - Kelt_Lower_Band));
Squeeze[i] = 0;
}
else
{
Neg_Diff[i] = 0;
}
// ======================
// Trigger Check
// ======================
if (Squeeze[i] == 1 && Squeeze[i+1] == 0 && Momentum[i] > 0 && i == 0) // a cross above zero line and Mom > 0
{
if (Last_Alert_Time != Time[0])
{
if (Alert_On == true) Alert("Alert: Possible Breakout - "+Symbol()+" - "+TimeToStr(TimeLocal()));
Last_Alert_Time = Time[0];
ObjectCreate("Breakout"+Time[0],OBJ_ARROW,0,Time[0],Ask);
ObjectSet("Breakout"+Time[0],OBJPROP_ARROWCODE,1);
ObjectSet("Breakout"+Time[0],OBJPROP_COLOR,Blue);
ObjectSet("Breakout"+Time[0],OBJPROP_WIDTH,2);
}
}
if (Squeeze[i] == 1 && Squeeze[i+1] == 0 && Momentum[i] < 0 && i == 0 ) // a cross above zero line and Mom < 0
{
if (Last_Alert_Time != Time[0])
{
if (Alert_On == true) Alert("Alert: Possible Breakout - "+Symbol()+" - "+TimeToStr(TimeLocal()));
Last_Alert_Time = Time[0];
ObjectCreate("Breakout"+Time[0],OBJ_ARROW,0,Time[0],Bid);
ObjectSet("Breakout"+Time[0],OBJPROP_ARROWCODE,1);
ObjectSet("Breakout"+Time[0],OBJPROP_COLOR,Red);
ObjectSet("Breakout"+Time[0],OBJPROP_WIDTH,2);
}
}
} // end of main indicator FOR loop
return(0);
}
//+------------------------------------------------------------------+
Comments