//+------------------------------------------------------------------+
//|                                                      VM_DHLC.mq4 |
//|                               Copyright © 2007, Victor Maranhão. |
//|                                              vmaranhao@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, Victor Maranhão."
#property link      "vmaranhao@gmail.com"

#property indicator_chart_window
#property indicator_buffers 5

#define cIX_BF_DBHLC   0
#define cIX_BF_PINUPDN 1
#define cIX_BF_IBS4    2
#define cIX_BF_IBOB    3
#define cIX_BF_TBHTBL  4

#define cIX_DBHLC 0
#define cIX_DBLHC 1
#define cIX_PINUP 2
#define cIX_PINDN 3
#define cIX_IBS4  4
#define cIX_IB    5
#define cIX_OB    6
#define cIX_TBH   7
#define cIX_TBL   8

extern bool  pDBHLC_Show        =      TRUE;
extern int   pDBHLC_Max_Delta   =         0;  // pip
extern color pDBHLC_Color       =    Yellow;
extern int   pDBHLC_Width       =         2; 
extern bool  pDBLHC_Show        =      TRUE;
extern int   pDBLHC_Max_Delta   =         0;  // pip
extern bool  pPINUP_Show        =      TRUE;
extern int   pPINUP_Min_Delta   =         5;  // pip
extern int   pPINUP_Top_Precent =        10;  // percent
extern color pPINUP_Color       =      Gold;
extern int   pPINUP_Width       =         2; 
extern bool  pPINDN_Show        =      TRUE;
extern int   pPINDN_Min_Delta   =         5;  // pip
extern int   pPINDN_Top_Precent =        10;  // percent
extern bool  pIBS4_Show         =      TRUE;
extern int   pIBS4_Min_Delta    =         0;  // pip
extern color pIBS4_Color        = OrangeRed;
extern int   pIBS4_Width        =         2; 
extern bool  pIB_Show           =      TRUE;
extern int   pIB_Min_Delta      =         0;  // pip
extern color pIB_Color          =      Aqua;
extern int   pIB_Width          =         2; 
extern bool  pOB_Show           =      TRUE;
extern int   pOB_Min_Delta      =         0;  // pip
extern bool  pTBH_Show          =      TRUE;
extern int   pTBH_Max_Delta     =         0;  // pip
extern color pTBH_Color         =     White;
extern int   pTBH_Width         =         2; 
extern bool  pTBL_Show          =      TRUE;
extern int   pTBL_Max_Delta     =         0;  // pip
extern bool  pShow_Stats        =      TRUE;


double buffDBHLC  [];
double buffIBS4   [];
double buffIBOB   [];
double buffTBHTBL [];
double buffPINUPDN[];
double buffer7[];

static string lblName [9] = { "VMPA0","VMPA1","VMPA2","VMPA3","VMPA4","VMPA5","VMPA6","VMPA7","VMPA8" };
static string lblText [9];
static color  lblColor[9];
static bool   lblShow [9];
static int    lblCount[9];
static string alrtText[9];

static double gDistArrow = 20;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

int init()

  {

   string title = "Price Action 1";
   
   IndicatorBuffers(5);
   
   IndicatorShortName(title);

   SetIndexBuffer    (cIX_BF_IBOB   , buffIBOB   );
   SetIndexBuffer    (cIX_BF_IBS4   , buffIBS4   );
   SetIndexBuffer    (cIX_BF_DBHLC  , buffDBHLC  );
   SetIndexBuffer    (cIX_BF_TBHTBL , buffTBHTBL );
   SetIndexBuffer    (cIX_BF_PINUPDN, buffPINUPDN);
 
   SetIndexStyle     (cIX_BF_IBOB   , DRAW_ARROW, EMPTY, pIB_Width   , pIB_Color   );
   SetIndexStyle     (cIX_BF_IBS4   , DRAW_ARROW, EMPTY, pIBS4_Width , pIBS4_Color );
   SetIndexStyle     (cIX_BF_DBHLC  , DRAW_ARROW, EMPTY, pDBHLC_Width, pDBHLC_Color);
   SetIndexStyle     (cIX_BF_TBHTBL , DRAW_ARROW, EMPTY, pTBH_Width  , pTBH_Color  );
   SetIndexStyle     (cIX_BF_PINUPDN, DRAW_ARROW, EMPTY, pPINUP_Width, pPINUP_Color);

   SetIndexArrow     (cIX_BF_IBOB   , 171);
   SetIndexArrow     (cIX_BF_IBS4   , 171);
   SetIndexArrow     (cIX_BF_DBHLC  , 171);
   SetIndexArrow     (cIX_BF_TBHTBL , 171);
   SetIndexArrow     (cIX_BF_PINUPDN, 171);
 
   SetIndexLabel     (cIX_BF_IBOB   , "Inside / Outside Bar"    );
   SetIndexLabel     (cIX_BF_IBS4   , "Inside Bar Smallest of 4");
   SetIndexLabel     (cIX_BF_DBHLC  , "DBHLC / DBLHC"           );
   SetIndexLabel     (cIX_BF_TBHTBL , "Two Bars High / Low"     );
   SetIndexLabel     (cIX_BF_PINUPDN, "PIN Up / Down"           );
 
   SetIndexDrawBegin (cIX_BF_IBOB   , 1);
   SetIndexDrawBegin (cIX_BF_IBS4   , 3);
   SetIndexDrawBegin (cIX_BF_DBHLC  , 1);
   SetIndexDrawBegin (cIX_BF_TBHTBL , 1);
   SetIndexDrawBegin (cIX_BF_PINUPDN, 1);
   
   gDistArrow = gDistArrow  * Point;

   Set_Label_Objects_Alerts();

   return(0);

  }

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

int deinit()

  {
  
   for (int ix = 0; ix < 9; ix++)
     ObjectDelete(lblName[ix]);
   
  }
  
//+------------------------------------------------------------------+
//| Start
//+------------------------------------------------------------------+

int start()
  {
  
          int      limit;
          int      found;
          int      countedBars = IndicatorCounted();
   static bool     gFirstTime  = TRUE;
   static datetime prevTime    = 0;
   static double   deltaDHLC   = 0;
   static double   deltaDLHC   = 0;
   static double   deltaPINUP  = 0;
   static double   deltaPINDN  = 0;
   static double   deltaIBS4   = 0;
   static double   deltaIB     = 0;
   static double   deltaOB     = 0;
   static double   deltaTBH    = 0;
   static double   deltaTBL    = 0;
   
   if (prevTime == iTime(NULL,0,0)) return (0);
   
   prevTime = iTime(NULL,0,0);
           
   if (countedBars > 0) countedBars--; 
   
   limit = Bars - countedBars;

   if (gFirstTime) 
     {
      Define_Min_PIN (deltaPINUP, deltaPINDN);
      deltaDHLC = pDBHLC_Max_Delta * Point;
      deltaDLHC = pDBLHC_Max_Delta * Point;
      deltaIBS4 = pIBS4_Min_Delta  * Point;
      deltaIB   = pIB_Min_Delta    * Point;
      deltaOB   = pOB_Min_Delta    * Point;
      deltaTBH  = pTBH_Max_Delta   * Point;
      deltaTBL  = pTBL_Max_Delta   * Point;
     }

   
   for (int ix1 = 0; ix1 < limit; ix1++)
     {
      found = -1;
      if (                  pDBHLC_Show ) found = Find_DBHLC (ix1, deltaDHLC );
      if ((found == -1) && (pDBLHC_Show)) found = Find_DBLHC (ix1, deltaDLHC );
      if ((found == -1) && (pPINUP_Show)) found = Find_PINUp (ix1, deltaPINUP);
      if ((found == -1) && (pPINDN_Show)) found = Find_PINDn (ix1, deltaPINDN);
      if ((found == -1) && (pIBS4_Show )) found = Find_IBS4  (ix1, deltaIBS4 );
      if ((found == -1) && (pIB_Show   )) found = Find_IB    (ix1, deltaIB   );
      if ((found == -1) && (pOB_Show   )) found = Find_OB    (ix1, deltaOB   );
      if ((found == -1) && (pTBH_Show  )) found = Find_TBH   (ix1, deltaTBH  );
      if ((found == -1) && (pTBL_Show  )) found = Find_TBL   (ix1, deltaTBL  );
      if  (found != -1) lblCount[found]++;
      if  (gFirstTime ) continue;
      if  (found != -1) Alert(Symbol()," (",Period(),") ", alrtText[found]);
     }

   Set_Labels();
     
   gFirstTime = FALSE;
   
   return(0);

  }

//+------------------------------------------------------------------+
//+  Find Double High, Lower Close
//+------------------------------------------------------------------+

int Find_DBHLC(int ix1, double delta)

  {

   double dif;
   
   dif = MathAbs(iHigh (NULL,0,ix1) - iHigh(NULL,0,ix1+1));
   
   if (dif > delta) return (-1);

   if (iClose(NULL,0,ix1) >= iLow(NULL,0,ix1+1)) return (-1);
   
   buffDBHLC[ix1] = iHigh(NULL,0,ix1) + gDistArrow;

   return (cIX_DBHLC);
   
  }

//+------------------------------------------------------------------+
//+  Find Double Low, Higher Close
//+------------------------------------------------------------------+

int Find_DBLHC(int ix1, double delta)

  {

   double dif;
   
   dif = MathAbs(iLow (NULL,0,ix1) - iLow(NULL,0,ix1+1));

   if (dif > delta) return (-1);

   if (iClose(NULL,0,ix1) <= iHigh(NULL,0,ix1+1)) return (-1);

   buffDBHLC[ix1] = iLow(NULL,0,ix1) - gDistArrow;

   return (cIX_DBLHC);
   
  }

//+------------------------------------------------------------------+
//+  Find PIN Up
//+------------------------------------------------------------------+

int Find_PINUp (int ix1, double delta)

  {

   if (iOpen (NULL,0,ix1) > iHigh(NULL,0,ix1+1)        ) return (-1);
   if (iOpen (NULL,0,ix1) < iLow (NULL,0,ix1+1)        ) return (-1);
   if (iClose(NULL,0,ix1) > iHigh(NULL,0,ix1+1)        ) return (-1);
   if (iClose(NULL,0,ix1) < iLow (NULL,0,ix1+1)        ) return (-1);
   if (iLow  (NULL,0,ix1) < iLow (NULL,0,ix1+1)        ) return (-1);
   if (iHigh (NULL,0,ix1) < iHigh(NULL,0,ix1+1) + delta) return (-1);
   
   buffPINUPDN[ix1] = iHigh(NULL,0,ix1) + gDistArrow;
   
   return (cIX_PINUP);
   
  }

//+------------------------------------------------------------------+
//+  Find PIN Up
//+------------------------------------------------------------------+

int Find_PINDn(int ix1, double delta)

  {

   if (iOpen (NULL,0,ix1) > iHigh(NULL,0,ix1+1)        ) return (-1);
   if (iOpen (NULL,0,ix1) < iLow (NULL,0,ix1+1)        ) return (-1);
   if (iClose(NULL,0,ix1) > iHigh(NULL,0,ix1+1)        ) return (-1);
   if (iClose(NULL,0,ix1) < iLow (NULL,0,ix1+1)        ) return (-1);
   if (iHigh (NULL,0,ix1) > iHigh(NULL,0,ix1+1)        ) return (-1);
   if (iLow  (NULL,0,ix1) > iLow (NULL,0,ix1+1) - delta) return (-1);
   
   buffPINUPDN[ix1] = iLow(NULL,0,ix1) - gDistArrow;
   
   return (cIX_PINDN);
   
  }

//+------------------------------------------------------------------+
//+  Find Inside Bar, Smallest of 4
//+------------------------------------------------------------------+
  
int Find_IBS4(int ix1, double delta)
  
  {
   
   double range = iHigh(NULL,0,ix1) - iLow(NULL,0,ix1) + delta;
   
   if (range > iHigh(NULL,0,ix1+3) - iLow(NULL,0,ix1+3)) return (-1);
    
   if (range > iHigh(NULL,0,ix1+2) - iLow(NULL,0,ix1+2)) return (-1);

   if (range > iHigh(NULL,0,ix1+1) - iLow(NULL,0,ix1+1)) return (-1);

   if (iHigh(NULL,0,ix1) > iHigh(NULL,0,ix1+1)) return (-1);

   if (iLow (NULL,0,ix1) < iLow (NULL,0,ix1+1)) return (-1);
   
   buffIBS4[ix1] = iHigh(NULL,0,ix1) + gDistArrow;
   
   return (cIX_IBS4);
   
  }
  
//+------------------------------------------------------------------+
//+  Find Inside Bar
//+------------------------------------------------------------------+
  
int Find_IB(int ix1, double delta)
  
  {
   
   if (iHigh(NULL,0,ix1) + delta >= iHigh(NULL,0,ix1+1)) return (-1);
   
   if (iLow (NULL,0,ix1) - delta <= iLow (NULL,0,ix1+1)) return (-1);
    
   buffIBOB[ix1] = iHigh(NULL,0,ix1) + gDistArrow;
   
   return (cIX_IB);
   
  }
  
//+------------------------------------------------------------------+
//+  Find Outside Bar
//+------------------------------------------------------------------+
  
int Find_OB(int ix1, double delta)
  
  {
   
   if (iHigh(NULL,0,ix1) + delta <= iHigh(NULL,0,ix1+1)) return (-1);
   
   if (iLow (NULL,0,ix1) - delta >= iLow (NULL,0,ix1+1)) return (-1);
    
   buffIBOB[ix1] = iLow(NULL,0,ix1) - gDistArrow;
   
   return (cIX_OB);
   
  }
  
//+------------------------------------------------------------------+
//+  Find Two Bars High
//+------------------------------------------------------------------+
  
int Find_TBH(int ix1, double delta)
  
  {
   
   double dif;
   
   dif = MathAbs(iHigh(NULL,0,ix1) - iHigh(NULL,0,ix1+1));

   if (dif > delta) return (-1);
    
   buffTBHTBL[ix1] = iHigh(NULL,0,ix1) + gDistArrow;
   
   return (cIX_TBH);
   
  }
  
//+------------------------------------------------------------------+
//+  Find Two Bars Low
//+------------------------------------------------------------------+
  
int Find_TBL(int ix1, double delta)
  
  {
   
   double dif;
   
   dif = MathAbs(iLow(NULL,0,ix1) - iLow(NULL,0,ix1+1));

   if (dif > delta) return (-1);
    
   buffTBHTBL[ix1] = iLow(NULL,0,ix1) - gDistArrow;
   
   return (cIX_TBL);
   
  }
  
//+------------------------------------------------------------------+
//+  Define Minimum PIN Up and Down
//+------------------------------------------------------------------+
  
void Define_Min_PIN(double& resultUp, double& resultDn)
  
  {
   int    contUp[500];
   int    contDn[500];
   int    contaUp;
   int    contaDn;
   int    totalUp;
   int    totalDn;
   double deltaUp = pPINUP_Min_Delta * Point;
   double deltaDn = pPINDN_Min_Delta * Point;
   int    fator = MathPow(10,Digits);
   int    contIx;
   int    limit;
   int    countedBars = IndicatorCounted();
    
   ArrayInitialize(contUp,0);
   
   limit = Bars - countedBars;
   
   for (int ix1 = 0; ix1 < limit; ix1++)
     { 
      if (iOpen (NULL,0,ix1) > iHigh(NULL,0,ix1+1)) continue;
      if (iOpen (NULL,0,ix1) < iLow (NULL,0,ix1+1)) continue;
      if (iClose(NULL,0,ix1) > iHigh(NULL,0,ix1+1)) continue;
      if (iClose(NULL,0,ix1) < iLow (NULL,0,ix1+1)) continue;
      
      if ((iLow  (NULL,0,ix1) >= iLow (NULL,0,ix1+1)) &&
          (iHigh (NULL,0,ix1) >= iHigh(NULL,0,ix1+1) + deltaUp))
        {
         contIx = (iHigh(NULL,0,ix1)-iHigh(NULL,0,ix1+1)) * fator;
         contUp[contIx]++;
         totalUp++;
         continue;
        }
       
      if ((iHigh(NULL,0,ix1) <= iHigh(NULL,0,ix1+1)) &&
          (iLow (NULL,0,ix1) <= iLow (NULL,0,ix1+1) - deltaDn))
        {
         contIx = (iLow(NULL,0,ix1+1)-iLow(NULL,0,ix1)) * fator;
         contDn[contIx]++;
         totalDn++;
        }
     } 

   totalUp = (totalUp / 100) * pPINUP_Top_Precent;
   totalDn = (totalDn / 100) * pPINDN_Top_Precent;
   
   for (int ix2 = ArrayRange(contUp,0); ix2 >= 0; ix2--)
     {
      contaUp = contaUp + contUp[ix2];
      if (contaUp >= totalUp)
        {
         resultUp = ix2 * Point;
         break;
        }
      }
   
   for (int ix3 = ArrayRange(contDn,0); ix3 >= 0; ix3--)
     {
      contaDn = contaDn + contDn[ix3];
      if (contaDn >= totalDn)
        {
         resultDn = ix3 * Point;
         break;
        }
      }

  }

//+------------------------------------------------------------------+
//+  Set Labels
//+------------------------------------------------------------------+

void Set_Labels ()

  {
   
   string txt;
   
   for (int ix = 0; ix < 9; ix++)
     if (lblShow[ix])
       {
        txt = lblText[ix] + lblCount[ix] + ")";
        ObjectSetText(lblName[ix],txt,9,"Verdana",lblColor[ix]);
       }

    
  }
  
//+------------------------------------------------------------------+
//+  Set Label Objects and Alert Texts
//+------------------------------------------------------------------+

void Set_Label_Objects_Alerts()

  {
  
   int ix;
   int dst;
   
   for (ix = 0; ix < 9; ix++)
     ObjectDelete(lblName[ix]);
     
   if (!pShow_Stats) return;
   
   lblShow[cIX_DBHLC] = pDBHLC_Show;
   lblShow[cIX_DBLHC] = pDBLHC_Show;
   lblShow[cIX_PINUP] = pPINUP_Show;
   lblShow[cIX_PINDN] = pPINDN_Show;
   lblShow[cIX_IBS4 ] = pIBS4_Show;
   lblShow[cIX_IB   ] = pIB_Show;
   lblShow[cIX_OB   ] = pOB_Show;
   lblShow[cIX_TBH  ] = pTBH_Show;
   lblShow[cIX_TBL  ] = pTBL_Show;

   lblColor[cIX_DBHLC] = pDBHLC_Color;
   lblColor[cIX_DBLHC] = pDBHLC_Color;
   lblColor[cIX_PINUP] = pPINUP_Color;
   lblColor[cIX_PINDN] = pPINUP_Color;
   lblColor[cIX_IBS4 ] = pIBS4_Color;
   lblColor[cIX_IB   ] = pIB_Color;
   lblColor[cIX_OB   ] = pIB_Color;
   lblColor[cIX_TBH  ] = pTBH_Color;
   lblColor[cIX_TBL  ] = pTBH_Color;

   lblText[cIX_DBHLC] = "DBHLC (";
   lblText[cIX_DBLHC] = "DBLHC (";
   lblText[cIX_PINUP] = "Pin Up (";
   lblText[cIX_PINDN] = "Pin Dn (";
   lblText[cIX_IBS4 ] = "IBS4 (";
   lblText[cIX_IB   ] = "IB (";
   lblText[cIX_OB   ] = "OB (";
   lblText[cIX_TBH  ] = "TBH (";
   lblText[cIX_TBL  ] = "TBL (";

   alrtText[cIX_DBHLC] = " Double Bars High Lower Close.";
   alrtText[cIX_DBLHC] = " Double Bars Low Higher Close.";
   alrtText[cIX_PINUP] = " Pin Up.";
   alrtText[cIX_PINDN] = " Pin Dn.";
   alrtText[cIX_IBS4 ] = " Inside Bar Smallest of 4.";
   alrtText[cIX_IB   ] = " Inside Bar.";
   alrtText[cIX_OB   ] = " Outside Bar.";
   alrtText[cIX_TBH  ] = " Two Bar High.";
   alrtText[cIX_TBL  ] = " Two Bar low.";

   for (ix = 0; ix < 9; ix++)
     if (lblShow[ix])
       {
        dst = dst + 13;
        ObjectCreate (lblName[ix],OBJ_LABEL        ,  0,0,0);
        ObjectSet    (lblName[ix],OBJPROP_CORNER   ,  0);
        ObjectSet    (lblName[ix],OBJPROP_XDISTANCE, 10);
        ObjectSet    (lblName[ix],OBJPROP_YDISTANCE, dst);
        ObjectSetText(lblName[ix],lblText[ix],9,"Verdana",lblColor[ix]);
       }
     
   }