MathMedian()

 

Hi all,

I have been trying, without success, to create a moving median indicator using MathMedian(), such as MathMedian(prices).

Can anyone give me a clue on how to fetch the prices, put into an array, calculate using MathMedian()?

Many thanks,

Arthur.
 
Arthur Albano:

Hi all,

I have been trying, without success, to create a moving median indicator using MathMedian(), such as MathMedian(prices).

Can anyone give me a clue on how to fetch the prices, put into an array, calculate using MathMedian()?

Many thanks,

Arthur.

Just replace the calculation in a simple indicator.

For example, the Indicators\Examples\ROC.mq5 indicator (ships with MT5) is very simple.

 
Anthony Garot:

Just replace the calculation in a simple indicator.

For example, the Indicators\Examples\ROC.mq5 indicator (ships with MT5) is very simple.

Used ROC, but with this line:

#include <Math\Stat\Normal.mqh>

And changed the follinw code:

   for(int i=pos;i<rates_total && !IsStopped();i++)
     {
      if(price[i]==0.0)
         ExtRocBuffer[i]=0.0;
      else
         ExtRocBuffer[i]=MathMedian(price); //--- changed line
}


But I got an error:

'price' - constant variable cannot be passed as reference

 

Try something like this:

double medianArray[];
ArrayCopy(medianArray, price, 0, 0, InpRocPeriod);
ExtRocBuffer[i]=MathMedian(medianArray);

I haven't tested this.

 
Anthony Garot:

Try something like this:

I haven't tested this.

Have to add:

#property indicator_buffers 2

 
Anthony Garot:

Try something like this:

I haven't tested this.

The original line of code is:

ExtRocBuffer[i]=(price[i]-price[i-ExtRocPeriod])/price[i]*100;

I have tried this:

ArrayCopy(medianarray,price,0,i,ExtRocPeriod);

But I am always getting the error 

array out of range in 'MovingMd.mq5' (69,22)

ExtRocBuffer[i]=MathMedian(medianArray);

//--- the main loop of calculations
   for(int i=pos;i<rates_total && !IsStopped();i++)
     {
      if(price[i]==0.0) {
         ExtRocBuffer[i]=0.0;
         medianArray[i]=0.0;
      }
      else {
         //-- ExtRocBuffer[i]=(price[i]-price[i-ExtRocPeriod])/price[i]*100;
         ArrayCopy(medianArray, price, 0, 0, ExtRocPeriod);
         ExtRocBuffer[i]=MathMedian(medianArray);
         }
     }
//--- OnCalculate done. Return new prev_calculated.

 

You probably want a lookback of, say, 12 starting with the rightmost bar.

Thus, you want to loop backwards.

Which means you want to use ArraySetAsSeries().

Perhaps something like this:

#property description "Median"

//--- indicator settings
#property indicator_separate_window

#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  LightSeaGreen

#include <Math\Stat\Normal.mqh>

//--- input parameters
input int InpLookbackPeriod=12;        // Period
//--- indicator buffers
double    ExtMedianBuffer[];

void OnInit()
{
    //--- indicator buffers mapping
    SetIndexBuffer(0,ExtMedianBuffer,INDICATOR_DATA);
    //--- set accuracy
    IndicatorSetInteger(INDICATOR_DIGITS,6);
    //--- name for DataWindow and indicator subwindow label
    IndicatorSetString(INDICATOR_SHORTNAME,"MED("+string(InpLookbackPeriod)+")");
    //--- sets first bar from what index will be drawn
    PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpLookbackPeriod);

    ArraySetAsSeries(ExtMedianBuffer,true);
    //--- initialization done
}

int OnCalculate(const int rates_total,const int prev_calculated,const int begin,const double &price[])
{
    //--- check for rates count
    if(rates_total<InpLookbackPeriod)
        return(0);

    //--- Checking and calculating the number of countable bars
    int limit=rates_total-prev_calculated;
    if(limit>1)
    {
        limit=rates_total-InpLookbackPeriod;
    }

    //--- the main loop of calculations
    for(int i=limit; i>=0 && !IsStopped(); i--)
    {
        double medianArray[];
        ArrayCopy(medianArray, price, 0, i, InpLookbackPeriod);
        ExtMedianBuffer[i]=MathMedian(medianArray);
    }

    //--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
}
//+------------------------------------------------------------------+

 
Anthony Garot:

You probably want a lookback of, say, 12 starting with the rightmost bar.

Thus, you want to loop backwards.

Which means you want to use ArraySetAsSeries().

Perhaps something like this:

int OnCalculate(const int rates_total,const int prev_calculated,const int begin,const double &price[])
{
    ArrayCopy(PricesCopy,price,0,0,WHOLE_ARRAY);
    ArraySetAsSeries(PricesCopy,true);
    
    //--- check for rates count
    if(rates_total<InpLookbackPeriod)
        return(0);

    //--- Checking and calculating the number of countable bars
    int limit=rates_total-prev_calculated;
    if(limit>1)
    {
        limit=rates_total-InpLookbackPeriod;
    }

    //--- the main loop of calculations
    for(int i=limit; i>=0 && !IsStopped(); i--)
    {
        ArrayCopy(PricesCopy, price, 0, i, InpLookbackPeriod);
        ArraySetAsSeries(PricesCopy,true);
        ExtMedianBuffer[i]=MathMedian(PricesCopy);
    }

    //--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
}

The problem is: the results are wrong. I attached it to a chart and results are just a fraction of price. That doesn't make sense. Results are like this: MathMedian(2,3,4,5,6) = 2. Result should be 4. I am trying to calculate median value of a price that's between 40 and 50, but the results are close to 20, lower than minimum value...

 
Arthur Albano:

The problem is: the results are wrong. I attached it to a chart and results are just a fraction of price. That doesn't make sense. Results are like this: MathMedian(2,3,4,5,6) = 2. Result should be 4. I am trying to calculate median value of a price that's between 40 and 50, but the results are close to 20, lower than minimum value...

Oh, you actually want the numbers to be correct?

:-D

Here's a complete solution. I put it on the main chart. The few test points I tried appear correct. Caveat emptor.

#property description    "Simple Moving Median"
#property description    " "
#property description    "Created for https://www.mql5.com/en/forum/273812"
#property description    " "
#property description    "MQL5 Profile: https://www.mql5.com/en/users/tonegarot"
#property description    "My Website: http://www.garot.com/trading/"
#property strict

//--- indicator settings
#property indicator_chart_window

#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  LightSeaGreen
#property indicator_width1  3

#include <Math\Stat\Normal.mqh>

//--- input parameters
input int InpLookbackPeriod=12;        // Period
//--- indicator buffers
double    ExtMedianBuffer[];

void OnInit()
{
    //--- indicator buffers mapping
    SetIndexBuffer(0,ExtMedianBuffer,INDICATOR_DATA);
    //--- set accuracy
    IndicatorSetInteger(INDICATOR_DIGITS,5);
    //--- name for DataWindow and indicator subwindow label
    IndicatorSetString(INDICATOR_SHORTNAME,"SMM("+string(InpLookbackPeriod)+")");
    //--- sets first bar from what index will be drawn
    PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpLookbackPeriod);

    ArraySetAsSeries(ExtMedianBuffer,false);
    //--- initialization done
}

int OnCalculate(const int rates_total,const int prev_calculated,const int begin,const double &price[])
{
    //--- check for rates count
    if(rates_total<InpLookbackPeriod)
        return(0);

    //--- Checking and calculating the number of countable bars
    int limit=rates_total-prev_calculated;
    if(limit>1)
    {
        limit=rates_total-1;
    }

    //--- the main loop of calculations
    for(int i=limit; i>=0 && !IsStopped(); i--)
    {
        double medianArray[];
        ArrayCopy(medianArray, price, 0, i-InpLookbackPeriod+1, InpLookbackPeriod);
        ExtMedianBuffer[i]=MathMedian(medianArray);
    }

    //--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
}
//+------------------------------------------------------------------+

 
Anthony Garot:

Oh, you actually want the numbers to be correct?

:-D

Here's a complete solution. I put it on the main chart. The few test points I tried appear correct. Caveat emptor.

#include <Math\Stat\Math.mqh>

Is enough. Values seem right now. But as Romans said: "caveat emptor" :D

I really forgot the +1 and -1 ones... Result? Array out index :P

 
Arthur Albano:

#include <Math\Stat\Math.mqh>

Is enough. Values seem right now. But as Romans said: "caveat emptor" :D

I really forgot the +1 and -1 ones... Result? Array out index :P

The strategy tester failed.

Reason: