Indicator AFIRMA - Autoregressive Finite Impulse Response Moving Average

AFIRMA - Autoregressive Finite Impulse Response Moving Average

Technical Forex Market Indicator
AFIRMA
Technical Forex Market Indicator
AFIRMA
Technical Forex Market Indicator
AFIRMA
Technical Forex Market Indicator
AFIRMA
Technical Forex Market Indicator
AFIRMA
Technical Forex Market Indicator
AFIRMA
Technical Forex Market Indicator
AFIRMA
Technical Forex Market Indicator
AFIRMA









Indicator AFIRMA (Autoregressive Finite Impulse Response Moving Average)is a very interesting technical indicator, where forms the basis Moving average.  Based on the digital filter accurately shows the price movement, though with a time lag. As you can see in the figures AFIRMA (blue) in combination with Moving average - MA (red), indicating above average good signals based on fitting the smooth function (polynomial or a sin / cos like in Fourier transform) has no lag but often shows the price movement not so well. The condition of combined moving average and its first derivative continuity is set at two moving averages crossing. As a result, we have the smooth moving average that accurately tracks the prices without a time lag. For better business results should be combined with indicator Bollinger Bands, Trend Detection Index - TDI, Laguerre RSI indicator, etc.

Indicator AFIRMA MQ4 Code Base (Copy Code)
//+------------------------------------------------------------------+
//|                                                       AFIRMA.mq4 |
//|                                          Copyright © 2006, gpwr. |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, gpwr."
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_width1 2
#property indicator_width2 2
//Global constants
#define pi 3.141592653589793238462643383279502884197169399375105820974944592
//Input parameters
extern int  Periods = 4;   // 1/(2*Periods) sets the filter bandwidth
extern int  Taps    = 21;  // must be an odd number
extern int  Window  = 4;   // selects windowing function
//Global variables
double w[], wsum, sx2, sx3, sx4, sx5, sx6, den; 
int n;
//Indicator buffers
double FIRMA[];
double ARMA[];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int init()
  {
   //Calculate weights
   ArrayResize(w, Taps);
   wsum = 0.0;
   for(int k = 0; k < Taps; k++)
     {
       switch(Window)
         {
           case 1:  w[k] = 1.0; // Rectangular window
                    break;
           case 2:  w[k] = 0.50 - 0.50*MathCos(2.0*pi*k / Taps);   // Hanning window
                    break;
           case 3:  w[k] = 0.54 - 0.46*MathCos(2.0*pi*k / Taps);   // Hamming window
                    break;
           case 4:  w[k] = 0.42 - 0.50*MathCos(2.0*pi*k / Taps) +  
                           0.08*MathCos(4.0*pi*k / Taps);          // Blackman window
                    break;
           case 5:  w[k] = 0.35875 - 0.48829*MathCos(2.0*pi*k / Taps) + 
                           0.14128*MathCos(4.0*pi*k / Taps) - 
                           0.01168*MathCos(6.0*pi*k / Taps);       // Blackman - Harris window
                    break; 
           default: w[k] = 1;                                      //Rectangular window 
                    break;
         }
       if(k != Taps / 2.0) 
           w[k] = w[k]*MathSin(pi*(k - Taps / 2.0) / Periods) / pi / (k - Taps / 2.0);
       wsum += w[k];
     }
//Calculate sums for the least-squares method
   n = (Taps - 1) / 2;
   sx2 = (2*n + 1) / 3.0;
   sx3 = n*(n + 1) / 2.0;
   sx4 = sx2*(3*n*n+3*n - 1) / 5.0;
   sx5 = sx3*(2*n*n+2*n - 1) / 3.0;
   sx6 = sx2*(3*n*n*n*(n + 2) - 3*n+1) / 7.0;
   den = sx6*sx4 / sx5 - sx5;
//Initialize indicator
   IndicatorBuffers(2);
   SetIndexBuffer(0, FIRMA);
   SetIndexBuffer(1, ARMA);
   SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2);
   IndicatorShortName("AFIRMA");
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int deinit()
  {
    return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
//Calculate FIR MA for all bars except for the last n bars
   ArrayInitialize(FIRMA, EMPTY_VALUE);
   for(int i = 0; i <= Bars - Taps; i++)
     {
       FIRMA[i+n] = 0.0;
       for(int k = 0; k < Taps; k++)
           FIRMA[i+n] += Close[i+k]*w[k] / wsum;
     }
   //Calculate regressive MA for the remaining n bars
   double a0 = FIRMA[n];
   double a1 = FIRMA[n] - FIRMA[n+1];
   double sx2y = 0.0;
   double sx3y = 0.0;
   for(i = 0; i <= n; i++)
     {
       sx2y += i*i*Close[n-i];
       sx3y += i*i*i*Close[n-i];
     }
   sx2y = 2.0*sx2y / n / (n + 1);
   sx3y = 2.0*sx3y / n / (n + 1);
   double p = sx2y - a0*sx2 - a1*sx3;
   double q = sx3y - a0*sx3 - a1*sx4;
   double a2 = (p*sx6 / sx5 - q) / den;
   double a3 = (q*sx4 / sx5 - p) / den;
   ArrayInitialize(ARMA, EMPTY_VALUE);
   for(i = 0; i <= n; i++)
       ARMA[n-i] = a0 + i*a1 + i*i*a2 + i*i*i*a3;
   return(0);
  }
//+------------------------------------------------------------------+

Indicator AFIRMA MQ5 Code Base (Copy Code)
//+------------------------------------------------------------------+
//|                                                       AFIRMA.mq5 |
//|                                         Copyright © 2006, gpwr.  |
//|                        More info: http://plusforex.blogspot.com  |
//+------------------------------------------------------------------+
//---- author of the indicator
#property copyright "Copyright © 2006, gpwr."
#property link      ""
//---- indicator version
#property version   "1.00"
//---- drawing the indicator in the main window
#property indicator_chart_window
//---- two buffers are used for calculation and drawing the indicator
#property indicator_buffers 2
//---- only two plots are used
#property indicator_plots   2
//+----------------------------------------------+
//|  Declaration of constants                    |
//+----------------------------------------------+
#define RESET 0
#define pi 3.141592653589793238462643383279502884197169399375105820974944592
//+----------------------------------------------+
//|  Indicator 1 drawing parameters              |
//+----------------------------------------------+
//---- drawing indicator 1 as a line
#property indicator_type1   DRAW_LINE
//---- use blue violet color for the indicator 1 line
#property indicator_color1  BlueViolet
//---- line of the indicator 1 is a continuous line
#property indicator_style1  STYLE_SOLID
//---- indicator 1 line width is equal to 2
#property indicator_width1  2
//---- displaying the indicator line label
#property indicator_label1  "FIRMA"
//+----------------------------------------------+
//|  Indicator 2 drawing parameters              |
//+----------------------------------------------+
//---- drawing the indicator 2 as a line
#property indicator_type2   DRAW_LINE
//---- red color is used for the indicator 2 line
#property indicator_color2  Red
//---- the indicator 2 line is a continuous curve
#property indicator_style2  STYLE_SOLID
//---- indicator 2 line width is equal to 2
#property indicator_width2  2
//---- displaying the indicator line label
#property indicator_label2  "ARMA"
//+----------------------------------------------+
//|  Declaration of enumerations                 |
//+----------------------------------------------+
enum ENUM_WINDOWS   // Type of constant
  {
   Rectangular = 1, // Rectangular window
   Hanning1,        // Hanning window 1
   Hanning2,        // Hanning window 2
   Blackman,        // Blackman window
   Blackman_Harris  // Blackman-Harris window
  };
//+----------------------------------------------+
//|  Indicator input parameters                  |
//+----------------------------------------------+
input int  Periods = 4;               // LF transmission width 1/(2*Periods)
input int  Taps    = 21;              // Number of delay units in the filter
input ENUM_WINDOWS Window=Blackman;   // Window index
input int Shift=0;                    // Horizontal shift of the indicator in bars
//+----------------------------------------------+
//---- declaration of the integer variables for the start of data calculation
int min_rates_total;
//---- declaration of global variables
int n;
double w[],wsum,sx2,sx3,sx4,sx5,sx6,den;
//---- declaration of dynamic arrays that
//---- will be used as indicator buffers
double FIRMABuffer[],ARMABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+  
void OnInit()
  {
//---- initialization of variables  
   ArrayResize(w,Taps);
   wsum=0.0;
   for(int k=0; k<Taps; k++)
     {
      switch(Window)
        {
         case Rectangular: w[k]=1.0; break;                                                       // Rectangular window      
         case Hanning1: w[k]=0.50-0.50*MathCos(2.0*pi*k/Taps); break;                             // Hanning window
         case Hanning2: w[k]=0.54-0.46*MathCos(2.0*pi*k/Taps); break;                             // Hamming window
         case Blackman: w[k]=0.42-0.50*MathCos(2.0*pi*k/Taps)+0.08*MathCos(4.0*pi*k/Taps); break; // Blackman window
         case Blackman_Harris: w[k]=0.35875-0.48829*MathCos(2.0*pi*k/Taps)+0.14128
            *MathCos(4.0*pi*k/Taps)-0.01168*MathCos(6.0*pi*k/Taps);                               // Blackman - Harris window
        }
      if(k!=Taps/2.0) w[k]=w[k]*MathSin(pi*(k-Taps/2.0)/Periods)/pi/(k-Taps/2.0);
      wsum+=w[k];
     }
//---- calculate sums for the least-squares method
   n=(Taps-1)/2;
   sx2 = (2*n + 1) / 3.0;
   sx3 = n*(n + 1) / 2.0;
   sx4 = sx2*(3*n*n+3*n - 1) / 5.0;
   sx5 = sx3*(2*n*n+2*n - 1) / 3.0;
   sx6 = sx2*(3*n*n*n*(n + 2) - 3*n+1) / 7.0;
   den = sx6*sx4 / sx5 - sx5;

//---- initialization of variables of the start of data calculation
   min_rates_total=Taps;

//---- set FIRMABuffer[] dynamic array as an indicator buffer
   SetIndexBuffer(0,FIRMABuffer,INDICATOR_DATA);
//---- shifting the indicator 1 horizontally by Shift
   PlotIndexSetInteger(0,PLOT_SHIFT,Shift);
//---- performing shift of the beginning of counting of drawing the indicator 1 by min_rates_total
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,min_rates_total);
//---- setting the indicator values that won't be visible on a chart
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
//---- indexing the elements in the buffer as timeseries
   ArraySetAsSeries(FIRMABuffer,true);

//---- set ARMABuffer[] dynamic array as an indicator buffer
   SetIndexBuffer(1,ARMABuffer,INDICATOR_DATA);
//---- shifting the indicator 2 horizontally by Shift
   PlotIndexSetInteger(1,PLOT_SHIFT,Shift);
//---- performing shift of the beginning of counting of drawing the indicator 2 by min_rates_total+1
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,min_rates_total);
//---- setting the indicator values that won't be visible on a chart
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE);
//---- indexing the elements in the buffer as timeseries
   ArraySetAsSeries(ARMABuffer,true);

//---- initializations of a variable for the indicator short name
   string shortname;
   StringConcatenate(shortname,
                     "AFIRMA(",Periods,", ",Taps,", ",EnumToString(Window),", ",Shift,")");
//--- creation of the name to be displayed in a separate sub-window and in a tooltip
   IndicatorSetString(INDICATOR_SHORTNAME,shortname);
//--- determination of accuracy of displaying the indicator values
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//----
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,    // number of bars in history at the current tick
                const int prev_calculated,// number of bars calculated at previous call
                const int begin,          // bars reliable counting beginning index
                const double &price[])    // price array for the indicator calculation
  {
//---- checking the number of bars to be enough for the calculation
   if(rates_total<min_rates_total+begin) return(RESET);

//---- declarations of local variables
   int limit,bar;
   double a0,a1,a2,a3,sx2y,sx3y,p,q;

//---- calculation of the 'limit' starting index for the bars recalculation loop
   if(prev_calculated>rates_total || prev_calculated<=0)// checking for the first start of the indicator calculation
     {
      limit=rates_total-1-min_rates_total-begin; // starting index for calculation of all bars
      //---- performing the shift of the beginning of the indicators drawing
      PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,min_rates_total+begin);
      PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,min_rates_total+begin);
     }
   else limit=rates_total-prev_calculated; // starting index for calculation of new bars

//---- indexing elements in arrays as timeseries  
   ArraySetAsSeries(price,true);

//---- main cycle of calculation of FIRMA indicator
   for(bar=limit; bar>=0; bar--)
     {
      FIRMABuffer[bar+n]=0.0;
      for(int k=0; k<Taps; k++) FIRMABuffer[bar+n]+=price[bar+k]*w[k]/wsum;
     }

//----  initialize indicator buffers
   for(bar=limit; bar>=0; bar--)
     {
      if(bar<n) FIRMABuffer[bar]=EMPTY_VALUE;
      ARMABuffer[bar]=EMPTY_VALUE;
     }

//---- calculate regressive MA for the remaining n bars
   a0 = FIRMABuffer[n];
   a1 = FIRMABuffer[n]-FIRMABuffer[n+1];
   sx2y = 0.0;
   sx3y = 0.0;

   for(int i=0; i<=n; i++)
     {
      sx2y += i*i*price[n-i];
      sx3y += i*i*i*price[n-i];
     }

   sx2y = 2.0*sx2y / n / (n + 1);
   sx3y = 2.0*sx3y / n / (n + 1);
   p = sx2y - a0*sx2 - a1*sx3;
   q = sx3y - a0*sx3 - a1*sx4;
   a2 = (p*sx6 / sx5 - q) / den;
   a3 = (q*sx4 / sx5 - p) / den;

   for(int k=0; k<=n; k++) ARMABuffer[n-k]=a0+k*a1+k*k*a2+k*k*k*a3;
//----    
   return(rates_total);
  }
//+------------------------------------------------------------------+