iMA based on different applied price

 

Hi,


I need assistance with an MA calculation. I want to use iMA with a custom applied price.

Is there an easy way to calculate iMA based on the difference between Open and Close?

example:

iMA(_Symbol,_Period,21,0,MODE_SMA,Close-Open);


I tried to convert my MQL4 code. But keep getting Array out of range error.


Thanks for any kind of help


//+------------------------------------------------------------------+
//|                                                   MACustom.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot ProxyIndex
#property indicator_label1  "MACustom"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- indicator buffers



extern int Length=21;
double Raw[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,IMA,INDICATOR_DATA);
   
//---
   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[])
  {
//---
   
//--- return value of prev_calculated for next call
   int bars=Bars(_Symbol,_Period);
   if(bars <= Length) return(0);
   int limit=bars-2;
  
   
    int pos;
    pos=limit;
    
    while(pos>=0)
    {
     Raw[pos]=iOpen(_Symbol,_Period,pos)-iClose(_Symbol,_Period,pos); 
     pos--;
    } 
    
    
double MA;
 pos=limit;
 while(pos>=0)
 {
  MA=iMAOnArrayMQL4(Raw, 0, Length, 0, MODE_SMA, pos);
  IMA[pos]=MA;
  pos--;
 }  




   return(rates_total);
  }
//+------------------------------------------------------------------+




double iMAOnArrayMQL4(double &array[],
                      int total,
                      int period,
                      int ma_shift,
                      int ma_method,
                      int shift)
  {
   double buf[],arr[];
   if(total==0) total=ArraySize(array);
   if(total>0 && total<=period) return(0);
   if(shift>total-period-ma_shift) return(0);
   switch(ma_method)
     {
      case MODE_SMA :
        {
         total=ArrayCopy(arr,array,0,shift+ma_shift,period);
         if(ArrayResize(buf,total)<0) return(0);
         double sum=0;
         int    i,pos=total-1;
         for(i=1;i<period;i++,pos--)
            sum+=arr[pos];
         while(pos>=0)
           {
            sum+=arr[pos];
            buf[pos]=sum/period;
            sum-=arr[pos+period-1];
            pos--;
           }
         return(buf[0]);
        }
      case MODE_EMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double pr=2.0/(period+1);
         int    pos=total-2;
         while(pos>=0)
           {
            if(pos==total-2) buf[pos+1]=array[pos+1];
            buf[pos]=array[pos]*pr+buf[pos+1]*(1-pr);
            pos--;
           }
         return(buf[shift+ma_shift]);
        }
      case MODE_SMMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double sum=0;
         int    i,k,pos;
         pos=total-period;
         while(pos>=0)
           {
            if(pos==total-period)
              {
               for(i=0,k=pos;i<period;i++,k++)
                 {
                  sum+=array[k];
                  buf[k]=0;
                 }
              }
            else sum=buf[pos+1]*(period-1)+array[pos];
            buf[pos]=sum/period;
            pos--;
           }
         return(buf[shift+ma_shift]);
        }
      case MODE_LWMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double sum=0.0,lsum=0.0;
         double price;
         int    i,weight=0,pos=total-1;
         for(i=1;i<=period;i++,pos--)
           {
            price=array[pos];
            sum+=price*i;
            lsum+=price;
            weight+=i;
           }
         pos++;
         i=pos+period;
         while(pos>=0)
           {
            buf[pos]=sum/weight;
            if(pos==0) break;
            pos--;
            i--;
            price=array[pos];
            sum=sum-lsum+price*period;
            lsum-=array[i];
            lsum+=price;
           }
         return(buf[shift+ma_shift]);
        }
      default: return(0);
     }
   return(0);
  }
 

you need to add "raw' to the indicator datas:

and change "indicator_buffers 2"

SetIndexBuffer(
1,RAW,INDICATOR_CALCULATIONS);
 
I extracted it from a larger piece of code. This was a modification problem, sorry.


The out-of-range array problem is still present.
 
Crunch007: The out-of-range array problem is still present.
  1. Of course, it is. Raw is an array with no size. Make it a buffer as Jean said.
  2.    int limit=bars-2;
      
     pos=limit;
     while(pos>=0)
     {
      MA=iMAOnArrayMQL4(Raw, 0, Length, 0, MODE_SMA, pos); // accesses pos+Length-1 = Bars+Length-3
    Then fix your second loop so you don't look back more than what data you have.
              How to do your lookbacks correctly.
 

I will give it a try. Thanks for the feedback.