Henderson's filter

 

Hello,

I have developed the Henderson filter in MQL4, but there is the problem that there are apparently miscalculations at the end. I searched for a long time and did not find the error. Thank you in advance.

//+------------------------------------------------------------------+
//|                                           Henderson's filter.mq4 |
//|                                        Copyright 2018, Arthur S. |
//|                    https://www.mql5.com/de/users/michael12345678 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, Arthur S."
#property link      "https://www.mql5.com/de/users/michael12345678"
#property version   "1.00"
#property strict

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   1
#property indicator_label1  "Henderson's filter"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrCrimson
#property indicator_width1  2

input int                inpPeriod = 32;          // Period
input ENUM_APPLIED_PRICE inpPrice  = PRICE_CLOSE; // Price

double val[],prices[],weights[];
int _filterSize,_half,_size;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0,val,INDICATOR_DATA); 
   SetIndexBuffer(1,prices,INDICATOR_CALCULATIONS); 
   //
   //---
   //
      _filterSize = MathMax(inpPeriod,3);
         if (MathMod(_filterSize,2)==0) _filterSize++; ArrayResize(weights,_filterSize);
         double m = MathFloor(_filterSize/2.0); _half = (int)m;
         double divisor = 8.0*(m+2.0)*((m+2.0)*(m+2.0)-1.0)*(4.0*(m+2.0)*(m+2)-1.0)*(4.0*(m+2.0)*(m+2.0)-9.0)*(4.0*(m+2.0)*(m+2.0)-25.0);  
         for (int j=-_half; j<=_half; j++)
            weights[j+_half] = 315.0*((m+1.0)*(m+1.0)-(j*j))*((m+2.0)*(m+2.0)-(j*j))*((m+3.0)*(m+3.0)-(j*j))*(3.0*(m+2.0)*(m+2.0)-11.0*(j*j)-16.0)/divisor;
            _size = ArraySize(weights);
   //
   //---            
   //
   IndicatorSetString(INDICATOR_SHORTNAME,"Henderson's filter ("+string(inpPeriod)+")");
   
   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(Bars(_Symbol,_Period)<rates_total) return(-1);
   for (int i=(int)MathMax(prev_calculated-_half,0); i<rates_total; i++)
   {
      double mod = 1.0;
      if ((rates_total-i-1)<_half)
      {
         double weightTotal = 0; for (int k=_half-(rates_total-i-1); k<_size; k++) weightTotal += weights[k]; mod = 1.0/weightTotal;               
      }
      //
      //---
      //
      double sum = mod*weights[_half]*getPrice(inpPrice,open,close,high,low,i,rates_total);
      for(int j=1; j<=_half; j++)
      {
         if (i-j>=0         ) sum += mod*weights[_half+j]*getPrice(inpPrice,open,close,high,low,i-j,rates_total);
         if (i+j<rates_total) sum += mod*weights[_half-j]*getPrice(inpPrice,open,close,high,low,i+j,rates_total);
      }
      val[i] = sum;
   }    
   
   return(rates_total);
}
//+------------------------------------------------------------------+
double getPrice(ENUM_APPLIED_PRICE tprice,const double &open[],const double &close[],const double &high[],const double &low[],int i,int _bars)
  {
   if(i>=0)
      switch(tprice)
        {
         case PRICE_CLOSE:     return(close[i]);
         case PRICE_OPEN:      return(open[i]);
         case PRICE_HIGH:      return(high[i]);
         case PRICE_LOW:       return(low[i]);
         case PRICE_MEDIAN:    return((high[i]+low[i])/2.0);
         case PRICE_TYPICAL:   return((high[i]+low[i]+close[i])/3.0);
         case PRICE_WEIGHTED:  return((high[i]+low[i]+close[i]+close[i])/4.0);
        }
   return(0);
  }
Files:
 
//+------------------------------------------------------------------+
//|                                           Henderson's filter.mq4 |
//|                                        Copyright 2018, Arthur S. |
//|                    https://www.mql5.com/de/users/michael12345678 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, Arthur S."
#property link      "https://www.mql5.com/de/users/michael12345678"
#property version   "1.00"
#property strict

#property indicator_chart_window
#property indicator_buffers 1     //#property indicator_buffers 2
#property indicator_plots   1
#property indicator_label1  "Henderson's filter"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrCrimson
#property indicator_width1  2

input int                inpPeriod = 32;          // Period
input ENUM_APPLIED_PRICE inpPrice  = PRICE_CLOSE; // Price

double val[],weights[];    //double val[],prices[],weights[];
int _filterSize,_half,_size;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,val,INDICATOR_DATA);
//SetIndexBuffer(1,prices,INDICATOR_CALCULATIONS); 
//
//---
//
   _filterSize=MathMax(inpPeriod,3);
   if(MathMod(_filterSize,2)==0) _filterSize++; ArrayResize(weights,_filterSize);
   double m=MathFloor(_filterSize/2.0); _half=(int)m;
   double divisor=8.0*(m+2.0)*((m+2.0)*(m+2.0)-1.0)*(4.0*(m+2.0)*(m+2)-1.0)*(4.0*(m+2.0)*(m+2.0)-9.0)*(4.0*(m+2.0)*(m+2.0)-25.0);
   for(int j=-_half; j<=_half; j++)
      weights[j+_half]=315.0*((m+1.0)*(m+1.0)-(j*j))*((m+2.0)*(m+2.0)-(j*j))*((m+3.0)*(m+3.0)-(j*j))*(3.0*(m+2.0)*(m+2.0)-11.0*(j*j)-16.0)/divisor;
   _size=ArraySize(weights);
//
//---            
//
   IndicatorSetString(INDICATOR_SHORTNAME,"Henderson's filter ("+string(inpPeriod)+")");

   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[])
  {
   int limit;

   if(Bars(_Symbol,_Period)<rates_total)
      return(-1);
   if(prev_calculated==0)
      limit=rates_total-_half;
   else
      limit=rates_total-prev_calculated+_half;

   for(int i=0; i<=limit; i++)
     {
      double mod=1.0;
      if(i<_half)
        {
         double weightTotal=0;
         for(int k=_half-i; k<_size; k++)
            weightTotal+=weights[k];
         if(weightTotal!=0.0)
            mod=1.0/weightTotal;
        }

      double sum=mod*weights[_half]*getPrice(i);

      for(int j=1; j<=_half; j++)
        {
         if (j <= i) 
            sum+=mod*weights[_half+j]*getPrice(i-j);

         sum+=mod*weights[_half-j]*getPrice(i+j);
        }

      val[i]=sum;
     }
/*
   if(Bars(_Symbol,_Period)<rates_total) return(-1);
   for (int i=(int)MathMax(prev_calculated-_half,0); i<rates_total; i++)
   {
      double mod = 1.0;
      if ((rates_total-i-1)<_half)
      {
         double weightTotal = 0; for (int k=_half-(rates_total-i-1); k<_size; k++) weightTotal += weights[k]; mod = 1.0/weightTotal;               
      }
      //
      //---
      //
      double sum = mod*weights[_half]*getPrice(inpPrice,open,close,high,low,i,rates_total);
      for(int j=1; j<=_half; j++)
      {
         if (i-j>=0         ) sum += mod*weights[_half+j]*getPrice(inpPrice,open,close,high,low,i-j,rates_total);
         if (i+j<rates_total) sum += mod*weights[_half-j]*getPrice(inpPrice,open,close,high,low,i+j,rates_total);
      }
      val[i] = sum;
   }    
   */

   return(rates_total);
  }
//+------------------------------------------------------------------+
double getPrice(int shift)
  {
   return (iMA(NULL, 0, 1, 0, MODE_SMA, inpPrice, shift));
  }
  
/*
double getPrice(ENUM_APPLIED_PRICE tprice,const double &open[],const double &close[],const double &high[],const double &low[],int i,int _bars)
  {
   if(i>=0)
      switch(tprice)
        {
         case PRICE_CLOSE:     return(close[i]);
         case PRICE_OPEN:      return(open[i]);
         case PRICE_HIGH:      return(high[i]);
         case PRICE_LOW:       return(low[i]);
         case PRICE_MEDIAN:    return((high[i]+low[i])/2.0);
         case PRICE_TYPICAL:   return((high[i]+low[i]+close[i])/3.0);
         case PRICE_WEIGHTED:  return((high[i]+low[i]+close[i]+close[i])/4.0);
        }
   return(0);
  }
*/
//+------------------------------------------------------------------+
 

A multicolor indicator can be downloaded from the following URL.

https://www.mql5.com/en/forum/174385/page621

However, some modification is required.

line 28

extern double sdvig = 0.0; //extern double sdvig = 0.0025; 

line 49

SetIndexBuffer (0, buffer1); SetIndexStyle (0, DRAW_LINE); //SetIndexBuffer (0, buffer1); 
Coding help
Coding help
  • 2016.04.11
  • www.mql5.com
Hi, Mr. Guru could you please help me to constantly refresh an ea after each tick movement...
Reason: