RSI Convergence and Divergence

 

Hi,

Can anyone point me in the right direction for where the error in the code is?

Am trying to get the RSI divergence plotted on the chart however, the arrows are all over the place.

Thank you.

Regards,

John Doe

//+------------------------------------------------------------------+
//|                                            RSI_Divergence_v2.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers   3
#property indicator_plots     2
//-- plot Buy Arrow
#property indicator_label1 "Buy Entry"
#property indicator_type1  DRAW_ARROW
#property indicator_color1 clrGoldenrod
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//-- plot Sell Arrow
#property indicator_label2 "Sell Entry"
#property indicator_type2  DRAW_ARROW
#property indicator_color2 clrSteelBlue
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- input parameters
input int                  Inp_rsi_ma_period     = 14;             // rsi: averaging period
input ENUM_APPLIED_PRICE   Inp_rsi_applied_price = PRICE_CLOSE;    // rsi: type of price or handle
input int                  Inp_rsi_Buffer        = 30;
      int                  OverboughtLevel       = (100-Inp_rsi_Buffer);
      int                  OversoldLevel         = (0+Inp_rsi_Buffer);
//--- indicator buffers
double   BuyEntry[],SellEntry[];
double   RSIBuffer[];
int      left_up_index  = 0,     righ_up_index  = 0,     left_down_index   = 0,     righ_down_index   = 0;
double   left_up_rsi    = 0.0,   righ_up_rsi    = 0.0,   left_down_rsi     = 0.0,   righ_down_rsi     = 0.0;
bool     find_up        = false, find_down      = false;
//--- indicator handles
int      handle_rsi;
int      bars_calculated=0;
bool     m_init_error=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,BuyEntry,INDICATOR_DATA);
   SetIndexBuffer(1,SellEntry,INDICATOR_DATA);
   SetIndexBuffer(2,RSIBuffer,INDICATOR_DATA);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
   PlotIndexSetInteger(0,PLOT_ARROW,241);
   PlotIndexSetInteger(1,PLOT_ARROW,242);
//--- set the vertical shift of arrows in pixels
   PlotIndexSetInteger(0,PLOT_ARROW_SHIFT,5);
   PlotIndexSetInteger(1,PLOT_ARROW_SHIFT,-5);
//--- set as an empty value 0.0
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE);  
//--- create handle of the indicator irsi
   handle_rsi=iRSI(Symbol(),Period(),Inp_rsi_ma_period,Inp_rsi_applied_price);
//--- if the handle is not created 
   if(handle_rsi==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code 
      PrintFormat("Failed to create handle of the irsi indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early 
      return(INIT_FAILED);
     }    
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   if(m_init_error)
      return(0);
   if(rates_total<=Inp_rsi_ma_period)
      return(0);
//---
   int values_to_copy;
//--- determine the number of values calculated in the indicator
   int calculated=BarsCalculated(handle_rsi);
   if(calculated<=0)
      {
      PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
      return(0);
      }
//--- if it is the first start of calculation of the indicator or if the number of values in the iMA indicator changed
//---or if it is necessary to calculated the indicator for two or more bars (it means something has changed in the price history)
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
   {
      //--- if the iMABuffer array is greater than the number of values in the iMA indicator for symbol/period, then we don't copy everything
      //--- otherwise, we copy less than the size of indicator buffers
      if(calculated>rates_total)
         values_to_copy=rates_total;
      else
         values_to_copy=calculated;
      }
   else
   {
      //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate()
      //--- for calculation not more than one bar is added
      values_to_copy=(rates_total-prev_calculated)+1;
   }
//--- fill the array with values of the iRSI indicator
//--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation
   if(!FillArrayFromBuffer(RSIBuffer,handle_rsi,values_to_copy))
      return(0);    
//--- memorize the number of values in the Moving Average indicator
   bars_calculated=calculated;   
//--- main loop  
   int limit=prev_calculated-1;
   if(prev_calculated==0)
      {
         limit=Inp_rsi_ma_period;
         for(int i=0; i<limit; i++)
         {
            BuyEntry[0]=EMPTY_VALUE;
            SellEntry[0]=EMPTY_VALUE;
         }
      }   
   for(int i=limit; i<rates_total; i++)
   {
      BuyEntry[i]=0.0;
      SellEntry[i]=0.0;
      if(left_up_rsi==0.0 && righ_up_rsi==0.0 && left_down_rsi==0.0 && righ_down_rsi==0.0)
        {
         //--- first initialization - when all four variables (***_price) are zero
         if(RSIBuffer[i+1]>70.0 && RSIBuffer[i]>70.0 && RSIBuffer[i-1]>70.0)
            if(RSIBuffer[i+1]<RSIBuffer[i] && RSIBuffer[i]>RSIBuffer[i-1])
              {
               righ_up_rsi=RSIBuffer[i];
               righ_up_index=i;
               continue;
              }
         if(RSIBuffer[i+1]<70.0 && RSIBuffer[i]<70.0 && RSIBuffer[i-1]<70.0)
            if(RSIBuffer[i+1]>RSIBuffer[i] && RSIBuffer[i]<RSIBuffer[i-1])
              {
               righ_down_rsi=RSIBuffer[i];
               righ_down_index=i;
               continue;
              }
        }
      else
        {
         //--- sell signal
         if(left_up_rsi==0.0 || righ_up_rsi==0.0 || !find_down)
           {
            //--- divergence search "UP"
            if(righ_up_rsi==0)
              {
               if(RSIBuffer[i+1]>70.0 && RSIBuffer[i]>70.0 && RSIBuffer[i-1]>70.0)
                  if(RSIBuffer[i+1]<RSIBuffer[i] && RSIBuffer[i]>RSIBuffer[i-1])
                    {
                     righ_up_rsi=RSIBuffer[i];
                     righ_up_index=i;
                     continue;
                    }
              }
            else if(!find_down)
              {
               if(RSIBuffer[i]<70.0 && RSIBuffer[i]>30.0)
                 {
                  find_down=true;continue;
                 }
              }
            else
              {
               if(RSIBuffer[i+1]>70.0 && RSIBuffer[i]>70.0 && RSIBuffer[i-1]>70.0)
                  if(RSIBuffer[i+1]<RSIBuffer[i] && RSIBuffer[i]>RSIBuffer[i-1])
                    {
                     left_up_rsi=RSIBuffer[i];left_up_index=i;
                     //--- сheck all prices "Close"
                     if(left_up_rsi>righ_up_rsi && close[left_up_index]<close[righ_up_index])
                       {
                           SellEntry[i]=low[i];
                       }
                     return(true);
                    }
              }
           }
        //--- buy signal
         if(left_down_rsi==0.0 || righ_down_rsi==0.0 || !find_up)
           {
            //--- divergence search "DOWN"
            if(righ_down_rsi==0)
              {
               if(RSIBuffer[i+1]<70.0 && RSIBuffer[i]<70.0 && RSIBuffer[i-1]<70.0)
                  if(RSIBuffer[i+1]>RSIBuffer[i] && RSIBuffer[i]<RSIBuffer[i-1])
                    {
                     righ_down_rsi=RSIBuffer[i];
                     righ_down_index=i;
                     continue;
                    }
              }
            else if(!find_up)
              {
               if(RSIBuffer[i]<70.0 && RSIBuffer[i]>30.0)
                 {
                  find_up=true;continue;
                 }
              }
            else
              {
               if(RSIBuffer[i+1]<70.0 && RSIBuffer[i]<70.0 && RSIBuffer[i-1]<70.0)
                  if(RSIBuffer[i+1]>RSIBuffer[i] && RSIBuffer[i]<RSIBuffer[i-1])
                    {
                     left_down_rsi=RSIBuffer[i];left_down_index=i;
                     //--- сheck all prices "Close"
                     if(left_down_rsi<righ_down_rsi && close[left_down_index]>close[righ_down_index])
                       {
                           BuyEntry[i]=high[i];
                       }
                     return(true);
                    }
              }
           }
        }
   }   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Filling indicator buffers from the iRSI indicator                |
//+------------------------------------------------------------------+
bool FillArrayFromBuffer(double &rsi_buffer[],  // indicator buffer of Relative Strength Index values
                         int ind_handle,        // handle of the iRSI indicator
                         int amount             // number of copied values
                        )
  {
//--- reset error code
   ResetLastError();
//--- fill a part of the iRSIBuffer array with values from the indicator buffer that has 0 index
   if(CopyBuffer(ind_handle,0,0,amount,rsi_buffer)<0)
     {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the iRSI indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
//--- everything is fine
   return(true);
  }   
//+------------------------------------------------------------------+