//+------------------------------------------------------------------+
//| Alligator_Histogram.mq4                                          |
//| Converted to histogram version                                   |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Converted by Grok"
#property link ""
#property description "Alligator as Histogram in subwindow with three colors"
#property strict

#property indicator_separate_window
#property indicator_buffers 7
#property indicator_color1 DodgerBlue
#property indicator_color2 Magenta
#property indicator_color3 Gray
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2
#property indicator_minimum 0
#property indicator_maximum 2

//---- input parameters
extern ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT; // Time frame
extern int InpJawsPeriod=13; // Jaws Period
extern int InpJawsShift=8; // Jaws Shift
extern int InpTeethPeriod=8; // Teeth Period
extern int InpTeethShift=5; // Teeth Shift
extern int InpLipsPeriod=5; // Lips Period
extern int InpLipsShift=3; // Lips Shift
extern bool Use_Price_Above_Below = true; // Price Above Alligator lines
extern bool Use_Lines_In_Order = true; // Price Above alligator lines and in order

//---- indicator buffers
double UpBuffer[];
double DownBuffer[];
double GrayBuffer[];
double JawsBuffer[];
double TeethBuffer[];
double LipsBuffer[];
double count[];

string indicatorFileName;
#define _mtfCall(_buff,_y) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,InpJawsPeriod,InpJawsShift,InpTeethPeriod,InpTeethShift,InpLipsPeriod,InpLipsShift,Use_Price_Above_Below,Use_Lines_In_Order,_buff,_y)

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   IndicatorBuffers(7);

   //---- drawing settings
   SetIndexStyle(0,DRAW_HISTOGRAM,EMPTY,2);
   SetIndexBuffer(0,UpBuffer);
   SetIndexLabel(0,"UP");

   SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,2);
   SetIndexBuffer(1,DownBuffer);
   SetIndexLabel(1,"Down");

   SetIndexStyle(2,DRAW_HISTOGRAM,EMPTY,2);
   SetIndexBuffer(2,GrayBuffer);
   SetIndexLabel(2,"In between");

   SetIndexBuffer(3,JawsBuffer);
   SetIndexBuffer(4,TeethBuffer);
   SetIndexBuffer(5,LipsBuffer);
   SetIndexBuffer(6,count);

   //---- first positions skipped when drawing
   int draw_begin = MathMax(MathMax(InpJawsPeriod + InpJawsShift, InpTeethPeriod + InpTeethShift), InpLipsPeriod + InpLipsShift);
   SetIndexDrawBegin(0,draw_begin);
   SetIndexDrawBegin(1,draw_begin);
   SetIndexDrawBegin(2,draw_begin);

   indicatorFileName = WindowExpertName();
   TimeFrame = MathMax(TimeFrame,_Period);

   IndicatorShortName(timeFrameToString(TimeFrame)+" Alligator Histogram");

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   int i = rates_total - prev_calculated;
   if (prev_calculated > 0) i++;
   if (i >= rates_total) i = rates_total - 1;
   count[0] = i;

   if (TimeFrame != _Period)
     {
      i = (int)MathMax(i,MathMin(rates_total-1,_mtfCall(6,0)*TimeFrame/_Period));
      for (; i >= 0; i--)
        {
         if (IsStopped()) break;
         int y = iBarShift(NULL,TimeFrame,time[i]);
         UpBuffer[i]   = _mtfCall(0,y);
         DownBuffer[i] = _mtfCall(1,y);
         GrayBuffer[i] = _mtfCall(2,y);
        }
      return(rates_total);
     }

   //---- calculate MA buffers
   for (; i >= 0; i--)
     {
      if (IsStopped()) break;
      JawsBuffer[i] = iMA(NULL,0,InpJawsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
      TeethBuffer[i] = iMA(NULL,0,InpTeethPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
      LipsBuffer[i] = iMA(NULL,0,InpLipsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
     }

   //---- calculate histogram
   int max_shift = MathMax(MathMax(InpJawsShift, InpTeethShift), InpLipsShift);
   i = rates_total - prev_calculated;
   if (prev_calculated > 0) i++;
   if (i >= rates_total) i = rates_total - 1;
   for (; i >= 0; i--)
     {
      if (IsStopped()) break;
      UpBuffer[i] = EMPTY_VALUE;
      DownBuffer[i] = EMPTY_VALUE;
      GrayBuffer[i] = EMPTY_VALUE;

      if(i + max_shift >= rates_total) continue;

      double jaws = JawsBuffer[i + InpJawsShift];
      double teeth = TeethBuffer[i + InpTeethShift];
      double lips = LipsBuffer[i + InpLipsShift];

      if(jaws == EMPTY_VALUE || teeth == EMPTY_VALUE || lips == EMPTY_VALUE || jaws == 0 || teeth == 0 || lips == 0) continue;

      double price_med = (high[i] + low[i]) / 2.0;

      bool above_all = price_med > MathMax(jaws, MathMax(teeth, lips));
      bool below_all = price_med < MathMin(jaws, MathMin(teeth, lips));

      bool bull_order = lips > teeth && teeth > jaws;
      bool bear_order = lips < teeth && teeth < jaws;

      bool is_up = (Use_Price_Above_Below ? above_all : true) && (Use_Lines_In_Order ? bull_order : true);
      bool is_down = (Use_Price_Above_Below ? below_all : true) && (Use_Lines_In_Order ? bear_order : true);

      if(is_up && !is_down)
        {
         UpBuffer[i] = 1.0;
        }
      else if(is_down && !is_up)
        {
         DownBuffer[i] = 1.0;
        }
      else
        {
         GrayBuffer[i] = 1.0;
        }
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+
//
//+------------------------------------------------------------------+

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
  {
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
      if (tf==iTfTable[i]) return(sTfTable[i]);
   return("");
  }
//+------------------------------------------------------------------+