//+------------------------------------------------------------------+
//|                                             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 Blue
// ===================
// 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=true;
extern bool      On_Screen_Info=true;
// =========================
// 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,3);
   SetIndexBuffer(0,Pos_Diff);
   SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,3);
   SetIndexBuffer(1,Neg_Diff);
   SetIndexStyle(2,DRAW_LINE,STYLE_DOT);
   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,12,PRICE_CLOSE,MODE_MAIN,0);
      double RSI = iRSI(Symbol(),0,12,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,10,3,3,MODE_SMA,1,MODE_MAIN,0);    
      double Sto_Signal = iStochastic(Symbol(),0,10,3,3,MODE_SMA,1,MODE_SIGNAL,0);
   
   
      Comment("-----------------------------------------------------------------",
              "\nDaily ATR(14): ",ATR," Todays Range: ",Todays_Range,
              "\nADX(12): ",NormalizeDouble(ADX,2)," RSI(12): ",NormalizeDouble(RSI,2),
              "\nMACD(12,26,9): ",MACD_Main,", ",MACD_Signal,
              "\nStochastic(10,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