//+------------------------------------------------------------------+
//|                                       Custom Moving Averages.mq4 |
//|                   Copyright 2005-2015, MetaQuotes Software Corp. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2005-2015, MetaQuotes Software Corp."
#property link        "http://www.mql4.com"
#property description "Moving Average"
#property strict

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Red
#property indicator_color2 clrAliceBlue
#property indicator_color2 clrGold

//--- indicator parameters
// MA line 1
extern int InpMAPeriod1=21; // Period
extern ENUM_TIMEFRAMES InpTIMEFRAME1=PERIOD_H4; //Anchor Timeframe
extern int InpMAShift1=0; // Shift
input ENUM_MA_METHOD InpMAMethod1=MODE_EMA; // Method

// MA line 1
extern int InpMAPeriod2=5; // Period
extern ENUM_TIMEFRAMES InpTIMEFRAME2=PERIOD_H4; //Anchor Timeframe
extern int InpMAShift2=0; // Shift
input ENUM_MA_METHOD InpMAMethod2=MODE_EMA; // Method

int InpMAPeriod_RS=30; // Period 

int adjustedMA1, adjustedMA2;
//--- indicator buffer

double MaLine1Buffer[], MaLine2Buffer[], MaRSBuffer[];
//Array to computing MaDiff
double MaDiff[];

double MyMAMultiplier;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit(void)
{

int period = Period() ; //capture the timeframe of the chart use InpTIMEFRAME
MaAdjuster(InpTIMEFRAME1, period); //call the MaAdjuster function, sending the number of period() to the function
MaAdjuster(InpTIMEFRAME2, period); //call the MaAdjuster function, sending the number of period() to the function

adjustedMA1 = NormalizeDouble(InpMAPeriod1*MyMAMultiplier,0); //convert the number of candle base on selected TIMEFRAMES
adjustedMA2 = NormalizeDouble(InpMAPeriod2*MyMAMultiplier,0); //convert the number of candle base on selected TIMEFRAMES

int InpTIMEFRAME_RS = MathMax(InpTIMEFRAME1,InpTIMEFRAME2);
int draw_begin=adjustedMA1-1;
if(InpMAMethod1==MODE_EMA || InpMAMethod2==MODE_EMA) draw_begin=0;

//--- indicator short name
  IndiShortName(InpMAMethod1);
  IndiShortName(InpMAMethod2);

//--- check for input
if(InpMAPeriod1<2 || InpMAPeriod2<2)
return(INIT_FAILED);
//--- indicator buffers mapping and drawings
SetIndexBuffer(0,MaLine1Buffer);
SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,2);
SetIndexShift(0,InpMAShift1);
SetIndexDrawBegin(0,draw_begin);
SetIndexLabel(0,"AutoAdj-Ma1"+tf2txt(InpTIMEFRAME1));

SetIndexBuffer(1,MaLine2Buffer);
SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,2);
SetIndexShift(1,InpMAShift2);
SetIndexDrawBegin(1,draw_begin);
SetIndexLabel(1,"AutoAdj-Ma2"+tf2txt(InpTIMEFRAME2));

SetIndexBuffer(2,MaRSBuffer);
SetIndexStyle(2,DRAW_LINE,STYLE_SOLID,2);
SetIndexDrawBegin(2,draw_begin);
SetIndexLabel(2,"AutoAdj-MaRS"+tf2txt(InpTIMEFRAME_RS));


//--- initialization done
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Moving Average |
//+------------------------------------------------------------------+
int start()
{

int counted_bars=IndicatorCounted();
if(counted_bars<0)return(-1);
if(counted_bars>0)counted_bars--;
int limit=Bars-counted_bars; //limit = new bar added into chart after indi dropped on chart
int InpTIMEFRAME_RS = MathMax(InpTIMEFRAME1,InpTIMEFRAME2);
if(counted_bars==0) limit-=InpTIMEFRAME_RS;

for(int i=0;i<limit;i++)
{
MaLine1Buffer[i] = iMA(NULL,InpTIMEFRAME1,adjustedMA1, InpMAShift1,InpMAMethod1,PRICE_CLOSE,i);
MaLine2Buffer[i] = iMA(NULL,InpTIMEFRAME2,adjustedMA2, InpMAShift2,InpMAMethod2,PRICE_CLOSE,i);
if(limit>=InpTIMEFRAME_RS && i>=InpTIMEFRAME_RS)
   {
   MaRSBuffer[i] = MAValidatorChk(InpMAPeriod_RS, MaLine1Buffer, InpTIMEFRAME1, InpMAPeriod1, MaLine2Buffer, InpTIMEFRAME2, InpMAPeriod2);
   }
   else MaRSBuffer[i]=0;
}

/*
for(int i=InpTIMEFRAME_RS;i<limit;i++)
{
   MaRSBuffer[i] = MAValidatorChk(InpMAPeriod_RS, MaLine1Buffer, InpTIMEFRAME1, InpMAPeriod1, MaLine2Buffer, InpTIMEFRAME2, InpMAPeriod2 );
}
*/

//--- return value of prev_calculated for next call
return(0);

}


double MAValidatorChk(int CalPeriod, double &InpMA1_array[], int Ma1_TF, int Ma1_period, double &InpMA2_array[], int Ma2_TF, int Ma2_period)
  {
      //from <40 [Oversold](buy only)
      //from 40-49 [Downtrend](Sell and buy) 
      //from 50-56 [Sideway] (No trading)
      //from 56-65 [Uptrend] (Buy)
      //from 69> [Overbought] (Sell only)
    //declare array to hold the last 100 value of MAs
       double MADiff_array[], MAPosDiff_array[], MANegDiff_array[];
       double MA1_array[], MA2_array[];
         
       ArrayResize(MADiff_array,CalPeriod);
       ArrayResize(MA1_array,CalPeriod);
       ArrayResize(MA2_array,CalPeriod);
       ArrayResize(MAPosDiff_array,CalPeriod);
       ArrayResize(MANegDiff_array,CalPeriod);
       for(int i=0;i<CalPeriod-1;i++)
        {
           //get value of MAh1 and MAh4 value 
            MA1_array[i] = InpMA1_array[i]; 
            MA2_array[i] = InpMA2_array[i]; 
             MADiff_array[i] = NormalizeDouble(MA1_array[i] - MA2_array[i],4);
             
          //pass the square MADiff_array value to MANegative and Positive array base on their value
          if(MADiff_array[i]<0)MANegDiff_array[i] =  1;
            else MANegDiff_array[i] = 0.0;
          if(MADiff_array[i]>0)MAPosDiff_array[i] =  1;
            else MAPosDiff_array[i] = 0.0;  
          //ArraySetAsSeries(MANegDiff_array,true);
          //ArraySetAsSeries(MAPosDiff_array,true);
          }
       //Compute the average 
       double AverageNegMADiff = NormalizeDouble(ArrayAverage(MANegDiff_array),4);
       double AveragePosMADiff =  NormalizeDouble(ArrayAverage(MAPosDiff_array),4);
       double MAdiffRS = NormalizeDouble(100-(100/(1+AveragePosMADiff/AverageNegMADiff)),2);
       //int NegPosRS_d;
       //if(NegPosRS  <0.9 || NegPosRS >1.1
       //function return 0 for uptrend (AveragePosMADiff > AverageNegMADiff) or downtrend(AveragePosMADiff < AverageNegMADiff)
       //if(AveragePosMADiff > AverageNegMADiff)result=1;
       //else if(AveragePosMADiff < AverageNegMADiff)result = -1;
       //else if(AveragePosMADiff = AverageNegMADiff) result=0;
       //  else GetLastError();
       return(MAdiffRS);
   }
   
   double ArrayAverage(double& array[])
   {
      double summation = 0; 
      for (int iArray = ArraySize(array) - 1; iArray >= 0; iArray--) summation += array[iArray];
      double average =    summation / ArraySize(array);
      if(average!=0)return(average);
      else 
         {
         Print("Error !!!", GetLastError());
         return(0);
         }
   }
   
 //+------------------------------------------------------------------+

void MaAdjuster(int anchorPeriod, int number)
{
if(anchorPeriod==PERIOD_H1)
{
switch(number) //convert to daily MA
{
case PERIOD_M1:MyMAMultiplier=60;break;
case PERIOD_M5:MyMAMultiplier=12;break;
case PERIOD_M15:MyMAMultiplier=4;break;
case PERIOD_M30:MyMAMultiplier=2;break;
case PERIOD_H1:MyMAMultiplier=1;break;
case PERIOD_H4:MyMAMultiplier=0.25;break;
case PERIOD_D1:MyMAMultiplier=0.042;break;
}
}
if(anchorPeriod==PERIOD_H4)
{
switch(number) //convert to daily MA
{
case PERIOD_M1:MyMAMultiplier=240;break;
case PERIOD_M5:MyMAMultiplier=48;break;
case PERIOD_M15:MyMAMultiplier=16;break;
case PERIOD_M30:MyMAMultiplier=8;break;
case PERIOD_H1:MyMAMultiplier=4;break;
case PERIOD_H4:MyMAMultiplier=1;break;
case PERIOD_D1:MyMAMultiplier=0.1667;break;
}
}
if(anchorPeriod==PERIOD_D1)
{
switch(number) //convert to daily MA
{
case PERIOD_M1:MyMAMultiplier=3600;break;
case PERIOD_M5:MyMAMultiplier=288;break;
case PERIOD_M15:MyMAMultiplier=96;break;
case PERIOD_M30:MyMAMultiplier=48;break;
case PERIOD_H1:MyMAMultiplier=24;break;
case PERIOD_H4:MyMAMultiplier=6;break;
case PERIOD_D1:MyMAMultiplier=1;break;
}
}
}

string tf2txt(int tf)
{
if(tf==PERIOD_M1) return("M1");
if(tf==PERIOD_M5) return("M5");
if(tf==PERIOD_M15) return("M15");
if(tf==PERIOD_M30) return("M30");
if(tf==PERIOD_H1) return("H1");
if(tf==PERIOD_H4) return("H4");
if(tf==PERIOD_D1) return("D1");
if(tf==PERIOD_W1) return("W1");
if(tf==PERIOD_MN1) return("MN1");
//----
return("??");
}
//+------------------------------------------------------------------+

//--- indicator short name
int IndiShortName(int maMethod)
{
   string short_name;
   switch(maMethod)
   {
   case MODE_SMA : short_name="SMA("; break;
   case MODE_EMA : short_name="EMA(";  break;
   case MODE_SMMA : short_name="SMMA("; break;
   case MODE_LWMA : short_name="LWMA("; break;
   default : return(INIT_FAILED);
   }
   IndicatorShortName(short_name+string(maMethod)+")");
   IndicatorDigits(Digits);
   return(0);
}