//+------------------------------------------------------------------+
//|                                       Custom Moving Averages.mq4 |
//|                   Copyright 2005-2015, MetaQuotes Software Corp. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2019 Duc Anh"
#property link "email: expdal3@gmail.com"
#property description "RSI on 2 Moving Average of Different Timeframe"
#property strict

#property indicator_separate_window
#property indicator_minimum    0
#property indicator_maximum    100
#property indicator_level1     45.0
#property indicator_level2     55.0
#property indicator_level3     65.0

#property indicator_buffers 5
#property indicator_color1 clrSienna
#property indicator_color2 clrAliceBlue
#property indicator_color3 clrGold
#property indicator_color4 clrGold
//--- indicator parameters
// MA line 1 (Fast)
extern int InpMAPeriod1=5; // Period
extern ENUM_TIMEFRAMES InpTIMEFRAME1=PERIOD_H1; //FastMA Anchor Timeframe
extern int InpMAShift1=0; // Shift
input ENUM_MA_METHOD InpMAMethod1=MODE_EMA; // Method

// MA line 2 (Slow)
extern int InpMAPeriod2=21; // Period
extern ENUM_TIMEFRAMES InpTIMEFRAME2=PERIOD_H1; //FastMA Anchor Timeframe
extern int InpMAShift2=0; // Shift
input ENUM_MA_METHOD InpMAMethod2=MODE_EMA; // Method

// inputs for MaRS
extern int InpMAPeriod_RS=30; // Period look back for MaRS
extern int MaRS_Avg_period=30; // Period computing MaRS average


int adjustedMA1, adjustedMA2;

//--- indicator buffer

double MaLine1Buffer[], MaLine2Buffer[], MaRSBuffer[], MaRS_Avg[];
double Trend[], State[]; //array for trendup/down

//Array to computing MaDiff
//double MaDiff[];

double MyMAMultiplier;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit(void)
{

ArraySetAsSeries(MaLine1Buffer,true);
ArraySetAsSeries(MaLine2Buffer,true);
ArraySetAsSeries(MaRSBuffer,true);

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);
SetIndexStyle(0,DRAW_NONE);
SetIndexShift(0,InpMAShift1);
SetIndexDrawBegin(0,draw_begin);
SetIndexLabel(0,"MaRS:MaFast"+tf2txt(InpTIMEFRAME1));

SetIndexBuffer(1,MaLine2Buffer);
SetIndexStyle(1,DRAW_NONE);
SetIndexShift(1,InpMAShift2);
SetIndexDrawBegin(1,draw_begin);
SetIndexLabel(1,"MaRS:MaSlow"+tf2txt(InpTIMEFRAME2));

SetIndexBuffer(2,MaRSBuffer);
SetIndexStyle(2,DRAW_LINE,STYLE_SOLID,2);
SetIndexDrawBegin(2,draw_begin);
SetIndexLabel(2,"MaRS"+tf2txt(InpTIMEFRAME_RS));

SetIndexBuffer(3,MaRS_Avg);
SetIndexStyle(3,DRAW_LINE,STYLE_SOLID,1);
SetIndexDrawBegin(3,draw_begin);
SetIndexLabel(3,"MaRS:Avg"+tf2txt(InpTIMEFRAME_RS));

SetIndexBuffer(4,Trend);
SetIndexLabel(1,"MaRS:Trend");

//SetIndexBuffer(4,Trend);


//--- 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--; //if the counted bar increase --> reduce 1 back to prev_calculated
//int limit=Bars-counted_bars; //limit = only count new bar added into chart after indi dropped on chart
int limit = MathMin(Bars-counted_bars,Bars-1);

int InpTIMEFRAME_RS = MathMax(InpTIMEFRAME1,InpTIMEFRAME2);
//if(counted_bars==0) limit-=InpMAPeriod_RS;

ArrayResize(Trend,limit);
ArrayResize(State,limit);
//Computing the 2 MAs fast and slow and MaRS
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>=InpMAPeriod_RS)
   {
   //Print("limit:", limit, "MARS_Period", InpMAPeriod_RS);
   //Insert the MARS computation here
   
      double MADiff_array[], MAPosDiff_array[], MANegDiff_array[];
      double MA1_array[], MA2_array[];

      ArrayResize(MADiff_array,limit);
      ArrayResize(MA1_array,limit);
      ArrayResize(MA2_array,limit);
      ArrayResize(MAPosDiff_array,limit);
      ArrayResize(MANegDiff_array,limit);
   
        for(int s = 0; s<limit; s++)
           { 
          //get value of MAh1 and MAh4 value 
           MA1_array[s] = MaLine1Buffer[s]; 
           MA2_array[s] = MaLine2Buffer[s]; 

           MADiff_array[s] = NormalizeDouble(MA1_array[s] - MA2_array[s],4);
           //Print("+++Line128 : ", MA1_array[s], " | ", MA2_array[s], " | ", MADiff_array[s]);

           }
   //Compute the MaRS buffer 
   MaRSBuffer[i] = iRSIOnArray(MADiff_array,0,InpMAPeriod_RS,i);

           }
  }
 //calculate the last x value of MaRSBuffer array
  //ArraySetAsSeries(MaRS_Avg,true);
  for(int i=limit-MaRS_Avg_period; i>=0; i--)
   {
   //initial value
    //string logmsg = "i: " + i + "Size of Array Trend:" + ArraySize(Trend) + " " + iMAOnArray(MaRSBuffer,0,MaRS_Avg_period,0,MODE_SMA,i) ;
    //  Print(logmsg);
      MaRS_Avg[i] = iMAOnArray(MaRSBuffer,0,MaRS_Avg_period,0,MODE_SMA,i);
      Trend[i]   = EMPTY_VALUE;
      State[i]     = State[i+1];
      if (MaRSBuffer[i]>MaRS_Avg[i]) State[i] =  1; //trend up
      if (MaRSBuffer[i]<MaRS_Avg[i]) State[i] = -1; // trend down
    
    // if current bar state is different from previous bar
      if (State[i] != State[i+1]) 
       if (State[i] == 1)
               Trend[i]   = 1;
         else  Trend[i] = -1;
     }
  //Print("MA1 size: ", MaLine1Size, "MA2 size: ", MaLine2Size, "RSBuff: ",MaRSBufferSize, "***",Msg)
//--- return value of prev_calculated for next call
return(0);
}
//---------------------------------------  
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_M30)
      {
         switch(number) //convert to daily MA
         {
         case PERIOD_M1:MyMAMultiplier=30;break;
         case PERIOD_M5:MyMAMultiplier=6;break;
         case PERIOD_M15:MyMAMultiplier=2;break;
         case PERIOD_M30:MyMAMultiplier=1;break;
         case PERIOD_H1:MyMAMultiplier=0.5;break;
         case PERIOD_H4:MyMAMultiplier=0.125;break;
         case PERIOD_D1:MyMAMultiplier=0.0208;break;
         }
      }
      
      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("??");
   }
//+------------------------------------------------------------------+

string trend2txt(int trend)
{
   string trendstr;
   if(trend==1)trendstr="Up";
     if(trend==-1)trendstr="Down";
   return(trendstr);
}
//--- 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);
}