Using iMA on other custom indicator's handle, gives blank window and only drawn for new bars, and I don't know why

 

Hello Guys,

I have an issue, I can not solve for quite a lot of hours now. I did my research, debugged a lot, but still have no clue what causes the problem. That's why I am here to ask for some help from more skilled veterans!

I have 2 indicators: A and B

A is averaging two iMA values and creates a single line from that. As alone it works well, attached to chart (figure_1). Everything is OK.

//+------------------------------------------------------------------+
//|                                                            A.mq5 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   1

#property indicator_label1  "Line"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrWhite
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

int SMMAHandle;
int SMAHandle;

double PriceBuffer[];

double SMMABuffer[];
double SMABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,PriceBuffer,INDICATOR_DATA);
   
   SetIndexBuffer(1,SMMABuffer,INDICATOR_DATA);
   SetIndexBuffer(2,SMABuffer,INDICATOR_DATA);

   LoadExternalIndicators();
//---
   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[])
  {
//---
   CopyIndicatorBuffers(rates_total);

   int start=MathMax(0,prev_calculated-1);
   for(int i=start;i<rates_total;i++)
     {
      PriceBuffer[i]=(SMMABuffer[i]+SMABuffer[i])/2.0;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Loads external indicators with error messages                    |
//+------------------------------------------------------------------+
void LoadExternalIndicators()
  {
   ResetLastError();
   SMMAHandle=iMA(NULL,0,13,0,MODE_SMMA,PRICE_CLOSE);
   if(SMMAHandle==INVALID_HANDLE)
      Alert("SMMA = ",SMMAHandle,"  error = ",GetLastError());

   ResetLastError();
   SMAHandle=iMA(NULL,0,21,0,MODE_SMA,PRICE_CLOSE);
   if(SMAHandle==INVALID_HANDLE)
      Alert("SMA = ",SMAHandle,"  error = ",GetLastError());
  }
//+------------------------------------------------------------------+
//| Loads external indicator's data buffer with error messages       |
//+------------------------------------------------------------------+
void CopyIndicatorBuffers(int rates_total)
  {
   BufferCopy("SMMA",SMMAHandle,rates_total,SMMABuffer,0);
   BufferCopy("SMA",SMAHandle,rates_total,SMABuffer,0);
  }
//+------------------------------------------------------------------+
//| CopyBuffer alternative with error messages                       |
//+------------------------------------------------------------------+
void BufferCopy(string name,int &handle,int rates_total,double &buffer[],int buffer_nr)
  {
   int copy= CopyBuffer(handle,buffer_nr,0,rates_total,buffer);
   if(copy<=0)
      Alert("An attempt to get the values of ",name," has failed");
  }
//+------------------------------------------------------------------+

figure_1

figure_1


B uses iCustom to call A, and applies iMA on A's handle. This is where the problem comes in.

//+------------------------------------------------------------------+
//|                                                            B.mq5 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   1

#property indicator_label1  "Line"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrWhite
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

int AHandle;
int MAHandle;

double LineBuffer[];

double ABuffer[];
double MABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,LineBuffer,INDICATOR_DATA);
   
   SetIndexBuffer(1,ABuffer,INDICATOR_DATA);
   SetIndexBuffer(2,MABuffer,INDICATOR_DATA);

   LoadExternalIndicators();
//---
   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[])
  {
//---
   CopyIndicatorBuffers(rates_total);

   int start=MathMax(0,prev_calculated-1);
   for(int i=start;i<rates_total;i++)
     {
      LineBuffer[i]=MABuffer[i];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
void LoadExternalIndicators()
  {
   ResetLastError();
   AHandle=iCustom(NULL,0,"Test\\1\\A.ex5");
   if(AHandle==INVALID_HANDLE)
      Alert("AHandle = ",AHandle,"  error = ",GetLastError());

   ResetLastError();
   MAHandle=iMA(NULL,0,50,0,MODE_SMA,AHandle);
   if(MAHandle==INVALID_HANDLE)
      Alert("MAHandle = ",MAHandle,"  error = ",GetLastError());
  }
//+------------------------------------------------------------------+
//| Loads external indicator's data LineBuffer with error messages       |
//+------------------------------------------------------------------+
void CopyIndicatorBuffers(int rates_total)
  {
   BufferCopy("A",AHandle,rates_total,ABuffer,0);
   BufferCopy("MA",MAHandle,rates_total,MABuffer,0);
  }
//+------------------------------------------------------------------+
//| CopyBuffer alternative with error messages                       |
//+------------------------------------------------------------------+
void BufferCopy(string name,int &handle,int rates_total,double &buffer[],int buffer_nr)
  {
   int copy= CopyBuffer(handle,buffer_nr,0,rates_total,buffer);
   if(copy<=0)
      Alert("An attempt to get the values of ",name," has failed");
  }
//+------------------------------------------------------------------+


Firstly the indicator window of B is blank, but after new bars drawn to the chart, it begins to display values, but only for new bars (figure_2).
(Initially B has a very large negative number as value.)

figure_2

figure_2


If I change the code to display A's buffer as B's value, everything good (figure_3).

figure_3

figure_3

The problem is with the iMA part, but I can not figure it out. Could You please help me with this?

Thanks!

Files:
A.mq5  8 kb
B.mq5  4 kb
 
iztrader: The problem is with the iMA part, but I can not figure it out.
  1. When you post code please use the SRC button! Please edit your post.
              General rules and best pratices of the Forum. - General - MQL5 programming forum

  2. Perhaps you should read the manual.
              Technical Indicators / iMA - Reference on algorithmic/automated trading language for MetaTrader 5
    MAHandle=iMA(
       NULL,
       0,
       50,
       0,
       MODE_SMA,
       AHandle
    ); 
    int  iMA(
       string               symbol,            // symbol name
       ENUM_TIMEFRAMES      period,            // period
       int                  ma_period,         // averaging period
       int                  ma_shift,          // horizontal shift
       ENUM_MA_METHOD       ma_method,         // smoothing type
       ENUM_APPLIED_PRICE   applied_price      // type of price or handle
       );
    A handle is not an applied price. You have to get the indicator's values and compute the MA yourself, like iMAOnArrayMQL4
              Migrating from MQL4 to MQL5 - MQL5 Articles № 18

 
whroeder1:
  1. When you post code please use the SRC button! Please edit your post.
              General rules and best pratices of the Forum. - General - MQL5 programming forum

  2. Perhaps you should read the manual.
              Technical Indicators / iMA - Reference on algorithmic/automated trading language for MetaTrader 5


    A handle is not an applied price. You have to get the indicator's values and compute the MA yourself, like iMAOnArrayMQL4
              Migrating from MQL4 to MQL5 - MQL5 Articles № 18

1, I edited the post, and reformatted the source

2, I read the manual, and it says:

applied_price
[in]  The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator.

AHandle is a handle of another indicator.


It is not a solution for me to compute MA myself, because this is only a test case I presented, to keep things simple. In real case I will use a lot of other indicators (iTEMA, iRSI and iCustom) based on the value of A. I can not rewrite all indicators, I want to outsource different logic to keep the system modular. There must be a way to achieve what I am looking for, because the docs clearly states that other indicators could be used instead of price types.

 
So it does.
 
whroeder1:
So it does.
Do you have any ideas what is wrong with the code, or what causes the problem?
 
iztrader:
Do you have any ideas what is wrong with the code, or what causes the problem?

Don't you need to use the short format of OnCalculate in b?

int OnCalculate(const int rates_total,         // size of the price[] array
                const int prev_calculated,   // bars processed during the previous call
                const int begin,             // from where the significant data begin
                const double &price[]        // array for calculation
                )
 
Amir Yacoby:

Don't you need to use the short format of OnCalculate in b?

I don't want to attach B to A at same indicator window, but would like to access data of MAofA and calculate a new buffer(in B) - partially - based on that info.
As I see Your suggestion is useful for displaying more than one indicators in the same window, so I could select to apply it on previous or first indicator's data, but unfortunately this is not my case.

 
Amir Yacoby:

Don't you need to use the short format of OnCalculate in b?

By the way, when I simply drag and drop the built-in MA on the chart and select "Apply to previous indicator's data" which is A, the result is also the same:

figure_4

figure_4

 
iztrader:

Using iMA on other custom indicator's handle, gives blank window and only drawn for new bars, and I don't know why


Set your initial values to something, e.g. 0 or close[i]

So, in A:

                if ( i < 21 )
                {
                        PriceBuffer[i] = 0;  // Or use close[i]
                }
                else
                {
                        PriceBuffer[i]=(SMMABuffer[i]+SMABuffer[i])/2.0;
                }

and in B:

                if ( i < 50 )
                {
                        LineBuffer[i]=0;   // or use ABuffer[i];
                }
                else
                {
                        LineBuffer[i]=MABuffer[i];
                }

The 21 and 50 are the periods of your longest moving averages. You probably want to make these constants for readability or input variables for flexibility, but that is aside from your question.

Reason: