1

I've converted the AFIRMA indicator from MQL4 to C#. It outputs the first series correctly (FIRMA) but the second one is stuck somewhere in the code (ARMA). Any ideas where or what keeps it from outputting? It seems like it's stuck somewhere.

Thank you for your time.

namespace cAlgo.Indicators
{
[Indicator(ScalePrecision = 5, AutoRescale = true, IsOverlay = true, AccessRights = AccessRights.None)]
public class AFIRMA : Indicator
{


    [Parameter("Periods", DefaultValue = 12)]
    public int Periods { get; set; }

    [Parameter("Taps", DefaultValue = 25)]
    public int Taps { get; set; }

    [Parameter("Window", DefaultValue = 4)]
    public int Window { get; set; }



    [Output("FIRMA", Color = Colors.Blue, PlotType = PlotType.DiscontinuousLine)]
    public IndicatorDataSeries FIRMA { get; set; }
    [Output("ARMA", Color = Colors.Red, PlotType = PlotType.DiscontinuousLine)]
    public IndicatorDataSeries ARMA { get; set; }


    int n;
    double den;
    double sx6;
    double sx5;
    double sx4;
    double sx3;
    double sx2;
    double wsum;
    double[] w;

    protected override void Initialize()
    {
        //Calculate weights
        Array.Resize(ref w, Taps);
        wsum = 0.0;
        for (int k = 0; k < Taps; k++)
        {
            switch (Window)
            {
                case 1:
                    w[k] = 1.0;
                    break;
                case 2:
                    w[k] = 0.5 - 0.5 * Math.Cos(2.0 * Math.PI * k / Taps);
                    break;
                case 3:
                    w[k] = 0.54 - 0.46 * Math.Cos(2.0 * Math.PI * k / Taps);
                    break;
                case 4:
                    w[k] = 0.42 - 0.5 * Math.Cos(2.0 * Math.PI * k / Taps) + 0.08 * Math.Cos(4.0 * Math.PI * k / Taps);
                    break;
                case 5:
                    w[k] = 0.35875 - 0.48829 * Math.Cos(2.0 * Math.PI * k / Taps) + 0.14128 * Math.Cos(4.0 * Math.PI * k / Taps) - 0.01168 * Math.Cos(6.0 * Math.PI * k / Taps);
                    break;
                default:
                    w[k] = 1;
                    break;
            }
            if (k != Taps / 2.0)
                w[k] = w[k] * Math.Sin(Math.PI * (k - Taps / 2.0) / Periods) / Math.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;
    }


    public override void Calculate(int index)
    {
        //Calculate FIR MA for all bars except for the last n bars
        for (int i = 0; i <= Bars - Taps; i++)
        {
            FIRMA[i + n] = 0.0;
            for (int k = 0; k < Taps; k++)
                FIRMA[i + n] += MarketSeries.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 (int i = 0; i <= n; i++)
        {
            sx2y += i * i * MarketSeries.Close[n - i];
            sx3y += i * i * i * MarketSeries.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;
        for (int i = 0; i <= n; i++)
        {
            ARMA[n - i] = a0 + i * a1 + i * i * a2 + i * i * i * a3;
            return;
        }
    }


    private int Bars
    {
        get { return MarketSeries.Close.Count; }
    }

}

}

MQL4 reference code:

#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 Copyright: Vladimir (Copyright © 2006, gpwr) Link: https://www.mql5.com/ru/code/11186

How it should look:

Dark Blue and Dark Red lines: Original and proper way the indicator should Output. Bright Blue line: How this specific code is outputting and Orange line which does not output at all. enter image description here

Addendum from a comment below:

enter image description here

All the values of variables used:

The output seems to have everything it needs in order to render but still, something is preventing it to do so. Even with an offsetted output it should still render something on the chart. That's why I chose to set an Autoscale to see if anything pops up anytime.

enter image description here

Update: Almost Done!

I've managed to fix the Outputting problem for ARMA. It was a problem of indexing. But on a new bar, I see, some variables don't render anymore and the output completely disappears. If i go hit build for the indicator code it renders again for 1 bar(dynamic fluctuations within the variables during the present candle are happening, so it works just fine, up until the new bar). This should be the last issue to fix and we can call it a solved case. Anyone? Any ideas?

enter image description here enter image description here

namespace cAlgo.Indicators
{
[Indicator(ScalePrecision = 5, AutoRescale = true, IsOverlay = true, AccessRights = AccessRights.None)]
public class AFIRMA: Indicator
{


    [Parameter("Periods", DefaultValue = 15)]
    public int Periods { get; set; }

    [Parameter("Taps", DefaultValue = 31)]
    public int Taps { get; set; }

    [Parameter("Window", DefaultValue = 4)]
    public int Window { get; set; }



    [Output("FIRMA", Color = Colors.Blue, PlotType = PlotType.DiscontinuousLine)]
    public IndicatorDataSeries FIRMA { get; set; }
    [Output("ARMA", Color = Colors.Red, PlotType = PlotType.DiscontinuousLine)]
    public IndicatorDataSeries ARMA { get; set; }


    int n;
    double den;
    double sx6;
    double sx5;
    double sx4;
    double sx3;
    double sx2;
    double wsum;
    double[] w;

    protected override void Initialize()
    {

        //Calculate weights
        Array.Resize(ref w, Taps);
        wsum = 0.0;
        for (int k = 0; k < Taps; k++)
        {
            switch (Window)
            {
                case 1:
                    w[k] = 1.0;
                    break;
                case 2:
                    w[k] = 0.5 - 0.5 * Math.Cos(2.0 * Math.PI * k / Taps);
                    break;
                case 3:
                    w[k] = 0.54 - 0.46 * Math.Cos(2.0 * Math.PI * k / Taps);
                    break;
                case 4:
                    w[k] = 0.42 - 0.5 * Math.Cos(2.0 * Math.PI * k / Taps) + 0.08 * Math.Cos(4.0 * Math.PI * k / Taps);
                    break;
                case 5:
                    w[k] = 0.35875 - 0.48829 * Math.Cos(2.0 * Math.PI * k / Taps) + 0.14128 * Math.Cos(4.0 * Math.PI * k / Taps) - 0.01168 * Math.Cos(6.0 * Math.PI * k / Taps);
                    break;
                default:
                    w[k] = 1;
                    break;
            }
            if (k != Taps / 2.0)
                w[k] = w[k] * Math.Sin(Math.PI * (k - Taps / 2.0) / Periods) / Math.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;


        //Calculate FIR MA for all bars except for the last n bars
        for (int i = 0; i <= Bars - Taps; i++)
        {
            FIRMA[i + n] = 0.0;
            for (int k = 0; k < Taps; k++)
                FIRMA[i + n] += MarketSeries.Close[i + k] * w[k] / wsum;

        }




    }


    public override void Calculate(int index)
    {
        //Calculate regressive MA for the remaining n bars
        double a0 = FIRMA[index - n];
        double a1 = FIRMA[index - n] - FIRMA[index - n - 1];
        double sx2y = 0.0;
        double sx3y = 0.0;

        for (int i = 0; i <= n; i++)
        {
            sx2y += i * i * MarketSeries.Close[index + i - n];
            sx3y += i * i * i * MarketSeries.Close[index + i - n];
        }
        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;

        for (int i = 0; i <= n; i++)
        {
            ARMA[index + i - n] = a0 + i * a1 + i * i * a2 + i * i * i * a3;
            //ChartObjects.DrawText("test", "ARMA: " + ARMA[index + i - n] + "\na0: " + a0 + "\na1: " + a1 + "\na2: " + a2 + "\na3: " + a3 + "\nn: " + n + "\ni: " + i + "\np: " + p + "\nq: " + q + "\nsx2y: " + sx2y + "\nsx3y: " + sx3y + "\nsx2: " + sx2 + "\nsx3: " + sx3 + "\nsx4: " + sx4 + "\nsx5: " + sx5 + "\nsx6: " + sx6 + "\nden: " + den, StaticPosition.TopRight);
        }
    }
    private int Bars
    {
        get { return MarketSeries.Close.Count; }
    }

}

}
glennsl
  • 28,186
  • 12
  • 57
  • 75
Ryan J. M.
  • 19
  • 3
  • 1
    Would you mind to complete the MCVE with a set of both POSACK and NACK sets of data+results, that, in your view, provide proper, data+test-driven acknowledgement of a **working** and a **not working** solution? Thanks for your kind re-consideration. – user3666197 Mar 09 '17 at 10:46

2 Answers2

1

It is a simple bug: Return of the ARMA loop is in the incorrect place and loop returns immediately.

for (int i = 0; i <= n; i++)
    {
        ARMA[n - i] = a0 + i * a1 + i * i * a2 + i * i * i * a3;
        return; // Not here
    }
return; //But here.
Zizy Archer
  • 1,392
  • 7
  • 11
  • I modified the return but unfortunately it still does not output. – Ryan J. M. Mar 10 '17 at 09:10
  • @RyanJ.Markwald What values does ARMA have at the point of the return? Set a breakpoint there and check the values. The code seems the same as MQL4 now and I don't see why it would get stuck. – Zizy Archer Mar 10 '17 at 09:52
  • Yeah, that's why i found it odd aswell. This number seems to be it's last value at the moment.![Picture with latest value in top-right corner](http://imgur.com/IvoS4cj). – Ryan J. M. Mar 10 '17 at 10:28
  • @RyanJ.Markwald Hum the number is way out of range. Might be all values are. And if they are, might be there is an error somewhere in the function, but I can't see it. – Zizy Archer Mar 10 '17 at 10:52
  • Yes you are right! I've updated the post with all the values of the variables used. But even so, It should render something, right? Thank your for your time. – Ryan J. M. Mar 10 '17 at 14:06
0

Shall that produce something like this?

enter image description here

How about the head-part?

Is that an intention or is that an un-corrected residual of mistake in the progressive, batch-driven CustomIndicator calculus, using an MQL4 TimeSeries habit of processing a reversed, forward-stepping Bar-number indexed arrays?

user3666197
  • 1
  • 6
  • 50
  • 92
  • I hope I provided all the information needed. I suspect it is a un-corrected result and the ARMA (red output) does not render at all, as seen in the picture uploaded. Thank you for your patience. – Ryan J. M. Mar 10 '17 at 08:45