//+------------------------------------------------------------------+
//|                                                          WSI.mq4 |
//|                             Copyright (c) 2017, Gehtsoft USA LLC | 
//|                                            http://fxcodebase.com |
//|                                   Paypal: https://goo.gl/9Rj74e  | 
//+------------------------------------------------------------------+
//|                                      Developed by : Mario Jemic  |                    
//|                                          mario.jemic@gmail.com   |
//|                   BitCoin : 15VCJTLaz12Amr7adHSBtL9v8XomURo9RF   |
//+------------------------------------------------------------------+


#property indicator_separate_window
#property indicator_buffers    3
#property indicator_width1     2
#property indicator_color1     clrLime
#property indicator_width2     2
#property indicator_color2     clrRed
#property indicator_width3     2
#property indicator_color3     clrDarkSlateGray
#property indicator_levelcolor clrYellow
#property indicator_levelwidth 1
#property indicator_levelstyle STYLE_DOT
#property strict

extern ENUM_TIMEFRAMES TimeFrame        = PERIOD_CURRENT;   // Time frame to use
extern int             CCI_Period       = 100;              // Cci period
extern int             ADX_Period       = 100;              // Adx period
extern bool            arrowsVisible    = true;             // Arrows visible?
extern bool            arrowsOnFirst    = false;            // Arrows shift?
extern string          arrowsIdentifier = "wsi Arrows1";    // Unique ID for arrows
extern double          arrowsUpperGap   = 1.0;              // Upper arrow gap
extern double          arrowsLowerGap   = 1.0;              // Lower arrow gap
extern color           arrowsUpColor    = clrDeepSkyBlue;   // Up arrow color
extern color           arrowsDnColor    = clrPaleVioletRed; // Down arrow color
extern int             arrowsUpCode     = 139;              // Up arrow code
extern int             arrowsDnCode     = 139;              // Down arrow code
extern bool            alertsOn         = false;            // Turn alerts on?
extern bool            alertsOnCurrent  = false;            // Alerts on still opened bar?
extern bool            alertsMessage    = true;             // Alerts should display message?
extern bool            alertsSound      = false;            // Alerts should play a sound?
extern bool            alertsNotify     = false;            // Alerts should send a notification?
extern bool            alertsEmail      = false;            // Alerts should send an email?
extern string          soundFile        = "alert2.wav";     // Sound file
extern bool            Interpolate      = true;             // Interpolate in multi time frame mode?

double WSI[];
double Up[];
double Dn[];
double Price[];
double CCI[];
double ADX[];
double trend[];
double count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,CCI_Period,ADX_Period,arrowsVisible,arrowsOnFirst,arrowsIdentifier,arrowsUpperGap,arrowsLowerGap,arrowsUpColor,arrowsDnColor,arrowsUpCode,arrowsDnCode,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsNotify,alertsEmail,soundFile,_buff,_ind)

int init()
{
   IndicatorBuffers(8);
   SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(0,Up);
   SetIndexLabel(0,"WSI Up");
   SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(1,Dn);
   SetIndexLabel(1,"WSI Down");
   SetIndexBuffer(2,WSI);
   SetIndexBuffer(3,Price);
   SetIndexBuffer(4,CCI);
   SetIndexBuffer(5,ADX);
   SetIndexBuffer(6,trend);
   SetIndexBuffer(7,count);
   
   indicatorFileName = WindowExpertName();
   TimeFrame         = fmax(TimeFrame,_Period); 
   
   SetLevelValue(0,0);
   IndicatorShortName(timeFrameToString(TimeFrame)+" WSI");
   return(0);
}
int deinit()
{
   string lookFor       = arrowsIdentifier+":";
   int    lookForLength = StringLen(lookFor);
   for (int i=ObjectsTotal()-1; i>=0; i--)
   {
      string objectName = ObjectName(i);
         if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
   }
   return(0);
}


int start()
{  
  int i,counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = fmin(Bars-counted_bars,Bars-1); count[0]=limit;
            if (TimeFrame!=_Period)
            {
               limit = (int)fmax(limit,fmin(Bars-1,_mtfCall(7,0)*TimeFrame/_Period));
               for (i=limit;i>=0 && !_StopFlag; i--)
               {
                  int y = iBarShift(NULL,TimeFrame,Time[i]);
                     WSI [i]  = _mtfCall(2,y);
                     Up[i]    = EMPTY_VALUE;
                     Dn[i]    = EMPTY_VALUE;
                     trend[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 time = iTime(NULL,TimeFrame,y);
                         for(n = 1; (i+n)<Bars && Time[i+n] >= time; n++) continue;	
                         for(k = 1; k<n && (i+n)<Bars && (i+k)<Bars; k++) _interpolate(WSI);                                             
            }
            for(i=limit; i>=0; i--)
            {
               if (trend[i] == 1) Up[i] = WSI[i];
               if (trend[i] ==-1) Dn[i] = WSI[i];
            }
      return(0);
      }
   
   for(i=limit; i>=0; i--)
   {
      Price[i] = iMA(NULL,0,1,0,MODE_SMA,PRICE_TYPICAL,i);
      CCI[i]   = iCCI(NULL,0,CCI_Period,PRICE_TYPICAL,i);
      ADX[i]   = iADX(NULL,0,ADX_Period,PRICE_CLOSE,MODE_MAIN,i);
      
      WSI[i]=(CCI[i]*Price[i]* ADX[i]) / 1000;
	   Up[i] = EMPTY_VALUE;
	   Dn[i] = EMPTY_VALUE;
	   if (i<Bars-1)
      {
	     trend[i] = 0;
        if (WSI[i] >= 0) trend[i] = 1;
        if (WSI[i] <  0) trend[i] =-1;
        if (trend[i] == 1) Up[i] = WSI[i];
        if (trend[i] ==-1) Dn[i] = WSI[i];
      }
       
       //
       //
       //
       //
       //
               
       if (arrowsVisible)
       {
          string lookFor = arrowsIdentifier+":"+(string)Time[i]; ObjectDelete(lookFor);            
             if (i<Bars-1 && trend[i] != trend[i+1])
             {
                if (trend[i] == 1) drawArrow(i,arrowsUpColor,arrowsUpCode,false);
                if (trend[i] ==-1) drawArrow(i,arrowsDnColor,arrowsDnCode, true);
             }
        }
   }
   
   if (alertsOn)
   {
      int whichBar = 1; if (alertsOnCurrent) whichBar = 0; 
      if (trend[whichBar] != trend[whichBar+1])
      {
         if (trend[whichBar] == 1) doAlert(" up");
         if (trend[whichBar] ==-1) doAlert(" down");       
      }         
   }   
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

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 =  StringConcatenate(Symbol()," ",timeFrameToString(_Period)," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," WSI changed to ",doWhat);
             if (alertsMessage) Alert(message);
             if (alertsNotify)  SendNotification(message);
             if (alertsEmail)   SendMail(_Symbol+" WSI ",message);
             if (alertsSound)   PlaySound(soundFile);
      }
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,bool up)
{
   string name = arrowsIdentifier+":"+(string)Time[i];
   double gap  = iATR(NULL,0,20,i);   
   
      //
      //
      //
      //
      //

      int add = 0; if (!arrowsOnFirst) add = _Period*60-1;
      ObjectCreate(name,OBJ_ARROW,0,Time[i]+add,0);
         ObjectSet(name,OBJPROP_ARROWCODE,theCode);
         ObjectSet(name,OBJPROP_COLOR,theColor);
         if (up)
               ObjectSet(name,OBJPROP_PRICE1,High[i] + arrowsUpperGap * gap);
         else  ObjectSet(name,OBJPROP_PRICE1,Low[i]  - arrowsLowerGap * gap);
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

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("");
}


  
