MT4 iMAOnArray and iBandsOnArray effect of number of elements on calculations - page 2

 
Sergey Efimenko:
What do you mean, what do I expect? I wrote above, that I need 300 latest (current) actual values, and not 300 first (initial), moreover, that I access an array at offset 299-0, but get data at offset from "array end" to "array end - 300" values (in my case from 4999 to 4700), that is, at offset 299 is a value, which should be at offset 4999 and similarly at offset 0 is a value, which should be at offset 4700. The question is, what is the purpose of calculating old values, when current values are not calculated?

If it was clear from what you wrote, there would be no questions.

double  iMAOnArray(
   double       array[],          // массив               // С этим понятно...
   int          total,            // количество элементов // Это у тебя 300
   int          ma_period,        // период               // Это ???
   int          ma_shift,         // сдвиг средней        // понятно
   int          ma_method,        // метод усреднения     // понятно
   int          shift             // сдвиг                // А здесь чему равна i???
   );

You were asked to show a code sample, while you showed just a fragment of an example. About the rest you can only guess that it's all in the loop. At what value of i do you want to get the last, current values? At i = 4700 or where?

 
Alexey Viktorov:

If it was clear from what you wrote, then there would be no questions.

You were asked to show a code example and you only showed a piece of example. About the rest you can only guess that it's all in a loop. At what value of i do you want to get the last, current values? At i = 4700 or where?

If you've used these functions with length limitation of calculation array in practice, you'll understand what I mean, otherwise what's the point of theoretical reasoning...? And what's unclear about my piece of code? I cited absolutely identical sections with the only difference that in the first case I don't use length limitation for calculation of the array. In this case it doesn't matter at all which calculation period, the shift average or the averaging method, as they are the same in both cases? The value of shift, as I wrote above, is similarly used exactly the same. Replace "i" with your shift variable in the loop, replace the GetValue(i) function with at least Open[i], make the three mentioned arrays 3 displaying buffers of the indicator and see how the first and the second one work. However, here is an example of the full code of the simple variant of the indicator in two variants for better understanding of the problem:

//this works fine:
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[],BufferMA[],BufferBMA[]; bool firstrun=true;
int init() { firstrun=true; SetIndexBuffer(0,Buffer); SetIndexBuffer(1,BufferMA); SetIndexBuffer(2,BufferBMA); return(0); }
int start() { int i,limit; int counted_bars=IndicatorCounted(); if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; limit=Bars-counted_bars-1;
   if(firstrun) {ArrayInitialize(Buffer,Open[Bars-1]); ArrayInitialize(BufferMA,Open[Bars-1]); ArrayInitialize(BufferBMA,Open[Bars-1]); firstrun=false; }
   for(i=limit; i>=0; i--) { Buffer[i]=Open[i]; BufferMA[i]=iMAOnArray(Buffer,0,12,0,0,i); BufferBMA[i]=iBandsOnArray(Buffer,0,12,2,0,MODE_MAIN,i); }
return(0); }

//it doesn't work properly:

#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[],BufferMA[],BufferBMA[]; bool firstrun=true;
int init() { firstrun=true; SetIndexBuffer(0,Buffer); SetIndexBuffer(1,BufferMA); SetIndexBuffer(2,BufferBMA); return(0); }
int start() { int i,limit; int counted_bars=IndicatorCounted(); if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; limit=Bars-counted_bars-1;
   if(firstrun) {ArrayInitialize(Buffer,Open[Bars-1]); ArrayInitialize(BufferMA,Open[Bars-1]); ArrayInitialize(BufferBMA,Open[Bars-1]); firstrun=false; }
   for(i=limit; i>=0; i--) { Buffer[i]=Open[i]; BufferMA[i]=iMAOnArray(Buffer,300,12,0,0,i); BufferBMA[i]=iBandsOnArray(Buffer,300,12,2,0,MODE_MAIN,i);  }
return(0); }

After drawing the indicators on the chart, go to the beginning (to the left) of the chart and look at 1 indicator from 12 bars and onwards, it is the beginning of "non-empty" filling of 2 and 3 of the array, approximately remember the first few values that differ from 0, then move the chart to the current quotes and look values starting from 300 bars, so values of 2 (bottom) indicator will be equal to those that you saw at the beginning of the chart of 1 indicator, while in idea, the values should match the current. I hope I explained it clearly. Also, if you put the charts on an online chart, the first one will work fine and the second one will "hang at its own".

 
Sergey Efimenko:


Not only is the code unstyled, but you insert the code as plain text. Please insert the code correctly.
 

I will present your code in a more readable form and in a new notation (really, how much longer can we use this anachronistic int start() in indicators???):

Indicator 1:

//+------------------------------------------------------------------+
//|                                                         Test.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[];
double BufferMA[];
double BufferBMA[];
bool firstrun=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   firstrun=true;
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMA,INDICATOR_DATA);
   SetIndexBuffer(2,BufferBMA,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[])
  {
//---
   int i,limit;
   limit=rates_total-prev_calculated-1;
   if(prev_calculated==0)
     {
      ArrayInitialize(Buffer,open[rates_total-1]);
      ArrayInitialize(BufferMA,open[rates_total-1]);
      ArrayInitialize(BufferBMA,open[rates_total-1]);
     }
   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,0,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,0,12,2,0,MODE_MAIN,i);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

Indicator 2:

//+------------------------------------------------------------------+
//|                                                         Test.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[];
double BufferMA[];
double BufferBMA[];
bool firstrun=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   firstrun=true;
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMA,INDICATOR_DATA);
   SetIndexBuffer(2,BufferBMA,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[])
  {
//---
   int i,limit;
   limit=rates_total-prev_calculated-1;
   if(prev_calculated==0)
     {
      ArrayInitialize(Buffer,open[rates_total-1]);
      ArrayInitialize(BufferMA,open[rates_total-1]);
      ArrayInitialize(BufferBMA,open[rates_total-1]);
     }
   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,300,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,300,12,2,0,MODE_MAIN,i);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

And the result of the execution:

Result

о

Files:
Test.mq4  3 kb
Test300.mq4  3 kb
 
Sergey Efimenko:

If you have used these functions

If I hadn't, I wouldn't be asking questions in order to suggest the right solution.

What's the point of taking 300 bars if you need to calculate a period of 12? Even if you need it "because", you should understand what 12 elements would be in the calculation of the average. And the hint about the direction of array indexing was very correct.

For understanding do experiments with manual calculation on paper or on a calculator, or in Excel.

 

When I look at the answers I realize that I'm just wasting my time here, trying to show the essence of the problem, and getting the "beauty" of the code in response (thanks of course, but the proposed code was written in two minutes just to show the essence of the problem and does not require any readability or other conversions)...

And especially delighted with the answer before my post... What calculator, what manual calculations, what indexing? Dear users, please understand the essence of the situation so as not to waste not only your time but also someone else's. Please reread my posts carefully, but if it's difficult, I will answer briefly: the direction of indexing of array in both cases is correct, the size of necessary calculations and other changeable parameters, as it is shown in primary code is set with external variables, the variant of creating own function was discussed above (and it is actually the only correct solution), but I want to repeat, I want to get it from built-in MT4.

In general thank you all, I will summarize: either servicedesk or own analogues of functions.

 

And I'm discouraged by the answer before my post...

If you're so stubborn, => servicedesk, and they only answer such questions out of boredom, and they rarely get bored.

Let me try again...

iMAOnArray() takes, in your case, 300 bars and calculates the average value of the last 12 bars out of three hundred. To average the first 12 bars, you should reverse the array indexing, ArraySetAsSeries(BufferMA, false); or take only 12 bars.

BufferMA[i]=iMAOnArray(Buffer,12,12,0,MODE_SMA,i);

So it turns out that instead of trying to understand how it works and how to use it, you simply stated that it doesn't work or works incorrectly. And it is not right in your opinion.

What's next about beauty of code: You think it's interesting for someone to break his eyes reading your code when it's all written in one line? Wrong. I didn't personally read it. Thanks to the little drummer for his patience several times a day to direct everyone... to the wrong place.

 

I wanted to answer very "in detail", but then, after re-reading the posts again, I deleted my answer, and finally realized that I was only wasting time here, explaining the same thing several times in different words...

PS All thanks and really thanks "Barabashke" (Vladimir), he did well, but this whole situation was not worth his labor, I'll be even more grateful if it will not be difficult to make, a screenshot in a key previous, adding a third option and showing what would happen if you follow the advice to change the direction of indexing. To put an end to the question of how the function works.

 
Sergey Efimenko:

I wanted to answer very "in detail", but then, after re-reading the posts again, I deleted my answer, and finally realized that I was only wasting time here, explaining the same thing several times in different words...

PS All thanks and really thanks "Barabashke" (Vladimir), he did well, but this whole situation was not worth his labor, I'll be even more grateful if it will not be difficult to make, a screenshot in a key previous, adding a third option and showing what would happen if you follow the advice to change the direction of indexing. To put an end to the question of how the function works.

Option 3:

//+------------------------------------------------------------------+
//|                                         Test300AsSeriesFalse.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[];
double BufferMA[];
double BufferBMA[];
bool firstrun=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   firstrun=true;
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMA,INDICATOR_DATA);
   SetIndexBuffer(2,BufferBMA,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[])
  {
//---
   ArraySetAsSeries(open,false);
//---
   int i,limit;
   limit=rates_total-prev_calculated-1;
   if(prev_calculated==0)
     {
      ArrayInitialize(Buffer,open[rates_total-1]);
      ArrayInitialize(BufferMA,open[rates_total-1]);
      ArrayInitialize(BufferBMA,open[rates_total-1]);
     }
   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,300,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,300,12,2,0,MODE_MAIN,i);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

And the overall result:

Options 1, 2 and 3

Files:
 

No, Vladimir. It is a bit wrong.

In this case, you should apply ArraySetAsSeries(array, false); to an array of three hundred elements among which iMAOnArray() is considered. But we'd better use CopyOpen() instead of the array's filling loop.

As I understand it, in this variant it will be better to

   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,12,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,12,12,2,0,MODE_MAIN,i);
     }