//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
//----
#property indicator_separate_window
#property indicator_buffers    2
#property indicator_color1     clrLimeGreen
#property indicator_color2     clrRed
#property indicator_width1     2
#property indicator_width2     2
#property indicator_level1     0
#property indicator_level2     100
#property indicator_levelcolor clrDimGray


//
//
//
//
//

extern ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;
extern int    Length             = 1;
extern bool   alertsOn           = false;
extern bool   alertsOnCurrent    = false;
extern bool   alertsSound        = false;
extern bool   alertsMessage      = true;
extern bool   alertsNotification = false;
extern bool   alertsEmail        = false;

//
//
//
//
//

double wso[];
double wro[];
double wrk[][12];
double same[];
int    center;

string indicatorFileName;
bool   returnBars;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int init()
{
   IndicatorBuffers(3);
   SetIndexBuffer(0, wso); 
   SetIndexBuffer(1, wro); 
   SetIndexBuffer(2, same); 
         if (MathMod(Length,2)==0) Length++;  center = (Length-1)/2;

         indicatorFileName = WindowExpertName();
         returnBars        = (TimeFrame==-99);
        
   IndicatorShortName(timeFrameToString(TimeFrame)+" wso & wro ("+Length+")");
   return(0);
}
int deinit()
{
   return(0);
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

#define S1 0
#define S2 1
#define S3 2
#define S4 3
#define S5 4
#define S6 5
#define R1 6
#define R2 7
#define R3 8
#define R4 9
#define R5 10
#define R6 11

int start()
{
   int i,r,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) { wso[0] = limit+1; return(0); }
         
   //
   //
   //
   //
   //

   if (TimeFrame==Period() || TimeFrame==PERIOD_CURRENT)
   {
      if (ArrayRange(wrk,0)!=Bars) ArrayResize(wrk,Bars);
      for(i=limit, r=Bars-i-1; i>=0; i--,r++)
      {
         if (r==0)
         {
            for (int k=0; k<6; k++)
            {
               wrk[r][k]   = Low[i];
               wrk[r][k+6] = High[i];
            }
            continue;
         }
      
         //
         //
         //
         //
         //
      
         int lowest  = iLowest(NULL,0,MODE_LOW,Length,i)-i;
         int highest = iHighest(NULL,0,MODE_HIGH,Length,i)-i;

         for (k=0; k<12; k++) wrk[r][k] = wrk[r-1][k];
         if (lowest==center)
         {
            wrk[r][S1] = Low[i+center];
            wrk[r][S2] = wrk[r-1][S1];
            wrk[r][S3] = wrk[r-1][S2];
            wrk[r][S4] = wrk[r-1][S3];
            wrk[r][S5] = wrk[r-1][S4];
            wrk[r][S6] = wrk[r-1][S5];
         }
         if (highest==center)
         {
            wrk[r][R1] = High[i+center];
            wrk[r][R2] = wrk[r-1][R1];
            wrk[r][R3] = wrk[r-1][R2];
            wrk[r][R4] = wrk[r-1][R3];
            wrk[r][R5] = wrk[r-1][R4];
            wrk[r][R6] = wrk[r-1][R5];
         }
         
         //
         //
         //
         //
         //

         wso[i] = 100*(1-(MathInt(wrk[r][S1]/Close[i])+
                          MathInt(wrk[r][S2]/Close[i])+
                          MathInt(wrk[r][S3]/Close[i])+
                          MathInt(wrk[r][S4]/Close[i])+
                          MathInt(wrk[r][S5]/Close[i])+
                          MathInt(wrk[r][S6]/Close[i]))/6.0);                         
/*         wro[i] = 100*(1-(MathInt(wrk[r][R1]/Close[i])+
                          MathInt(wrk[r][R2]/Close[i])+
                          MathInt(wrk[r][R3]/Close[i])+
                          MathInt(wrk[r][R4]/Close[i])+
                          MathInt(wrk[r][R5]/Close[i])+
                          MathInt(wrk[r][R6]/Close[i]))/6.0);   
*/                                        
         wro[i] = 100*(1-(MathInt(wrk[r][R1]/Close[i+1])+
                          MathInt(wrk[r][R2]/Close[i+1])+
                          MathInt(wrk[r][R3]/Close[i+1])+
                          MathInt(wrk[r][R4]/Close[i+1])+
                          MathInt(wrk[r][R5]/Close[i+1])+
                          MathInt(wrk[r][R6]/Close[i+1]))/6.0);
                          
         same[i] = 0;
         if (wso[i]==  0 && wro[i]==  0) same[i] = -1;                                  
         if (wso[i]== 100 && wro[i]== 100) same[i] = 1;                          
      }
      manageAlerts();
      return(0);
   }
   
   //
   //
   //
   //
   //
   
   limit = MathMax(limit,MathMin(Bars,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/Period()));
   for (i=limit;i>=0;i--)
   {
      int y = iBarShift(NULL,TimeFrame,Time[i]);
         wso[i]    = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Length,alertsOn,alertsOnCurrent,alertsSound,alertsMessage,alertsNotification,alertsEmail,0,y);
         wro[i]    = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Length,alertsOn,alertsOnCurrent,alertsSound,alertsMessage,alertsNotification,alertsEmail,1,y);
   }
   return(0);
}

double MathInt(double number)
{
   if (number>=1.0)
         return(1);
   else  return(0);    
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

void manageAlerts()
{
   if (alertsOn)
   {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1;
      
      //
      //
      //
      //
      //
      
      Comment(same[whichBar],"   ",same[whichBar+1]);
      static string   alertType1 = "";
      static datetime alertTime1 = 0;
      if (same[whichBar] != same[whichBar+1])
      {
         if (same[whichBar] ==  1) doAlert(alertType1,alertTime1,"wso & wro levels alligned up");
         if (same[whichBar] == -1) doAlert(alertType1,alertTime1,"wso & wro levels alligned down");
      }
   }
}

//
//
//
//
//

void doAlert(string& previousAlert, datetime& previousTime, string doWhat)
{
   string message;
   
   if (previousAlert != doWhat || previousTime != Time[0]) {
       previousAlert  = doWhat;
       previousTime   = Time[0];

       //
       //
       //
       //
       //

       message = timeFrameToString(Period())+" "+Symbol()+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+"  "+doWhat;
          if (alertsMessage)      Alert(message);
          if (alertsEmail)        SendMail(StringConcatenate(Symbol(),"wso & wro"),message);
          if (alertsNotification) SendNotification(StringConcatenate(Symbol(),"wso & wro "+message));
          if (alertsSound)        PlaySound("alert2.wav");
   }
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

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("");
}