Need help with iHighest & iLowest appearing on the wrong side of the Moving Average

 

Hi,

The following indicator has been coded to show only above or below the MA, however, this is not showing as expect.

Can someone point out the error in the code for me?

Thank you.

Regards,

John


//+------------------------------------------------------------------+
//|                                             Swing_Point_v0.1.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, 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 Swing High
#property indicator_label1    "Swing high"
#property indicator_type1     DRAW_ARROW
#property indicator_color1    clrGoldenrod
#property indicator_style1    STYLE_SOLID
#property indicator_width1    2
//--- plot Swing High
#property indicator_label2    "Swing Low"
#property indicator_type2     DRAW_ARROW
#property indicator_color2    clrSteelBlue
#property indicator_style2    STYLE_SOLID
#property indicator_width1    2
//--- input parameters
input int   PeriodsInMajorSwing  =  13;
input int   Inp_MA_period        =  50;
//--- indicator buffers
double   SwingHighBuffer[];
double   SwingLowBuffer[];
double   MABuffer[];
//--- indicator handles
int      handle_iMA;
int      bars_calculated   =  0;
bool     m_init_error      =  false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,SwingHighBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SwingLowBuffer,INDICATOR_DATA);
//---
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
//---
   PlotIndexSetInteger(0,PLOT_ARROW,159);
   PlotIndexGetInteger(1,PLOT_ARROW,159);
//---
   PlotIndexSetInteger(0,PLOT_ARROW_SHIFT,-10);
   PlotIndexSetInteger(1,PLOT_ARROW_SHIFT,10);
//---
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);    
//---
   ArraySetAsSeries(SwingHighBuffer,true);
   ArraySetAsSeries(SwingLowBuffer,true);
//--- create handle of Moving Average
   handle_iMA=iMA(Symbol(),Period(),Inp_MA_period,0,MODE_SMMA,PRICE_CLOSE);
   if(handle_iMA==INVALID_HANDLE)
   {
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
      Symbol(),
      EnumToString(Period()),
      GetLastError());
      m_init_error=true;
      return(INIT_SUCCEEDED);
   }
//---
   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_MA_period)
      return(0);
//---
   int values_to_copy;
   int calculated = BarsCalculated(handle_iMA);
   if(calculated<=0)
      {
         PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
         return(0);
      }
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
      {
         if(calculated>rates_total)
            values_to_copy=rates_total;
         else
            values_to_copy=calculated;
      }
   else
      {
         values_to_copy=(rates_total-prev_calculated)+1;
      }   
   if(!FillArrayFromBuffer(MABuffer,0,handle_iMA,values_to_copy))
      return(0);
   bars_calculated = calculated;   
//---      
   int limit=prev_calculated-1;
   if(prev_calculated==0)
      {
         SwingHighBuffer[0]=0.0;
         SwingLowBuffer[0]=0.0;
         limit=1;
      }
//---
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);  
//---
   for(int i=limit; i<rates_total; i++)
      {
         SwingHighBuffer[i] =  0.0;
         SwingLowBuffer[i]  =  0.0;
         //--- Swing High
         int N = iHighest(Symbol(),Period(),MODE_HIGH,(PeriodsInMajorSwing*2),i);
         if((high[N]>high[N-1]) && (close[N]<MABuffer[N]))
            {
               SwingHighBuffer[N]=high[N];
            }
         //--- Swing Low
         int O = iLowest(Symbol(),Period(),MODE_LOW,(PeriodsInMajorSwing*2),i);
         if((low[O]<low[O-1]) && (close[N]>MABuffer[N]))
            {
               SwingLowBuffer[O]=low[O];
            }  
           
      }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Filling indicator buffers from the MA indicator                  |
//+------------------------------------------------------------------+
bool FillArrayFromBuffer(  double &values[], // indicator buffer of Moving Average values
                           int shift, // shift
                           int ind_handle, // handle of the iMA indicator
                           int amount // number of copied values
                        )
{
   ResetLastError();
   if(CopyBuffer(ind_handle,0,-shift,amount,values)<0)
      {
         PrintFormat("Failed to copy data from the iMA indicator, error code %d",GetLastError());
         return(false);
      }
   return(true);
}
Files:
Capture.PNG  76 kb
 
   int limit=prev_calculated-1;
   ⋮
   for(int i=limit; i<rates_total; i++)
      {
         SwingHighBuffer[i] =  0.0;
  1. If prev_calculated is zero, limit is minus one, and buffer[-1] does not exist; array exceeded; indicator crashes.
  2. See How to do your lookbacks correctly #9#14 & #19.

 

Hi Willaim,

Please ignore previous post.

Did some amendments to the code, the previous issue was solved, however, now, i have a new issue, there are multiply iHighest instead of just the 1 particular point.

Will it make sense to put them all into an array and then pick it up from the array?

Regards,

John

//+------------------------------------------------------------------+
//|                                             Swing_Point_v0.1.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, 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 Swing High
#property indicator_label1    "Swing high"
#property indicator_type1     DRAW_ARROW
#property indicator_color1    clrGoldenrod
#property indicator_style1    STYLE_SOLID
#property indicator_width1    2
//--- plot Swing High
#property indicator_label2    "Swing Low"
#property indicator_type2     DRAW_ARROW
#property indicator_color2    clrSteelBlue
#property indicator_style2    STYLE_SOLID
#property indicator_width1    2
//--- input parameters
input int   PeriodsInMajorSwing  =  13;
input int   Inp_MA_period        =  50;
//--- indicator buffers
double   SwingHighBuffer[];
double   SwingLowBuffer[];
double   MABuffer[];
//--- indicator handles
int      handle_iMA;
int      bars_calculated   =  0;
bool     m_init_error      =  false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,SwingHighBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SwingLowBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,MABuffer,INDICATOR_DATA);
//---
   //IndicatorSetInteger(INDICATOR_DIGITS,Digits());
//---
   PlotIndexSetInteger(0,PLOT_ARROW,159);
   PlotIndexGetInteger(1,PLOT_ARROW,159);
//---
   PlotIndexSetInteger(0,PLOT_ARROW_SHIFT,-10);
   PlotIndexSetInteger(1,PLOT_ARROW_SHIFT,10);
//---
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);    
//---
   ArraySetAsSeries(SwingHighBuffer,true);
   ArraySetAsSeries(SwingLowBuffer,true);
//--- create handle of Moving Average
   handle_iMA=iMA(Symbol(),Period(),Inp_MA_period,0,MODE_SMMA,PRICE_CLOSE);
   if(handle_iMA==INVALID_HANDLE)
   {
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
      Symbol(),
      EnumToString(Period()),
      GetLastError());
      m_init_error=true;
      return(INIT_SUCCEEDED);
   }
//---
   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_MA_period)
      return(0);
//---
   int values_to_copy;
   int calculated = BarsCalculated(handle_iMA);
   if(calculated<=0)
      {
         PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
         return(0);
      }
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
      {
         if(calculated>rates_total)
            values_to_copy=rates_total;
         else
            values_to_copy=calculated;
      }
   else
      {
         values_to_copy=(rates_total-prev_calculated)+1;
      }   
   if(!FillArrayFromBuffer(MABuffer,0,handle_iMA,values_to_copy))
      return(0);
   bars_calculated = calculated;   
//---      
   int limit=prev_calculated+1;
   if(prev_calculated==0)
      {
         SwingHighBuffer[0]=0.0;
         SwingLowBuffer[0]=0.0;
         limit=1;
      }
//---
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);  
//---
   for(int i=limit; i<rates_total; i++)
      {
         SwingHighBuffer[i] =  0.0;
         SwingLowBuffer[i]  =  0.0;
         //--- Swing High
         int N = iHighest(Symbol(),Period(),MODE_HIGH,(PeriodsInMajorSwing*2),i);
         /*if((high[N]>high[N-1]) && (close[N]<MABuffer[N]))
            {
               SwingHighBuffer[N]=high[N];
            }*/
         //--- Swing Low
         int O = iLowest(Symbol(),Period(),MODE_LOW,(PeriodsInMajorSwing*2),i);
         /*if((low[O]<low[O-1]) && (close[N]>MABuffer[N]))
            {
               SwingLowBuffer[O]=low[O];
            }*/  
         if((high[i]==iHigh(Symbol(),Period(),iHighest(Symbol(),Period(),MODE_HIGH,(PeriodsInMajorSwing*2),i))) && (close[i]<MABuffer[i]))
            {
               SwingHighBuffer[i]=high[i];
            }
         if((low[i]==iLow(Symbol(),Period(),O)) && (close[i]>MABuffer[i]))
            {
               SwingHighBuffer[i]=high[i];
            }   
              
      }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Filling indicator buffers from the MA indicator                  |
//+------------------------------------------------------------------+
bool FillArrayFromBuffer(  double &values[], // indicator buffer of Moving Average values
                           int shift, // shift
                           int ind_handle, // handle of the iMA indicator
                           int amount // number of copied values
                        )
{
   ResetLastError();
   if(CopyBuffer(ind_handle,0,-shift,amount,values)<0)
      {
         PrintFormat("Failed to copy data from the iMA indicator, error code %d",GetLastError());
         return(false);
      }
   return(true);
}