//+------------------------------------------------------------------+
//|                                                Ratio MACD_v3.mq4 |
//| The Ratio code was written by 2007, Christof Risch (iya)         |
//| All credits to him                                               |
//| Linuxser 2007                                                    |
//| mladen   2008                                                    |
//+------------------------------------------------------------------+
#property copyright "Under The GNU General Public License V3"
#property link      "www.gnu.org"

#property indicator_separate_window
#property indicator_buffers 8
#property indicator_color1 DimGray
#property indicator_color2 DarkOrange
#property indicator_color3 Green
#property indicator_color4 DarkOrange
#property indicator_color5 Green
#property indicator_color6 Gray
#property indicator_color7 LimeGreen
#property indicator_color8 Yellow
#property indicator_width4 2
#property indicator_width5 2
#property indicator_width6 2
#property indicator_width7 2
#property indicator_style1 STYLE_DOT

//
//
//
//
//

extern string timeFrame         = "current time frame";
extern int    FastEMA           = 12;
extern int    SlowEMA           = 26;
extern int    SignalEMA         =  9;
extern int    AppliedPrice      =  0;
extern bool   MacdHistogram     = true;
extern bool   OsmaHistogram     = true;
extern bool   interpolateColors = false;

//
//
//
//
//

double buffer0[];
double buffer1[];
double buffer2[];
double buffer3[];
double buffer4[];
double buffer5[];
double buffer6[];
double buffer7[];
int    TimeFrame;
string IndicatorFileName;
bool   CalculatingMACD=false; 

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   if (timeFrame == "calculateMACD")
   {
       TimeFrame = Period();
          CalculatingMACD = true;
          SetIndexBuffer(0,buffer0);
          SetIndexBuffer(1,buffer1);
       return(0);
   }
      
   //
   //
   //
   //
   //                        
         
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS)+1);
   
      SetIndexBuffer(0,buffer0); SetIndexLabel(0,NULL);
      SetIndexBuffer(1,buffer1); SetIndexLabel(1,"MACD down"); SetIndexEmptyValue(1,0); 
      SetIndexBuffer(2,buffer2); SetIndexLabel(2,"MACD up");   SetIndexEmptyValue(2,0); 
      SetIndexBuffer(3,buffer3); SetIndexLabel(3,"OSMA down"); SetIndexEmptyValue(3,0); 
      SetIndexBuffer(4,buffer4); SetIndexLabel(4,"OSMA up");   SetIndexEmptyValue(4,0); 
      SetIndexBuffer(5,buffer5); SetIndexLabel(5,"OSMA"); 
      SetIndexBuffer(6,buffer6); SetIndexLabel(6,"MACD"); 
      SetIndexBuffer(7,buffer7); SetIndexLabel(7,"Signal"); 

      if (MacdHistogram) { SetIndexStyle(1,DRAW_HISTOGRAM); SetIndexStyle(2,DRAW_HISTOGRAM); }              
      else               { SetIndexStyle(1,DRAW_NONE);      SetIndexStyle(2,DRAW_NONE);      }	           
      if (OsmaHistogram) { SetIndexStyle(3,DRAW_HISTOGRAM); SetIndexStyle(4,DRAW_HISTOGRAM); }              
      else               { SetIndexStyle(3,DRAW_NONE);      SetIndexStyle(4,DRAW_NONE);      }	           
	
   //
   //
   //
   //
   //

   string PriceType;
   switch(AppliedPrice)
   {
      case PRICE_CLOSE:    PriceType = "Close";    break;  // 0
      case PRICE_OPEN:     PriceType = "Open";     break;  // 1
      case PRICE_HIGH:     PriceType = "High";     break;  // 2
      case PRICE_LOW:      PriceType = "Low";      break;  // 3
      case PRICE_MEDIAN:   PriceType = "Median";   break;  // 4
      case PRICE_TYPICAL:  PriceType = "Typical";  break;  // 5
      case PRICE_WEIGHTED: PriceType = "Weighted"; break;  // 6
   }      

   TimeFrame = stringToTimeFrame(timeFrame);
   
   string TimeFrameStr;
   switch(TimeFrame)
   {
      case PERIOD_M1:  TimeFrameStr="(M1)";      break;
      case PERIOD_M5:  TimeFrameStr="(M5)";      break;
      case PERIOD_M15: TimeFrameStr="(M15)";     break;
      case PERIOD_M30: TimeFrameStr="(M30)";     break;
      case PERIOD_H1:  TimeFrameStr="(H1)";      break;
      case PERIOD_H4:  TimeFrameStr="(H4)";      break;
      case PERIOD_D1:  TimeFrameStr="(Dayly)";   break;
      case PERIOD_W1:  TimeFrameStr="(Weekly)";  break;
      case PERIOD_MN1: TimeFrameStr="(Monthly)"; break;
      default :        TimeFrameStr="";
   }
   IndicatorShortName("Ratio MACD("+FastEMA+","+SlowEMA+","+SignalEMA+","+PriceType+") "+TimeFrameStr);
   IndicatorFileName = WindowExpertName();
   return(0);
}

 
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
   int i,limit;

   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
         limit = Bars-counted_bars;
         if (TimeFrame > Period()) limit = MathMax(limit,TimeFrame/Period());

   //
   //
   //
   //
   //
   
      if (CalculatingMACD) { calculateMACD(limit); return(0); }
         
   //
   //
   //
   //
   //
   
	for(i = limit; i >= 0; i--)
	{
		int      shift1 = iBarShift(NULL,TimeFrame,Time[i]);
		datetime	time1  = iTime    (NULL,TimeFrame,shift1);

         buffer0[i]=0;
         buffer6[i]=iCustom(NULL,TimeFrame,IndicatorFileName,"calculateMACD",FastEMA,SlowEMA,SignalEMA,AppliedPrice,0,shift1); 
         buffer7[i]=iCustom(NULL,TimeFrame,IndicatorFileName,"calculateMACD",FastEMA,SlowEMA,SignalEMA,AppliedPrice,1,shift1); 
         buffer5[i]=buffer6[i]-buffer7[i]; 
         
         //
         //
         //
         //
         //

            if (buffer5[i]  < buffer5[i+1]) { buffer3[i]=buffer5[i];   buffer4[i]=0; }
            if (buffer5[i]  > buffer5[i+1]) { buffer4[i]=buffer5[i];   buffer3[i]=0; }
            if (buffer5[i] == buffer5[i+1]) { buffer3[i]=buffer3[i+1]; buffer4[i]=buffer4[i+1]; }
            if (buffer6[i]  < buffer6[i+1]) { buffer1[i]=buffer6[i];   buffer2[i]=0; }
            if (buffer6[i]  > buffer6[i+1]) { buffer2[i]=buffer6[i];   buffer1[i]=0; }
            if (buffer6[i] == buffer6[i+1]) { buffer1[i]=buffer1[i+1]; buffer2[i]=buffer2[i+1]; }

         //
         //
         //
         //
         //
         
            if(TimeFrame <= Period() || shift1==iBarShift(NULL,TimeFrame,Time[i-1])) continue;

         //
         //
	      //   apply interpolation
	      //
	      //
		 
     		   for(int n = 1; i+n < Bars && Time[i+n] >= time1; n++) continue;	
      		   double factor = 1.0 / n;
               for(int k = 1; k < n; k++)
		         {
			         buffer5[i+k] = k*factor*buffer5[i+n] + (1.0-k*factor)*buffer5[i];
			         buffer6[i+k] = k*factor*buffer6[i+n] + (1.0-k*factor)*buffer6[i];
			         buffer7[i+k] = k*factor*buffer7[i+n] + (1.0-k*factor)*buffer7[i];
		            if (interpolateColors)
		            {
   			         buffer1[i+k] = k*factor*buffer1[i+n] + (1.0-k*factor)*buffer1[i];
	                  buffer2[i+k] = k*factor*buffer2[i+n] + (1.0-k*factor)*buffer2[i];
			            buffer3[i+k] = k*factor*buffer3[i+n] + (1.0-k*factor)*buffer3[i];
			            buffer4[i+k] = k*factor*buffer4[i+n] + (1.0-k*factor)*buffer4[i];
                  }
                  else
                  {
        	   		   if (buffer1[i+k]!=0) buffer1[i+k]=buffer6[i+k];
        	   		   if (buffer2[i+k]!=0) buffer2[i+k]=buffer6[i+k];
        	   		   if (buffer3[i+k]!=0) buffer3[i+k]=buffer5[i+k];
        	   		   if (buffer4[i+k]!=0) buffer4[i+k]=buffer5[i+k];
                  }			            
      		   }	  
   }
   return(0);
}



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

void calculateMACD(int limit)
{
   double alpha = 2.0 / (1.0 + SignalEMA);
	for(int i = limit; i >= 0; i--)
	{
         buffer0[i] = iMA(NULL,0,FastEMA,0,MODE_EMA,AppliedPrice,i)-
                      iMA(NULL,0,SlowEMA,0,MODE_EMA,AppliedPrice,i);
         buffer1[i] = buffer1[i+1]+alpha*(buffer0[i]-buffer1[i+1]);
   }
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   for(int l = StringLen(tfs)-1; l >= 0; l--)
   {
      int char = StringGetChar(tfs,l);
          if((char > 96 && char < 123) || (char > 223 && char < 256))
               tfs = StringSetChar(tfs, l, char - 32);
          else 
              if(char > -33 && char < 0)
                  tfs = StringSetChar(tfs, l, char + 224);
   }

   //
   //
   //
   //
   //
   
   int tf=0;
         if (tfs=="M1" || tfs=="1")     tf=PERIOD_M1;
         if (tfs=="M5" || tfs=="5")     tf=PERIOD_M5;
         if (tfs=="M15"|| tfs=="15")    tf=PERIOD_M15;
         if (tfs=="M30"|| tfs=="30")    tf=PERIOD_M30;
         if (tfs=="H1" || tfs=="60")    tf=PERIOD_H1;
         if (tfs=="H4" || tfs=="240")   tf=PERIOD_H4;
         if (tfs=="D1" || tfs=="1440")  tf=PERIOD_D1;
         if (tfs=="W1" || tfs=="10080") tf=PERIOD_W1;
         if (tfs=="MN" || tfs=="43200") tf=PERIOD_MN1;
   return(tf);
}