

//  Dynamic Fibonacci Grid v1.12 Walt
//--------------------------------------------------------------

#property indicator_chart_window

enum enColorScheme
{
   blue = 1//Blue
   ,red = 2//Red
   ,green = 3//Green
};

input int    Range_in_pips = 30;
extern int   Shift         = 1;
extern int   Spacing       = 25;
extern int   Width         = 24;
extern int   MA_mode       = 0;
extern bool  DrawZoneSeparatorLines = false;
input enColorScheme ColorScheme = blue;

#define NSL    10       // number of shade levels
#define NSVR   17      // number of solid vertical lines
#define NMA    7       // number of MAs, change ma_period[NMA-1] accordingly 
#define NTF    4       // number of time frames/lanes, change tfp[NTF] accordinlgy

double   fml[NTF][NMA];                                    // momentum lines
double   bsl_up[NTF][NSL];                                 // color shades levels to the up side
double   bsl_down[NTF][NSL];                               // color shades levels to the down side
double   bsl[NSL];                                         // color shades distances ('point' adjusted)
double   srl[28];                                          // support/resistance levels (total = 2*NSL + NMA + 1(Bid) )
double   price, average1, average2, point;
double   tmpArray[NMA], lowestMA, highestMA;
int      srgap, tfc, mac;                                  // color shades distances
int      _bsl[NSL]    = {10, 16, 26, 42, 68, 111, 179, 290, 470, 760}; // time shades distance : 9, 16, 26, 42, 68, 110, 178, 246
int      ma_period[NMA] = {21,34,55,75,100,144,233};         // SMAs, NMA-1
int      tfp[NTF]     = {1,5,15,60};                       // Time frames/lanes - in minutes. Like H4=240, D1=1440 etc...
int      counted_bars, startBar, bar, i, y;
int      gap = 10;
int      tf, c, offset, xUnit;
int      shift, spacing, width, supports, resistances;
color    Shade[NSL];//    = {C'220,240,255', C'180,210,255', C'140,180,255', C'100,150,255', C'60,120,255', C'20,90,255', C'0,60,255', C'0,40,225', C'0,30,200'};
color    col, macolor;
string   objName, dir, MA, name;
string   uniqueid = "FXG: ";
datetime curTime;
double   PipPoints;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

int init()
{
///////////////////////////////////////////////////
   switch(ColorScheme){
      case 1:
         color    ShadeBlue[NSL]    = {C'220,240,255', C'180,210,255', C'140,180,255', C'100,150,255', C'60,120,255', C'20,90,255', C'0,60,255', C'0,40,225', C'0,30,200'};
         ArrayCopy(Shade,ShadeBlue,0,0,WHOLE_ARRAY);
         break;
      case 2:
         color    ShadeRed[NSL]    = {C'253,221,207', C'251,200,180', C'249,180,155', C'247,160,131',      C'246,141,111'     , C'244,122,92', C'242,102,73', C'240,78,55', C'237,28,36'};
         ArrayCopy(Shade,ShadeRed,0,0,WHOLE_ARRAY);
         break;
      case 3:
         color    ShadeGreen[NSL]    = {C'187,206,194', C'158,188,169', C'132,171,146', C'111,164,131',      C'85,149,112'     , C'61,143,99', C'20,131,82', C'0,126,70', C'0,114,54'};
         ArrayCopy(Shade,ShadeGreen,0,0,WHOLE_ARRAY);
         break;
   }
   
///////////////////////////////////////////////////

   xUnit   = Period() * 60;
   shift   = Shift * xUnit;
   spacing = Spacing * xUnit;
   width   = Width * xUnit;
   point   = 0.01;
   if(Digits > 3) point = 0.0001;
   
      if(Digits==3 || Digits==5)
      {
      PipPoints=Point*10;
      }
   else
      {
      PipPoints=Point;
      }
   
   ChartSetInteger(0,CHART_SCALEFIX,true);
   ChartSetInteger(0,CHART_SHOW_DATE_SCALE,false);
   ChartSetDouble(0,CHART_FIXED_MAX,(Bid+(Range_in_pips*PipPoints)));
   ChartSetDouble(0,CHART_FIXED_MIN,(Bid-(Range_in_pips*PipPoints)));

//+------------------------------------------------------------------+
//| creating the objects for drawing the grid                        |
//+------------------------------------------------------------------+

   for(i=0; i<NSL; i++)  bsl[i] = _bsl[i]*point;
   for(tf=0; tf<NTF; tf++)
   {
      for(i=0; i<NSL; i++)
      {
         objName = uniqueid + "bsl_up_rect_" + tf + "_" + i;          // upper zones
         ObjectCreate(objName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
            ObjectSet(objName, OBJPROP_COLOR, Shade[i]);
            
         objName = uniqueid + "ext_bsl_up_rect_" + tf;            // external upper zones
         ObjectCreate(objName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
            ObjectSet(objName, OBJPROP_COLOR, C'255,255,255');
            
         objName = uniqueid + "bsl_down_rect_" + tf + "_" + i;        // lower zones
         ObjectCreate(objName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
            ObjectSet(objName, OBJPROP_COLOR, Shade[i]);
            
         objName = uniqueid + "ext_bsl_down_rect_" + tf;          // external lower zones
         ObjectCreate(objName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
            ObjectSet(objName, OBJPROP_COLOR, C'255,255,255');
            
         if(DrawZoneSeparatorLines == true){
            objName = uniqueid+"bsl_up_bar_"+tf+"_"+i;           // upper zone separator lines
            ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
               ObjectSet(objName, OBJPROP_COLOR, clrBlack);
               ObjectSet(objName, OBJPROP_RAY, false);
               ObjectSet(objName, OBJPROP_WIDTH, 1);
               ObjectSet(objName, OBJPROP_STYLE, 0);
               
            objName = uniqueid+"bsl_down_bar_"+tf+"_"+i;         // lower zone separator lines
            ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
               ObjectSet(objName, OBJPROP_COLOR, clrBlack);
               ObjectSet(objName, OBJPROP_RAY, false);
               ObjectSet(objName, OBJPROP_WIDTH, 1);
               ObjectSet(objName, OBJPROP_STYLE, 0);
         }
      }

      objName = uniqueid + "MidShade_" + tf;                      // price zone
      ObjectCreate(objName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
         ObjectSet(objName, OBJPROP_COLOR, C'255,255,144');
         //ObjectSet(objName, OBJPROP_COLOR, clrWhite);

      for(i=0; i<NMA; i++)
      {
         objName = uniqueid + "fml_bar_" + tf + "_" + i;              // horizontal momentum lines
         ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
            ObjectSet(objName, OBJPROP_COLOR, Black);
            ObjectSet(objName, OBJPROP_RAY, false);
            ObjectSet(objName, OBJPROP_WIDTH, 1);
         if(i<2 || i == NMA-1)
            ObjectSet(objName, OBJPROP_WIDTH, 3);
      }

      for(i=1; i<=NSVR; i++)
      {
         objName = uniqueid + "svr_" + tf + "_" + i;                  // solid vertical lines (10 pips or more)
         ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
         ObjectSet(objName, OBJPROP_RAY, false);
         ObjectSet(objName, OBJPROP_WIDTH, 3);
            
         objName = uniqueid + "ext_up_svr_" + tf;                 // extern upper vertical lines
         ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
         ObjectSet(objName, OBJPROP_RAY, false);
         ObjectSet(objName, OBJPROP_WIDTH, 3);
            
         objName = uniqueid + "ext_down_svr_" + tf;               // extern lower vertical lines
         ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
         ObjectSet(objName, OBJPROP_RAY, false);
         ObjectSet(objName, OBJPROP_WIDTH, 3);
      }
   }
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+

int deinit()
{
   string lookFor       = uniqueid;
   int    lookForLength = StringLen(lookFor);   
   for(i = ObjectsTotal() - 1; i >= 0; i--)
   {
      name = ObjectName(i);
         if(StringSubstr(name, 0, lookForLength) == lookFor) ObjectDelete(name);
   }
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+

int start()
{
   int X = -10, Y = 15, A = 10, B = 12;
   point   = 0.01;
   if(Digits > 3) point = 0.0001;
   
   ChartSetDouble(0,CHART_FIXED_MAX,(Bid+(Range_in_pips*PipPoints)));
   ChartSetDouble(0,CHART_FIXED_MIN,(Bid-(Range_in_pips*PipPoints)));
   
//+------------------------------------------------------------------+
//| Time lines                                                       |
//+------------------------------------------------------------------+

   int short_gap_count;
   int long_gap_count;
   int sr_short_gap_count;
   int sr_long_gap_count;
   curTime = Time[0];
   price   = Close[0];
    
   for(tf=0; tf<NTF; tf++)
   {
      bar = iBarShift(NULL, tfp[tf], curTime, false);
      for(i=0; i<NMA; i++)  fml[tf][i] = iMA(NULL, tfp[tf], ma_period[i], 0, MA_mode, PRICE_CLOSE, bar/Period());  // populating the fml array...
      for(i=0; i<NMA; i++) tmpArray[i] = fml[tf][i];                                                               // finding the highest and lowest MAs from the (7) fml's/MA's
      ArraySort(tmpArray);                                                                                         // copying the MAs levels of this TF to one dim array to feed ArrayBsearch
         lowestMA  = tmpArray[0];
         highestMA = tmpArray[6];

      for(i=0; i<NSL; i++)                                                                                         // populating the bsl arrays...
      {
         bsl_up[tf][i]   = lowestMA  + bsl[i];
         bsl_down[tf][i] = highestMA - bsl[i];
      }
   }

//+------------------------------------------------------------------+
//| drawing the color shades of the grid from top to bottom          |
//+------------------------------------------------------------------+

   for(tf=0; tf<NTF; tf++) 
   {
      offset = 0;                                                                // find the number of overlapping shades
      for(i=offset; i<NSL-1; i++) if(bsl_up[tf][i] <= bsl_down[tf][i]) offset++;

      if(offset > 0)                                                             // hide first level objects' overlapping, so they wont be left as 'ghosts'
      {
         objName = uniqueid + "bsl_up_rect_" + tf + "_" + (NSL-2-offset+1);
            ObjectSet(objName, OBJPROP_TIME1,  0);
            ObjectSet(objName, OBJPROP_TIME2,  0);
            ObjectSet(objName, OBJPROP_PRICE1, 0);
            ObjectSet(objName, OBJPROP_PRICE2, 0);
            
         objName = uniqueid + "bsl_down_rect_" + tf + "_" + (NSL-2-offset+1);
            ObjectSet(objName, OBJPROP_TIME1,  0);
            ObjectSet(objName, OBJPROP_TIME2,  0);
            ObjectSet(objName, OBJPROP_PRICE1, 0);
            ObjectSet(objName, OBJPROP_PRICE2, 0);
         if(DrawZoneSeparatorLines == true){ 
            objName = uniqueid+"bsl_up_bar_"+tf+"_"+(NSL-2-offset+1);
               ObjectSet(objName, OBJPROP_TIME1,  0);
               ObjectSet(objName, OBJPROP_TIME2,  0);
               ObjectSet(objName, OBJPROP_PRICE1, 0);
               ObjectSet(objName, OBJPROP_PRICE2, 0);
   
            objName = uniqueid+"bsl_down_bar_"+tf+"_"+(NSL-2-offset+1);
               ObjectSet(objName, OBJPROP_TIME1,  0);
               ObjectSet(objName, OBJPROP_TIME2,  0);
               ObjectSet(objName, OBJPROP_PRICE1, 0);
               ObjectSet(objName, OBJPROP_PRICE2, 0);
         }
      }
        
      double highest=0;
      for(i=NSL-2; i>=offset; i--)
      {
         objName = uniqueid + "bsl_up_rect_" + tf + "_" + (i-offset);
            ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing);
            ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+width);
            ObjectSet(objName, OBJPROP_PRICE1, bsl_up[tf][i]);
            ObjectSet(objName, OBJPROP_PRICE2, bsl_up[tf][i+1]);
                
         if (bsl_down[tf][i]>highest) highest=bsl_up[tf][i+1];
         
         if(DrawZoneSeparatorLines == true){    
            objName = uniqueid+"bsl_up_bar_"+tf+"_"+(i-offset);
               ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing);
               ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+width);
               ObjectSet(objName, OBJPROP_PRICE1, bsl_up[tf][i]);
               ObjectSet(objName, OBJPROP_PRICE2, bsl_up[tf][i]);
         }
      }

      double lowest=9999.9999;
      for(i=0; i<NSL-1; i++)
      {
         objName = uniqueid + "bsl_down_rect_" + tf + "_" + (i-offset);
            ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing);
            ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+width);
            ObjectSet(objName, OBJPROP_PRICE1, bsl_down[tf][i]);
            ObjectSet(objName, OBJPROP_PRICE2, bsl_down[tf][i+1]);
         
         if(bsl_down[tf][i]<lowest) lowest=bsl_down[tf][i+1];
         
         if(DrawZoneSeparatorLines == true){    
            objName = uniqueid+"bsl_down_bar_"+tf+"_"+(i-offset);
               ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing);
               ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+width);
               ObjectSet(objName, OBJPROP_PRICE1, bsl_down[tf][i]);
               ObjectSet(objName, OBJPROP_PRICE2, bsl_down[tf][i]);
         }
      }

      objName = uniqueid + "MidShade_" + tf;
         ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing);
         ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+width);
         ObjectSet(objName, OBJPROP_PRICE1, bsl_up[tf][offset]);
         ObjectSet(objName, OBJPROP_PRICE2, bsl_down[tf][offset]);
      
      objName = uniqueid + "ext_bsl_up_rect_" + tf;
         ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing);
         ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+width);
         ObjectSet(objName, OBJPROP_PRICE1, highest);
         ObjectSet(objName, OBJPROP_PRICE2, WindowPriceMax());
            
      objName = uniqueid + "ext_up_svr_" + tf;
         ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing+Width/2*xUnit);
         ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+Width/2*xUnit);
         ObjectSet(objName, OBJPROP_PRICE1, highest);
         ObjectSet(objName, OBJPROP_PRICE2, WindowPriceMax());   
         ObjectSet(objName, OBJPROP_COLOR,  clrNONE);
      
      objName = uniqueid + "ext_bsl_down_rect_" + tf;
         ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing);
         ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+width);
         ObjectSet(objName, OBJPROP_PRICE1, lowest);
         ObjectSet(objName, OBJPROP_PRICE2, WindowPriceMin());
        
      objName = uniqueid + "ext_down_svr_" + tf;
         ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing+Width/2*xUnit);
         ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+Width/2*xUnit);
         ObjectSet(objName, OBJPROP_PRICE1, lowest);
         ObjectSet(objName, OBJPROP_PRICE2, WindowPriceMin());
         ObjectSet(objName, OBJPROP_COLOR,  clrNONE);

//+------------------------------------------------------------------+
//| drawing the momentum lines bars                                  |
//+------------------------------------------------------------------+

      for(i=0; i<NMA; i++)
      {
         objName = uniqueid + "fml_bar_" + tf + "_" + i;
            ObjectSet(objName, OBJPROP_TIME1,  curTime+shift+tf*spacing+xUnit);
            ObjectSet(objName, OBJPROP_TIME2,  curTime+shift+tf*spacing+width-xUnit);
            ObjectSet(objName, OBJPROP_PRICE1, fml[tf][i]);
            ObjectSet(objName, OBJPROP_PRICE2, fml[tf][i]);

         if(i==0)
         {
            if(fml[tf][i] >= price) col = Red;
            else                    col = Lime;
            ObjectSet(objName, OBJPROP_COLOR, col);
         }
         if(i==1)
         {
            if(fml[tf][i] >= price) col = FireBrick;
            else                    col = ForestGreen;
            ObjectSet(objName, OBJPROP_COLOR, col);
         }
      }

//+------------------------------------------------------------------+
//| drawing the solid vertical lines                                 |
//+------------------------------------------------------------------+      

      ArrayInitialize(srl, -1);
      for (i=0; i<NMA; i++) srl[i] = fml[tf][i];
      for (i=offset; i<NSL; i++)
      {
         srl[NMA+i] = bsl_down[tf][i];
         srl[NMA+NSL+i] = bsl_up[tf][i];
      }
      
      srl[NMA+2*NSL] = price;
      ArraySort(srl);

      c           = 0;          // looking for a gap of 10 pips or more
      supports    = 0;
      resistances = 0;
      for(i=0; i<NMA+2*NSL+2; i++)
      {
         if(srl[i] > price) resistances++;
         if(srl[i] < price) supports++;
         if(-1 == srl[i])
            continue;
         if(srl[i+1]-srl[i] >= gap*point)
         {
            c++;
            objName = uniqueid + "svr_" + tf + "_" + c;
               ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing+Width/2*xUnit);
               ObjectSet(objName, OBJPROP_TIME2, curTime+shift+tf*spacing+Width/2*xUnit);
               ObjectSet(objName, OBJPROP_PRICE1, srl[i]+point);
               ObjectSet(objName, OBJPROP_PRICE2, srl[i+1]-point);

            if (srl[i+1] <= price)
            {
               if(price==srl[i+1]) short_gap_count++;
               ObjectSet(objName, OBJPROP_COLOR, FireBrick);
            }
            else
            {
               if(price==srl[i]) long_gap_count++;
               ObjectSet(objName, OBJPROP_COLOR, Green);
            }
         }
         
         if (srl[i+1]-srl[i] >= srgap*point)
         {
            if(srl[i+1] <= price)
               if(price==srl[i+1]) sr_short_gap_count++;
               else
               if(price==srl[i])   sr_long_gap_count++;
         }

      }
      
      if(supports == 0) 
      {
         sr_short_gap_count++;
         short_gap_count++;
      }
      
      if(resistances == 0) 
      {
         sr_long_gap_count++;
         long_gap_count++;
      }

      if(c >= NSVR) Print("Warning: NSVR exceeded");
      else  // hide the unused vertical lines objects so they wont be left as 'ghosts' (only the first)
      {
         objName = uniqueid + "svr_" + tf + "_" + (c+1);
            ObjectSet(objName, OBJPROP_TIME1, 0);
            ObjectSet(objName, OBJPROP_TIME2, 0);
            ObjectSet(objName, OBJPROP_PRICE1, 0);
            ObjectSet(objName, OBJPROP_PRICE2, 0);
      }
   }
   
return(0);
}

