
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "www,forex-station.com"
#property link      "www,forex-station.com"

#property indicator_separate_window
#property indicator_buffers 2
#property strict

//
//
//

extern ENUM_TIMEFRAMES   TimeFrame        = PERIOD_CURRENT;    // Time frame
input int                FastMaPeriod     = 3;                 // Fast moving average period
input ENUM_MA_METHOD     FastMaMethod     = MODE_SMMA;         // Fast moving average method
input ENUM_APPLIED_PRICE FastMaPrice      = PRICE_CLOSE;       // Fast moving average price
input int                FastMaShift      = 0;                 // Fast ma shift
input int                SlowMaPeriod     = 80;                // Slow moving average period
input ENUM_MA_METHOD     SlowMaMethod     = MODE_EMA;          // Slow moving average method
input ENUM_APPLIED_PRICE SlowMaPrice      = PRICE_CLOSE;       // Slow moving average price
input int                SlowMaShift      = 0;                 // Slow ma shift
input int                HistoWidth       = 3;                 // Histogram bars width
input color              UpHistoColor     = clrLimeGreen;      // Bullish color
input color              DnHistoColor     = clrRed;            // Bearish color
input bool               alertsOn         = true;              // Alerts true/false?
input bool               alertsOnCurrent  = false;             // Alerts open bar true/false?
input bool               alertsMessage    = true;              // Alerts message true/false?
input bool               alertsSound      = true;              // Alerts sound true/false?
input bool               alertsNotify     = false;             // Alerts notification true/false?
input bool               alertsEmail      = false;             // Alerts email true/false?
input string             soundfile        = "alert2.wav";      // Sound file to use

double UpH[],DnH[],valc[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,FastMaPeriod,FastMaMethod,FastMaPrice,FastMaShift,SlowMaPeriod,SlowMaMethod,SlowMaPrice,SlowMaShift,HistoWidth,UpHistoColor,DnHistoColor,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsNotify,alertsEmail,soundfile,_buff,_ind)

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

int OnInit()
{
   IndicatorBuffers(4);   
   SetIndexBuffer(0,UpH,INDICATOR_DATA); SetIndexStyle(0,DRAW_HISTOGRAM,EMPTY,HistoWidth,UpHistoColor);
   SetIndexBuffer(1,DnH,INDICATOR_DATA); SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,HistoWidth,DnHistoColor);   
   SetIndexBuffer(2,valc);
   SetIndexBuffer(3,count);
   
   IndicatorSetDouble(INDICATOR_MINIMUM,0);
   IndicatorSetDouble(INDICATOR_MAXIMUM,1);
   
   indicatorFileName = WindowExpertName();
   TimeFrame         = MathMax(TimeFrame,_Period);
    SetIndexShift(0,FastMaShift*TimeFrame/_Period);
    SetIndexShift(1,SlowMaShift*TimeFrame/_Period);
     
   IndicatorSetString(INDICATOR_SHORTNAME,timeFrameToString(TimeFrame)+" Ma cross");
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,r,limit=fmin(rates_total-prev_calculated+1,rates_total-1); count[0] = limit;
   if(FastMaShift<0) limit = fmax(limit,-FastMaShift);
   if(SlowMaShift<0) limit = fmax(limit,-SlowMaShift);
      if (TimeFrame!=_Period)
      {
         limit = (int)fmax(limit,fmin(rates_total-1,_mtfCall(3,0)*TimeFrame/_Period));
         for (i=limit; i>=0; i--)
         {
                  int y = iBarShift(NULL,TimeFrame,time[i]);
                     UpH[i] = _mtfCall(0,y);
                     DnH[i] = _mtfCall(1,y);
         }  
   return(rates_total);
   }            
   
   //
   //
   //
   
   struct maStruct
     {
        double fma;
        double sma;
     };
     static maStruct wrk[];
     static int        wrkSize = -1;
                   if (wrkSize<rates_total) wrkSize = ArrayResize(wrk,rates_total+500);
   
   //
   //
   //
   
   for(i=limit, r=rates_total-i-1; i>=0; i--,r++)
   {
      wrk[r].fma  = iMA(NULL,0,FastMaPeriod,FastMaShift,FastMaMethod,FastMaPrice,i);
      wrk[r].sma  = iMA(NULL,0,SlowMaPeriod,SlowMaShift,SlowMaMethod,SlowMaPrice,i);
      valc[i] = (r>0) ? (wrk[r].fma>wrk[r].sma) ? 1 : (wrk[r].fma<wrk[r].sma) ? -1 : valc[i+1] : 0;
      UpH[i] = (valc[i] == 1) ? 1 : EMPTY_VALUE;
      DnH[i] = (valc[i] ==-1) ? 1 : EMPTY_VALUE;             
   }
   manageAlerts();
return(rates_total);
}
      
//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void manageAlerts()
{
   if (alertsOn)
   {
      int whichBar = (alertsOnCurrent) ? 1 : 0; 
      if (valc[whichBar]!= valc[whichBar+1])
      {
         static datetime time1 = 0;
         static string   mess1 = "";
            if (valc[whichBar] == 1) doAlert(time1,mess1," up");
            if (valc[whichBar] ==-1) doAlert(time1,mess1," down");
      }
   }
}

//
//
//

void doAlert(datetime& previousTime, string& previousAlert, string doWhat)
{
   string message;
   
   if (previousAlert != doWhat || previousTime != Time[0]) {
       previousAlert  = doWhat;
       previousTime   = Time[0];

       //
       //
       //

       message = timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" Ma Cross "+doWhat;
          if (alertsMessage) Alert(message);
          if (alertsNotify)  SendNotification(message);
          if (alertsEmail)   SendMail(_Symbol+" Ma Cross ",message);
          if (alertsSound)   PlaySound(soundfile);
   }
}

//
//
//

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("");
}
