//+------------------------------------------------------------------+
//|                                                       #dtosc.mq4 |
//|           13 June 2012                                    mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"


#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Lime
#property indicator_color2 Red
#property indicator_color3 Lime
#property indicator_color4 Red
#property indicator_width3 2
#property indicator_width4 2

//
//
//
//
//

extern string TimeFrame    = "Current time frame";
extern int    PeriodRSI    = 50;
extern int    PeriodStoch  = 50;
extern int    PeriodSK     = 14;
extern int    PeriodSD     = 7;
extern int    MAMode       = 3;
   
//
//
//
//
//

double SK[];
double SD[];
double StoRSI[];
double RSI[];
double trend[];
double barUp[];
double barDn[];
double wickUp[];
double wickDn[];
string IndicatorFileName;
int    timeFrame;
bool   returnBars;
bool   calculateValue;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(8);
      SetIndexBuffer(0,wickUp); SetIndexStyle(0, DRAW_HISTOGRAM);
      SetIndexBuffer(1,wickDn); SetIndexStyle(1, DRAW_HISTOGRAM);
      SetIndexBuffer(2,barUp);  SetIndexStyle(2, DRAW_HISTOGRAM);
      SetIndexBuffer(3,barDn);  SetIndexStyle(3, DRAW_HISTOGRAM);
      SetIndexBuffer(4,SK);
      SetIndexBuffer(5,SD);
      SetIndexBuffer(6,StoRSI);
      SetIndexBuffer(7,RSI);

   //
   //
   //
   //
   //
   
      IndicatorFileName = WindowExpertName();
      returnBars        = (TimeFrame == "returnBars");     if (returnBars)     return(0);
      calculateValue    = (TimeFrame == "calculateValue"); if (calculateValue) return(0);
      timeFrame         = stringToTimeFrame(TimeFrame);   

   //
   //
   //
   //
   //
   
   IndicatorShortName(timeFrameToString(timeFrame)+" DTOSC ("+PeriodRSI+","+PeriodStoch+","+PeriodSK+","+PeriodSD+")");
return(0);
}
int deinit()
{
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

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) { barUp[0] = limit; return(0); }
          if (ArraySize(trend)!=Bars) ArrayResize(trend,Bars);
          

   //
   //
   //
   //
   //

   if (calculateValue || timeFrame == Period())
   {
      for(i=limit; i>=0; i--)
      {
         RSI[i]    = iRSI(NULL,0,PeriodRSI,PRICE_CLOSE,i);
         double lo = RSI[ArrayMinimum(RSI,PeriodStoch,i)];
         double hi = RSI[ArrayMaximum(RSI,PeriodStoch,i)];
         if (hi!=lo)
               StoRSI[i] = 100.0*((RSI[i] - lo)/(hi - lo));
         else  StoRSI[i] = 0;
      }   
      for(i=limit; i>=0; i--) SK[i]=iMAOnArray(StoRSI,0,PeriodSK,0,MAMode,i);
      for(i=limit, r=Bars-i-1; i>=0; i--,r++)
      {
         SD[i] = iMAOnArray(SK,0,PeriodSD,0,MAMode,i);
         trend[r]  = trend[r-1];
         barUp[i]  = EMPTY_VALUE;
         barDn[i]  = EMPTY_VALUE;
         wickUp[i] = EMPTY_VALUE;
         wickDn[i] = EMPTY_VALUE;
            if (SK[i]>SD[i]) trend[r] =  1;
            if (SK[i]<SD[i]) trend[r] = -1;
            if (!calculateValue)
            {
               if (trend[r] == 1) { barUp[i] = MathMax(Open[i],Close[i]); barDn[i] = MathMin(Open[i],Close[i]); wickUp[i]=High[i]; wickDn[i]=Low[i];}
               if (trend[r] ==-1) { barUp[i] = MathMin(Open[i],Close[i]); barDn[i] = MathMax(Open[i],Close[i]); wickDn[i]=High[i]; wickUp[i]=Low[i];}
            }   
            else wickUp[i] = trend[r];
      }         
      return(0);      
   }
   
   //
   //
   //
   //
   //
   
   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,timeFrame,IndicatorFileName,"returnBars",0,0)*timeFrame/Period()));
   for(i=limit, r=Bars-i-1; i>=0; i--,r++)
   {
      int y = iBarShift(NULL,timeFrame,Time[i]);
      double ttrend = iCustom(NULL,timeFrame,IndicatorFileName,"calculateValue",PeriodRSI,PeriodStoch,PeriodSK,PeriodSD,MAMode,0,y);
         barUp[i]  = EMPTY_VALUE;
         barDn[i]  = EMPTY_VALUE;
         wickUp[i] = EMPTY_VALUE;
         wickDn[i] = EMPTY_VALUE;
               if (ttrend == 1) { barUp[i] = MathMax(Open[i],Close[i]); barDn[i] = MathMin(Open[i],Close[i]); wickUp[i]=High[i]; wickDn[i]=Low[i];}
               if (ttrend ==-1) { barUp[i] = MathMin(Open[i],Close[i]); barDn[i] = MathMax(Open[i],Close[i]); wickDn[i]=High[i]; wickUp[i]=Low[i];}
   }               
   return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

string sTfTable[] = {"M1","M5","M10","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,10,15,30,60,240,1440,10080,43200};

//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   tfs = StringUpperCase(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}
string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//
//
//
//
//

string StringUpperCase(string str)
{
   string   s = str;

   for (int length=StringLen(str)-1; length>=0; length--)
   {
      int tchar = StringGetChar(s, length);
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                     s = StringSetChar(s, length, tchar - 32);
         else if(tchar > -33 && tchar < 0)
                     s = StringSetChar(s, length, tchar + 224);
   }
   return(s);
}