Indicator showing the range of two moving averages

 

Hello Community,

I tried building an indicator that shows the range of two moving averages.

The indicator is designed to have 3 buffers and 1 plot, with the plot being a single line showing the range data.

The goal is to be able to track proximity to the crossover. Need help please.

Below is my script, but it

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots 1

double ma1Buffer[];
double ma2Buffer[];
double maRangeBuffer[];

int ma1Handle;
int ma2Handle;

input int ma1_period = 24;
input int ma2_period = 100;
input ENUM_MA_METHOD ma_method = MODE_SMA;
input ENUM_APPLIED_PRICE ma_price = PRICE_CLOSE;


int OnInit()
{
    //   indicator buffer mapping
    SetIndexBuffer(0, maRangeBuffer, INDICATOR_DATA);
    SetIndexBuffer(1, ma1Buffer, INDICATOR_CALCULATIONS);
    SetIndexBuffer(2, ma2Buffer, INDICATOR_CALCULATIONS);
    //   indicator accuracy
    IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
    //--- sets first bar from what index will be drawn
    PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, ma2_period);
    //--- name for DataWindow and indicator subwindow label
    string short_name = StringFormat("MA_RANGE(%d)", ma1_period, ma2_period);
    IndicatorSetString(INDICATOR_SHORTNAME, short_name);
    //PlotIndexSetString(0,PLOT_LABEL,short_name);
    //--- set the drawing histogram and line to an empty value
    PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
    
    return (INIT_SUCCEEDED);
}

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 (rates_total <= ma2_period)
        return (0);

    int start;
    if (prev_calculated == 0)
    {
        // Calculate the first MA values
        for (int i = 0; i < ma2_period; i++)
        {
            double sum_ma1 = 0, sum_ma2 = 0;
            for (int j = 0; j < ma1_period; j++)
                sum_ma1 += close[i - j];
            for (int j = 0; j < ma2_period; j++)
                sum_ma2 += close[i - j];
            ma1Buffer[i] = sum_ma1 / ma1_period;
            ma2Buffer[i] = sum_ma2 / ma2_period;
            maRangeBuffer[i] = ma1Buffer[i] - ma2Buffer[i];
        }
        start = ma2_period;
    }
    else
        start = prev_calculated - 1;

    // Calculate MA range for the remaining bars
    for (int i = start; i < rates_total; i++)
    {
        double sum_ma1 = 0, sum_ma2 = 0;
        for (int j = 0; j < ma1_period; j++)
            sum_ma1 += close[i - j];
        for (int j = 0; j < ma2_period; j++)
            sum_ma2 += close[i - j];
        ma1Buffer[i] = sum_ma1 / ma1_period;
        ma2Buffer[i] = sum_ma2 / ma2_period;
        maRangeBuffer[i] = ma1Buffer[i] - ma2Buffer[i];
    }

    return (rates_total);
}

seems not to be working.

I keep on getting this error code; 2024.05.07 08:39:08.450 array out of range in 'macor.mq5' (60,36)

Am just barely 3 months old to MQL5. I need help.

Would be so happy to have this script working.

At the moment I use it in it basic logic in my EA which works like this ;

But would love to have it as an indicator.

         //========================================================
         // IMPLEMENTING MA RANGE INICATOR
         //========================================================
         //     It basic formula I have been using
         double crossover_range = NormalizeDouble(bigger_Ma_Value,_Digits)-NormalizeDouble(smaller_Ma_Value,_Digits);
         //========================================================
         // end - IMPLEMENTING MACOR INICATOR
         //========================================================
 

I think you are overcomplicating things.

You can simply use iMA commands for initializing handles into OnInit, then copy buffers from MA indicators, and then do a simple difference between your buffers.

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   1

input int      iMA1Period     = 50;
input int      iMA2Period     = 200;

double   ExtMA1[], ExtMA2[], ExtDelta[];
int      Handle_MA1, Handle_MA2;

int OnInit() {
   SetIndexBuffer(0,ExtDelta);
   SetIndexBuffer(1,ExtMA1);
   SetIndexBuffer(2,ExtMA2);
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrBlue);
   if( (Handle_MA1 = iMA(NULL,0,iMA1Period,0,MODE_EMA,PRICE_CLOSE)) == INVALID_HANDLE ) return INIT_FAILED;
   if( (Handle_MA2 = iMA(NULL,0,iMA2Period,0,MODE_EMA,PRICE_CLOSE)) == INVALID_HANDLE ) return INIT_FAILED;
   return(INIT_SUCCEEDED);
}

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( prev_calculated<1 ) {
      ArrayInitialize(ExtMA1,EMPTY_VALUE);
      ArrayInitialize(ExtMA2,EMPTY_VALUE);
      ArrayInitialize(ExtDelta,EMPTY_VALUE);
   }
   if( CopyBuffer(Handle_MA1,0,0,MathMin(rates_total-prev_calculated+1,rates_total-1),ExtMA1)<=0 ) return 0;
   if( CopyBuffer(Handle_MA2,0,0,MathMin(rates_total-prev_calculated+1,rates_total-1),ExtMA2)<=0 ) return 0;
   for (int i=MathMax(0,prev_calculated-1); i<rates_total && !_StopFlag; i++) 
      ExtDelta[i] = ExtMA1[i] - ExtMA2[i];
   return(rates_total);
}
 
Fabio Cavalloni #:

I think you are overcomplicating things.

You can simply use iMA commands for initializing handles into OnInit, then copy buffers from MA indicators, and then do a simple difference between your buffers.

Sir Fabio, you are soo kind, thank You Sir, there is much I can learn from your script. Lol, you made it look very simple.
Reason: