//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "www.forex-station.com"
#property link      "www.forex-station.com"

#property indicator_separate_window
#property indicator_buffers    7
#property indicator_color1     clrGreen
#property indicator_color2     clrRed
#property indicator_color3     clrLime
#property indicator_color4     clrOrange
#property indicator_color5     clrGray
#property indicator_color6     clrLimeGreen
#property indicator_color7     clrRed
#property indicator_width1     2
#property indicator_width2     2
#property indicator_levelcolor clrMediumOrchid
#property strict

//
//
//
//
//

extern ENUM_TIMEFRAMES TimeFrame        = PERIOD_CURRENT;   // Time frame
input int              Tenkan           = 12;               // Tenkan period
input int              Kijun            = 26;               // Kijun period
input bool             alertsOn         = true;             // Turn alerts on?
input bool             alertsOnCurrent  = false;            // Alerts on current (still opened) bar?
input bool             alertsMessage    = true;             // Alerts showing a pop-up message?
input bool             alertsPushNotif  = false;            // Alerts sending a push notification?
input bool             alertsSound      = false;            // Alerts playing sound?
input bool             alertsEmail      = false;            // Alerts sending email?
input string           soundFile        = "alert2.wav";     // Alerts Sound File to use
input bool             ArrowOnFirst     = false;            // Arrow on first mtf bar
input bool             Interpolate      = true;             // Interpolate in multi time frame mode?

double huu[],hud[],hdd[],hdu[],ks[],ts[],val[],trend[],valc[],up[],dn[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Tenkan,Kijun,alertsOn,alertsOnCurrent,alertsMessage,alertsPushNotif,alertsSound,alertsEmail,soundFile,ArrowOnFirst,_buff,_ind)

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

int OnInit()
{
     IndicatorBuffers(12);
     SetIndexBuffer(0, huu,INDICATOR_DATA); SetIndexStyle(0,DRAW_HISTOGRAM);
     SetIndexBuffer(1, hdd,INDICATOR_DATA); SetIndexStyle(1,DRAW_HISTOGRAM);
     SetIndexBuffer(2, hud,INDICATOR_DATA); SetIndexStyle(2,DRAW_HISTOGRAM);
     SetIndexBuffer(3, hdu,INDICATOR_DATA); SetIndexStyle(3,DRAW_HISTOGRAM);
     SetIndexBuffer(4, val,INDICATOR_DATA); SetIndexStyle(4,DRAW_LINE);
     SetIndexBuffer(5, up, INDICATOR_DATA); SetIndexStyle(5,DRAW_ARROW); SetIndexArrow(5,233);
     SetIndexBuffer(6, dn, INDICATOR_DATA); SetIndexStyle(6,DRAW_ARROW); SetIndexArrow(6,234);
     SetIndexBuffer(7, ts);
     SetIndexBuffer(8, ks);  
     SetIndexBuffer(9, trend);
     SetIndexBuffer(10,valc);
     SetIndexBuffer(11,count);
     SetLevelValue(0,0); 
     
     indicatorFileName = WindowExpertName();
     TimeFrame         = fmax(TimeFrame,_Period);  
        
   IndicatorSetString(INDICATOR_SHORTNAME,timeFrameToString(TimeFrame)+"  Tenkan Sen - Kijun Sen Histo");
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) { }

//
//
//

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,limit=fmin(rates_total-prev_calculated+1,rates_total-1); count[0] = limit;
      if (TimeFrame!=_Period)
      {
         limit = (int)fmax(limit,fmin(rates_total-1,_mtfCall(11,0)*TimeFrame/_Period));
         for (i=limit;i>=0 && !_StopFlag; i--)
         {
            int y = iBarShift(NULL,TimeFrame,time[i]);
            int x = y;
            if (ArrowOnFirst)
                  {  if (i<rates_total-1) x = iBarShift(NULL,TimeFrame,time[i+1]);               }
            else  {  if (i>0)             x = iBarShift(NULL,TimeFrame,time[i-1]); else x = -1;  }
                      huu[i] = _mtfCall(0,y);
                      hdd[i] = _mtfCall(1,y);
                      hud[i] = _mtfCall(2,y);
                      hdu[i] = _mtfCall(3,y);
                      val[i] = _mtfCall(4,y);
                     if (x!=y)
                     {
                        up[i] = _mtfCall(5,y);
                        dn[i] = _mtfCall(6,y);
                     }
                     
                     if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,time[i-1]))) continue;
                  
                     //
                     //
                     //
                  
                     #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n
                     int n,k; datetime itime = iTime(NULL,TimeFrame,y);
                        for(n = 1; (i+n)<rates_total && time[i+n] >= itime; n++) continue;	
                        for(k = 1; k<n && (i+n)<rates_total && (i+k)<rates_total; k++) 
                        {
                          _interpolate(val);
                          if (huu[i]!= EMPTY_VALUE) huu[i+k] = val[i+k];
  	                       if (hdd[i]!= EMPTY_VALUE) hdd[i+k] = val[i+k];
  	                       if (hud[i]!= EMPTY_VALUE) hud[i+k] = val[i+k];
  	                       if (hdu[i]!= EMPTY_VALUE) hdu[i+k] = val[i+k];
                       }          
               }      
      return(rates_total);
      }    
      
      //
      //
      //
              
      for (i=limit;i>=0 && !_StopFlag; i--)
      {
          double tlo =  low[ArrayMinimum(low, Tenkan,i)];
          double thi = high[ArrayMaximum(high,Tenkan,i)];
          ts[i] = ((thi+tlo)!=0) ? (thi+tlo)*0.5 : 0;
         
          double klo =  low[ArrayMinimum(low, Kijun,i)];
          double khi = high[ArrayMaximum(high,Kijun,i)];
          ks[i]  = ((khi+klo)!=0) ? (khi+klo)*0.5 : 0;
          val[i] = ts[i] - ks[i]; 
         
          valc[i] = (i<rates_total-1) ? (val[i]>val[i+1]) ? 1 : (val[i]<val[i+1]) ? -1 : valc[i+1] : 0; 
          if (val[i]>0)
          if (valc[i]==1)
                huu[i] = val[i];
          else  hud[i] = val[i];
          if (val[i]<0)
          if (valc[i]==1)
                hdu[i] = val[i];
          else  hdd[i] = val[i]; 
           
      }
      for (i=limit; i>=0; i--)
      {
         up[i] = dn[i] = EMPTY_VALUE;
         trend[i] = (val[i]>0) ? 1 : (val[i]<0)    ? -1 : 0; 
         if (i<rates_total-1 && trend[i] !=trend[i+1])
         {  
            if (trend[i] == 1) up[i] = val[i]-iStdDevOnArray(val,0,10,0,MODE_SMA,i);
            if (trend[i] ==-1) dn[i] = val[i]+iStdDevOnArray(val,0,10,0,MODE_SMA,i); 
         }
   }
manageAlerts();
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("");
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------

void manageAlerts()
{
    if (alertsOn)
    {
      int whichBar = 1; if (alertsOnCurrent) whichBar = 0; 
      if (hdu[whichBar+1] == EMPTY_VALUE && hdu[whichBar] != EMPTY_VALUE) doAlert("weak buy");
      if (huu[whichBar+1] == EMPTY_VALUE && huu[whichBar] != EMPTY_VALUE) doAlert("strong buy");
      if (hud[whichBar+1] == EMPTY_VALUE && hud[whichBar] != EMPTY_VALUE) doAlert("weak sell");
      if (hdd[whichBar+1] == EMPTY_VALUE && hdd[whichBar] != EMPTY_VALUE) doAlert("strong sell");  
   }
}   

//
//
//

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(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" Tenkan Sen Kijun Sen Histo "+doWhat;
          if (alertsMessage)    Alert(message);
          if (alertsPushNotif)  SendNotification(message);
          if (alertsEmail)      SendMail(_Symbol+" Tenkan Sen Kijun Sen Histo ",message);
          if (alertsSound)      PlaySound(soundFile);
   }
}     
   
  
  