//-------------------------------------------------------+
//                                Hma alerts current.mq4 |
//-------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 clrBlack
#property indicator_color2 clrWhite
#property indicator_width1 5
#property indicator_width2 5

extern ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;
extern int    HMAPeriod    = 34;
extern double HMADivisor   = 3;
extern bool   ShowLines    = false;
extern int    ShowLineBars = 5000;
extern color  BuyLine      = clrBlack;
extern color  SellLine     = clrWhite;
extern int    LinesWidth   = 1;
extern ENUM_LINE_STYLE LinesStyle = STYLE_DASH;
extern string SignalsName  ="Hma lines";
extern bool   AlertsOn     = false;
extern bool   AlertsMesage = true;
extern bool   AlertsSound  = false;
extern bool   AlertsEmail  = false;

double hma[],hmaDn[],arrup[],arrdwn[];
string indicatorFileName;
bool   returnBars;
int    maxArrows;

//------------------------------------------------------------------

int init()
{
   IndicatorBuffers(4);
   SetIndexBuffer(0,hma);  SetIndexLabel(0,"Hma up");
   SetIndexBuffer(1,hmaDn);SetIndexLabel(1,"Hma down");
   SetIndexBuffer(2,arrup);
   SetIndexBuffer(3,arrdwn);
   indicatorFileName = WindowExpertName();
   returnBars        = TimeFrame==-99;
   TimeFrame         = MathMax(TimeFrame,_Period);
   IndicatorShortName(timeFrameToString(TimeFrame)+" Hma alerts current ("+HMAPeriod+","+HMADivisor+")");
   return(0);
}

//--------------------------
int deinit() {DeleteArrows();return(0);}
//--------------------------

int start()
{
   int counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
   int limit=MathMin(Bars-counted_bars,Bars-1);
   if (returnBars) { hma[0] = MathMin(limit+1,Bars-1); return(0); }

   if (TimeFrame == Period())
      {
        for(int i=limit; i>=0; i--)
            {
               hma[i]=iHull(iMA(NULL,0,1,0,MODE_SMA,0,i),HMAPeriod,HMADivisor,i,0);
               if (hma[i]<hma[i+1]) hmaDn[i]=hma[i]; else hmaDn[i]=EMPTY_VALUE;
               
               if (hmaDn[i]== EMPTY_VALUE && hmaDn[i+1]!=EMPTY_VALUE) arrup[i] =1; else arrup[i] =EMPTY_VALUE;
               if (hmaDn[i]!= EMPTY_VALUE && hmaDn[i+1]==EMPTY_VALUE) arrdwn[i]=1; else arrdwn[i]=EMPTY_VALUE;
               //if (Close[i]>hma[i] && Close[i+1]<hma[i+1]) arrup[i] =1; else arrup[i] =EMPTY_VALUE;
               //if (Close[i]<hma[i] && Close[i+1]>hma[i+1]) arrdwn[i]=1; else arrdwn[i]=EMPTY_VALUE;
            }
         
        if (AlertsOn)
            {
               if (arrup[1]  != EMPTY_VALUE) doAlert("BUY Signal @ ");
               if (arrdwn[1] != EMPTY_VALUE) doAlert("SELL Signal @ ");
               //if (Close[0]>hma[0] && Close[1]<hma[1]) doAlert(" BUY cruce precio @ ");
               //if (Close[0]<hma[0] && Close[1]>hma[1]) doAlert(" SELL cruce precio @ ");
            }
            
        if (ShowLines)
            {
              DeleteArrows();
              for (i=0; i<ShowLineBars ;i++)
               {
                  if (arrup[i]  != EMPTY_VALUE) DrawArrow(i,"up");
                  if (arrdwn[i] != EMPTY_VALUE) DrawArrow(i,"down");
               }
            }            
            
       return(0);
      }

//------------------- Multitimeframe period ------------------------------------
  
   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/Period()));
   for (i=limit; i>=0; i--)
      {
         int y = iBarShift(NULL,TimeFrame,Time[i]);
         hma[i]   = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,HMAPeriod,HMADivisor,0,y);
         hmaDn[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,HMAPeriod,HMADivisor,1,y);
      }   
   return(0);
}

//------------------------------------------------------------------

double workHull[][4];
double iHull(double price, double period, double divisor, int r, int instanceNo=0)
{
   if (ArrayRange(workHull,0)!= Bars) ArrayResize(workHull,Bars); r=Bars-r-1;
   int HmaPeriod  = MathMax(period,2);
   int HalfPeriod = MathFloor(HmaPeriod/divisor);
   int HullPeriod = MathFloor(MathSqrt(HmaPeriod));
   double thma,hmw,weight; instanceNo *= 2;
   workHull[r][instanceNo] = price;
               
         hmw = HalfPeriod; thma = hmw*price; 
         for(int k=1; k<HalfPeriod && (r-k)>=0; k++)
            {
               weight = HalfPeriod-k;
               hmw   += weight;
               thma  += weight*workHull[r-k][instanceNo];  
            }             
   workHull[r][instanceNo+1] = 2.0*thma/hmw;

         hmw = HmaPeriod; thma = hmw*price; 
         for(k=1; k<period && (r-k)>=0; k++)
            {
               weight = HmaPeriod-k;
               hmw   += weight;
               thma  += weight*workHull[r-k][instanceNo];
            }             
   workHull[r][instanceNo+1] -= thma/hmw;
         
         hmw = HullPeriod; thma = hmw*workHull[r][instanceNo+1];
         for(k=1; k<HullPeriod && (r-k)>=0; k++)
            {
               weight = HullPeriod-k;
               hmw   += weight;
               thma  += weight*workHull[r-k][1+instanceNo];  
            }
            
   return(thma/hmw);
}

//+-------------------------------------------------------------------

void DrawArrow(int i,string type)
{
   maxArrows++;
      string name  = StringConcatenate(SignalsName,maxArrows);
         
      ObjectCreate(name,OBJ_VLINE,0,Time[i],0);
      if (type=="up")
         {
            ObjectSet(name,OBJPROP_STYLE,LinesStyle);    
            ObjectSet(name,OBJPROP_WIDTH,LinesWidth);    
            ObjectSet(name,OBJPROP_COLOR,BuyLine);
         }
      else if (type=="down")
         {
            ObjectSet(name,OBJPROP_STYLE,LinesStyle);
            ObjectSet(name,OBJPROP_WIDTH,LinesWidth);
            ObjectSet(name,OBJPROP_COLOR,SellLine);
         }
}

//-------------------------------------------------------------------

void DeleteArrows() {while(maxArrows>0) { ObjectDelete(StringConcatenate(SignalsName,maxArrows));maxArrows--;}}

//-------------------------------------------------------------

void doAlert(string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
   if (previousAlert != doWhat || previousTime != Time[0]) 
      {
         previousAlert  = doWhat;
         previousTime   = Time[0];
         message = timeFrameToString(TimeFrame)+" Hma alerts "+Symbol()+doWhat+DoubleToStr(Close[0],Digits);
         if (AlertsMesage) Alert(message);
         if (AlertsSound)  PlaySound("alert2.wav");
         if (AlertsEmail)  SendMail(StringConcatenate(Symbol()," Hma alerts "),message);
      }
}

//-------------------------------------------------------------------

string sTfTable[] = {"M1","M2","M3","M5","M10","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,2,3,5,10,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("");
}

//--------------------------------------------------------------------
