//+------------------------------------------------------------------+
//|                                                       #dtosc.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_minimum -50
#property indicator_maximum +50
#property indicator_color1  clrOrange
#property indicator_color2  clrLimeGreen
#property indicator_color4  clrDeepSkyBlue
#property indicator_color5  clrOrangeRed
#property indicator_width4  2
#property indicator_width5  2

//
//
//
//
//

   extern ENUM_TIMEFRAMES TimeFrame      = PERIOD_CURRENT;
   extern int            PeriodRSI       = 13;
   extern int            PeriodStoch     = 8;
   extern int            PeriodSK        = 5;
   extern int            PeriodSD        = 3;
   extern double         LevelUp         = 70;
   extern double         LevelDn         = 30;
   extern ENUM_MA_METHOD MAMode          = MODE_SMA;
   extern bool           alertsOn        = true;
   extern bool           alertsOnCurrent = true;
   extern bool           alertsMessage   = true;
   extern bool           alertsSound     = true;
   extern bool           alertsEmail     = false;
   extern string         soundfile       = "alert2.wav";
   extern int            HistoWidth      = 3;
   extern bool           Interpolate     = true;

//
//
//
//
//

double SK[];
double SD[];
double StoRSI[];
double RSI[];
double cross[],trend[],histou[],histod[],histon[];
string IndicatorFileName;
bool   returnBars;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(9);
      SetIndexBuffer(0,histou); SetIndexStyle(0,DRAW_HISTOGRAM,0,HistoWidth);
      SetIndexBuffer(1,histod); SetIndexStyle(1,DRAW_HISTOGRAM,1,HistoWidth);
      SetIndexBuffer(2,histon); SetIndexStyle(2,DRAW_HISTOGRAM,2,HistoWidth);
      SetIndexBuffer(3,SK);
      SetIndexBuffer(4,SD);
      SetIndexBuffer(5,StoRSI);
      SetIndexBuffer(6,RSI);
      SetIndexBuffer(7,cross);
      SetIndexBuffer(8,trend);

   //
   //
   //
   //
   //
   
   IndicatorFileName = WindowExpertName();
   returnBars = (TimeFrame == -99);
   TimeFrame = MathMax(TimeFrame,_Period);   
         LevelDn -= 50;
         LevelUp -= 50;
         SetLevelValue(0,LevelUp);
         SetLevelValue(1,LevelDn);

   //
   //
   //
   //
   //
   
   IndicatorShortName(timeFrameToString(TimeFrame)+" DTOSC ("+PeriodRSI+","+PeriodStoch+","+PeriodSK+","+PeriodSD+")");
return(0);
}
int deinit() { 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) { histou[0] = limit; return(0); }
               SetIndexStyle(2,DRAW_HISTOGRAM,0,EMPTY,ChartGetInteger(0,CHART_COLOR_BACKGROUND));

   //
   //
   //
   //
   //
   
   if (TimeFrame != Period())
   {
      limit = MathMax(limit,MathMin(Bars,iCustom(NULL,TimeFrame,IndicatorFileName,-99,0,0)*TimeFrame/Period()));
      for(int i=limit; i>=0; i--)
      {
         int y = iBarShift(NULL,TimeFrame,Time[i]);
            histou[i] = iCustom(NULL,TimeFrame,IndicatorFileName,PERIOD_CURRENT,PeriodRSI,PeriodStoch,PeriodSK,PeriodSD,LevelUp+50,LevelDn+50,MAMode,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,soundfile,0,y);
            histod[i] = iCustom(NULL,TimeFrame,IndicatorFileName,PERIOD_CURRENT,PeriodRSI,PeriodStoch,PeriodSK,PeriodSD,LevelUp+50,LevelDn+50,MAMode,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,soundfile,1,y);
            histon[i] = iCustom(NULL,TimeFrame,IndicatorFileName,PERIOD_CURRENT,PeriodRSI,PeriodStoch,PeriodSK,PeriodSD,LevelUp+50,LevelDn+50,MAMode,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,soundfile,2,y);
            SK[i]     = iCustom(NULL,TimeFrame,IndicatorFileName,PERIOD_CURRENT,PeriodRSI,PeriodStoch,PeriodSK,PeriodSD,LevelUp+50,LevelDn+50,MAMode,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,soundfile,3,y);
            SD[i]     = iCustom(NULL,TimeFrame,IndicatorFileName,PERIOD_CURRENT,PeriodRSI,PeriodStoch,PeriodSK,PeriodSD,LevelUp+50,LevelDn+50,MAMode,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,soundfile,4,y);
            
            if (!Interpolate || y==iBarShift(NULL,TimeFrame,Time[i-1])) continue;

            //
            //
            //
            //
            //

            datetime time = iTime(NULL,TimeFrame,y);
               for(int n = 1; i+n < Bars && Time[i+n] >= time; n++) continue;	
               for(int j = 1; j < n; j++)
               {
                  SK[i+j] = SK[i] + (SK[i+n]-SK[i])*j/n;
                  SD[i+j] = SD[i] + (SD[i+n]-SD[i])*j/n;
               }
      }
      return(0);         
   }
   
   //
   //
   //
   //
   //
             
   for(i=limit; i>=0; i--)
   {
      RSI[i] = iRSI(NULL,0,PeriodRSI,PRICE_CLOSE,i);
      double LLV = RSI[ArrayMinimum(RSI,PeriodStoch,i)];
      double HHV = RSI[ArrayMaximum(RSI,PeriodStoch,i)];
      if ((HHV-LLV)!=0)
            StoRSI[i] = 100.0*((RSI[i] - LLV)/(HHV - LLV))-50;
      else  StoRSI[i] = 0;
   }   
   for(i=limit; i>=0; i--) SK[i]=iMAOnArray(StoRSI,0,PeriodSK,0,MAMode,i);
   for(i=limit; i>=0; i--)
   {
      SD[i]=iMAOnArray(SK,0,PeriodSD,0,MAMode,i);
      cross[i]  = cross[i+1];
      histod[i] = EMPTY_VALUE;
      histou[i] = EMPTY_VALUE;
      histon[i] = EMPTY_VALUE;
      trend[i]  = trend[i+1];
         if (SK[i]>SD[i]) cross[i] =  1;
         if (SK[i]<SD[i]) cross[i] = -1;
         if (SD[i]>LevelUp && cross[i] == -1)                 trend[i] =  1;
         if (SD[i]<LevelDn && cross[i] ==  1)                 trend[i] = -1;
         if (SD[i]<LevelUp && trend[i] == 1 && cross[i] == 1) trend[i] =  0;
         if (SD[i]>LevelDn && trend[i] ==-1 && cross[i] ==-1) trend[i] =  0;
         if (trend[i]== 1) { histou[i] =  50; histon[i] = LevelUp; }
         if (trend[i]==-1) { histod[i] = -50; histon[i] = LevelDn; }
         
   }    
   
   //
   //
   //
   //
   //
        
   if (alertsOn)
   {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1;
      if (cross[whichBar] != cross[whichBar+1])
      if (cross[whichBar] == 1)
            doAlert("dtosc trend changed to up");
      else  doAlert("dtosc trend changed to 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(timeFrameToString(_Period)+" "+Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," Dtosc ",doWhat);
             if (alertsMessage) Alert(message);
             if (alertsEmail)   SendMail(StringConcatenate(Symbol()," Dtosc "),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("");
}