//+------------------------------------------------------------------+
//| Detrended Oscillator.mq4
//| Copyright © 2008, Todd Geiger, fxid10t@yahoo.com (tageiger@comcast.net)
//| http://www.metaquotes.net
//+------------------------------------------------------------------+
/*This is my adaptation of Joe DiNaopli's Detrended Oscillator with 
  average overbought & oversold levels */
#property copyright "Copyright © 2008, Todd Geiger, fxid10t@yahoo.com (tageiger@comcast.net)"
#property link      "http://www.metaquotes.net"

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 Red

//---- input parameters
extern int     period            =1440;   //daily 
extern int     ma.period         =7;      //seven period ma
extern int     ma.method         =0;      //simple ma
extern int     ma.price          =0;      //close price
extern int     ob_os.period      =6;      //number of months back

//---- indicator buffers
double DOSC[];
double AvgOB[];
double AvgOS[];

int init()  {   
   IndicatorBuffers(3);
   SetIndexStyle(0,2);
   SetIndexStyle(1,0,0,EMPTY,DimGray);
   SetIndexStyle(2,0,0,EMPTY,DimGray);
   SetIndexBuffer(0,DOSC);
   SetIndexBuffer(1,AvgOB);
   SetIndexBuffer(2,AvgOS);
   IndicatorShortName(period+" DOSC");
   SetIndexDrawBegin(0,period/Period()*ma.period);
   SetIndexDrawBegin(1,period/Period()*ma.period);
   SetIndexDrawBegin(2,period/Period()*ma.period);
   SetIndexEmptyValue(0,0);
   SetIndexEmptyValue(1,0);
   SetIndexEmptyValue(2,0);
   SetIndexLabel(0,period+" DOSC");
   SetIndexLabel(1,period+" AvgOB");
   SetIndexLabel(2,period+" AvgOS");
   SetLevelValue(0,0);
return(0); }

int deinit()  {return(0);}

int start() {
   int limit;
   int counted_bars=IndicatorCounted();
//---- check for possible errors
   if(counted_bars<0) return(-1);
//---- the last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
//---- main loop
   for(int i=0; i<limit; i++)  {
double dima=iMA(Symbol(),period,ma.period,0,ma.method,ma.price,iBarShift(Symbol(),1440,Time[i]));
//DOSC[i]=NormalizeDouble(Close[i]-iMA(Symbol(),Period(),period/Period()*ma.period,0,ma.method,ma.price,i),Digits);  }
DOSC[i]=NormalizeDouble(Close[i]-dima,Digits);  }
//----six months back
      double M=TimeMonth(iTime(Symbol(),Period(),i));
      if(M<=ob_os.period) {   double Ms=M+12-ob_os.period; double Y=TimeYear(iTime(Symbol(),Period(),i))-1;   }
      if(M>ob_os.period) {   Ms=M-ob_os.period; Y=TimeYear(iTime(Symbol(),Period(),i));   }
      string m=DoubleToStr(Ms,0);
      if(Ms<10)   { m=("0"+m);   }
      double D=TimeDay(iTime(Symbol(),Period(),i));
      string d=DoubleToStr(D,0);
      if(D<10) { d=("0"+d);   }   
      string y=DoubleToStr(Y,0);
      double H=TimeHour(iTime(Symbol(),Period(),i));
      string h=DoubleToStr(H,0);
      if(H<10) { h=("0"+h);   }
      double Min=TimeMinute(iTime(Symbol(),Period(),i));
      string min=DoubleToStr(Min,0);
      if(Min<10)  { min=("0"+min);  }
      string St=StringConcatenate(y,".",m,".",d," ",h,":",min);

//----determine average overbought/oversold levels     
      double hi.sum=0; int hi.c=0; double highest=0;
      double lo.sum=0; int lo.c=0; double lowest=0;
      
      if( iMA(Symbol(),Period(),1440/Period()*7,0,0,0,iBarShift( Symbol(),Period(),StrToTime(St) ))==0 ) { return(0);  }
      
      for( int ii=0; ii<iBarShift(Symbol(),Period(),StrToTime(St)); ii++) {
         if(DOSC[ii+4]<=DOSC[ii+2] && DOSC[ii+4]>0 &&
            DOSC[ii+3]<=DOSC[ii+2] && DOSC[ii+3]>0 &&
            DOSC[ii+1]<=DOSC[ii+2] && DOSC[ii+1]>0 &&
            DOSC[ii]<=DOSC[ii+2]   && DOSC[ii]>0 ) {
            hi.sum+=DOSC[ii+2]; hi.c++;
            AvgOB[0]=hi.sum/hi.c;
            SetLevelValue(1,hi.sum/hi.c); }
         if(DOSC[ii+4]>=DOSC[ii+2] && DOSC[ii+4]<0 &&
            DOSC[ii+3]>=DOSC[ii+2] && DOSC[ii+3]<0 &&
            DOSC[ii+1]>=DOSC[ii+2] && DOSC[ii+1]<0 &&
            DOSC[ii]>=DOSC[ii+2]   && DOSC[ii]<0 ) {
            lo.sum+=DOSC[ii+2]; lo.c++;
            AvgOS[0]=lo.sum/lo.c;
            SetLevelValue(2,lo.sum/lo.c); }  }
return(0);}