Learning and writing together in MQL5 - page 35

 

Who knows if I can pass a function to a non-member of a class as an argument to a reference (address) to another function which is not a member of any class at all?

Or, can I pass a function to a class member as an argument a reference (address) to another function which is not a member of any class at all?

Документация по MQL5: Основы языка / Типы данных / Структуры и классы
Документация по MQL5: Основы языка / Типы данных / Структуры и классы
  • www.mql5.com
Основы языка / Типы данных / Структуры и классы - Документация по MQL5
 
victorg:

Who knows if I can pass a function to a non-member of a class as an argument to a reference (address) to another function which is not a member of any class at all?

Or, can I pass a function to a class member as an argument a reference (address) to another function that is not a member of any class at all?

No. No.

You can't. In MQL5 there is no such a notion as "a function address" or "a function reference".

 

Thank you!

Another question.

There are two files with code in mql5.The first file is the main one - indicator or script. The second file ismqh.

// f_01.mqh
double extfunc(int a);
//-------------------------------------
double example(void)
  {
  double a;
  a=extfunc(35);
  return(a);
  }
//-------------------------------------
Thesecondmqh-file is connected to the main one at the very beginning. Compilation of the main file goes without errors or warnings. But when I try to compile the mqh-file separately I get ' function must have a body'.My question is, how can I tell the compiler that there is nothing wrong with the function, but its body is in a different file?


Документация по MQL5: Файловые операции / FileMove
Документация по MQL5: Файловые операции / FileMove
  • www.mql5.com
Файловые операции / FileMove - Документация по MQL5
 
victorg:

The secondmqh-file is included at the beginning of the main file. The compilation of the main file goes without errors and warnings. But when trying to compile the mqh-file separately we get ' function must have a body'.My question is: how to tell the compiler that there is nothing wrong with the function but its body is in a different file?
There is no way. Don't tear it apart, it does not make it easier to understand when reading the code.
 
Yedelkin:

I may be overreacting, but here's another question. Before sending a request to place a market order (to open a position), I reset a trade ticket to zero, i.e. I make result.deal=0. Can we expect that the server will return a null trade ticket in MqlTradeResult response structure, but a bit later, the trade will be executed and the position will be opened? Or will the return of a null trade ticket by the server guarantee that the position could not be opened and it will not be further opened based on this request?

OK, by virtue of the lack of response and by virtue of this line

struct MqlTradeResult
{
ulong deal; // Ticket to deal, if it was done
};

I conclude that the return of a null deal ticket by the server guarantees that the position cannot be opened and it will not be further opened based on this request.

 

I do not quite understand the forum structure, if not there, please direct me in the right direction

Since I am not a specialist, but I am interested in programming and proceeding from my own inclinations in the process of training, I am trying to understand by analyzing the existing code

For simplicity, I took a piece of custom code of MA , and try to understand what occurs in it (I reflected it in comments)

In general, if not difficult, please comment on the code, I want to understand what happens after each command. Thank you.

void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double &price[])//I figured it out &price[].

  {
   int i,limit;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)// first calculation
     {
      limit=InpMAPeriod+begin;                                               //почему переменная begin=0 ???
      //--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;                            //здесь инициализируются значения индикатора на барах с индексами от 0 до limit-1 ??? крайне правых на графике???
      //--- calculate first visible value
      double firstValue=0;                                                    //при инициализации переменной имеющей тип double не обязательно использовать значения типа double???
      for(i=begin;i<limit;i++)
         firstValue+=price[i];                                               //разобрался, здесь идет накопление переданной цены
      firstValue/=InpMAPeriod;
      ExtLineBuffer[limit-1]=firstValue;                                      
     }
   else limit=prev_calculated-1;                                              //в результате чего prev_calcutated не должно равняться 0, если индикатор поместили на оффлайн график?
//--- main loop
   for(i=limit;i<rates_total && !IsStopped();i++)                              //цикл для индикатора на баре с индексами от limit до последнего на графике
      ExtLineBuffer[i]=ExtLineBuffer[i-1]+(price[i]-price[i-InpMAPeriod])/InpMAPeriod;
//---
  }

put it in the printout and see that the values in the ExtLineBuffer are assigned from index limit-1to index rates_total-1, but in the chart the indicator is drawn in the whole space, hmm, then where is value assignment tothe indicator buffer on the interval from 1 to limit-1???

Документация по MQL5: Основы языка / Операции и выражения / Операции присваивания
Документация по MQL5: Основы языка / Операции и выражения / Операции присваивания
  • www.mql5.com
Основы языка / Операции и выражения / Операции присваивания - Документация по MQL5
 
Profi_R:

I do not quite understand the forum structure, if not there, please direct me in the right direction

Since I am not a specialist, but I am interested in programming and proceeding from my own inclinations in the process of training, I am trying to understand by analyzing the existing code

For simplicity, I took a piece of custom code of MA , and try to understand what is happening in it (I reflected it in comments)

I want to understand what happens after each command. Thank you.

I won't comment in detail, it may be enough to correct the basic error of your perception, and then you'll put the puzzle together yourself - that's much more useful.

So, the basis of your confusion is that many indicators in mql5 (this one in particular) are written without indexing of indicator buffers, i.e. with the value AsSeries=false.

It means that the index of the oldest bar on the history = 0 and the "freshest" one = RatesTotal-1.

// Is something clear?

The point of such approach is some gain in speed, because indexing does not require [hidden] recalculation when accessing the buffer (it remains "hardware")

// Perhaps the (mistaken) belief that indexing for indicator buffers ALWAYS occurs from the end of history to the beginning. This is always true in mql4, but it's not necessary in mql5.

// Here, the direction of indexing is always from the beginning of history to its end by default. To reverse the indexing, you should use the SetAsSeries(...) function in an explicit form.

// Note, the developers do not recommend to use defaults (in case they do change) and ALWAYS use SetAsSeries() function to set indexing direction.

void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double &price[])//I sorted out &price[]

put it to the printout and see that the values in the ExtLineBuffer are assigned from index limit-1to index rates_total-1, but in the chart the indicator is drawn in the entire space, hmm, then where is the value assigned tothe indicator buffer in the interval from 1 to limit-1?

I think you can figure it out on your own, but just in case, I'll check it out again tomorrow.
 
MetaDriver: ..

Thank you for your feedback.)

I've read about the order of directivity in arrays and recommendations to explicitly specify directivity in the help, but I had some doubts, which were eliminated after unsetting of intermediate data in the variables.

So far, only the directionality is determined, i.e. the comment about initialization was incorrect and the values of the indicator buffer are initialized on the specified range on the left side of the chart.

There are still questions about

1. the variable begin, is the terminal responsible for its value passed to the event handler?

2. can a variable of double type be passed to int type?

3. it seems that terminal is also responsible for value of variable prev_calculated

4. it is not clear where does indicator calculation on the interval from 0 to limit-1 takes place?

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
Основы языка / Функции / Функции обработки событий - Документация по MQL5
 
Profi_R:

There are still questions about

1. the variable begin, is the terminal responsible for its value sent to the event handler?

3. it seems that the value of variable prev_calculated is also responsible for the terminal

Most likely, the function under discussion was written for the first form of OnCalculate() function call. See Reference.

Profi_R:

We still have questions about

2. Can a variable of the double type be replaced with a value of the int type?

Yes, you can. See the section on implicit type conversion. The compiler will often give a warning about possible loss of data when using implicit type conversion.

Profi_R:

Still there are questions about

4. I do not understand where the indicator is calculated on the interval from 0 to limit-1.

Do these lines answer your question:

//--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;                            
//--- calculate first visible value
... и далее по коду
?
 
Profi_R:

Thank you for your feedback.)

I've read about the order of directivity in arrays and recommendations to explicitly specify directivity in the help, but I had some doubts, which were eliminated after unsetting of intermediate data in the variables.

So far, only the directionality is determined, i.e. the comment about initialization was incorrect and the values of the indicator buffer are initialized on the specified range on the left side of the chart.

OK.

There are still questions about

1. the variable begin, is the terminal responsible for its value sent to the event handler?

Yes, the terminal is responsible for its transmission to the indicator.


This parameter indicates to the indicator how many initial historical values of the input series should be ignored (skipped), because they are incorrect and should not participate in the calculations. Where can such incorrectness come from, what is its origin? It's related to the possibility of creating indicators that are calculated not on the price data, but on the data provided by other indicators. In MT5 there are three mechanisms that allow receiving data of another indicator for an indicator input.

Method 1. sequence of steps:

Create a handle for the input indicator using one of the iIndicator(...) functions or IndicatorCreate(...).

2. as required, take its values from its buffers using the CopyBuffer(...) function.

The second way. It is necessary if in the first case we want to pass not a price series, but an indicator series to the input indicator. I.e., in this case we are going to receive values calculated by the input indicator (2) that takes data of another indicator (1) on its own input. I.e., we want to build the indicator-totally-indicator chain.

Sequence of steps:

1. create a handle for the first (1) input indicator using one of the iIndicator(...) functions or IndicatorCreate(...) function.

2. create a handle of the second (2) indicator using the same method, but specify the handle of the first (1) as the last parameter(applied_price) when creating it.

Use CopyBuffer(...) function to retrieve its values from the indicator buffers as required.

The third method is also used for building indicator chains, but, in contrast to the previous method, the data source (input sequence) isn't fixed before compilation, it can be set by a user directly in the terminal. By specifying the appropriate parameter at the moment of indicator starting.

I will leave it to you to understand these mechanisms by yourself. I have provided a lot of direct links in the previous text to the key places in documentation that will help you to do this.

Let's focus only on the parameters of the short form of the call of OnCalculate():

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])

Their purpose is quite clearly documented. Here I just want to explain the very need (reasonableness) of passing them into this function. With the first and last parameter, I hope everything is clear enough. In order to perform calculations, we must have a buffer with input data (price[]) and know its current length. (don't forget that its length increases as the quotes fill in the terminal.)

But in addition, we must also know from the very beginning of the input row its data is strictly correct or the initial values should be ignored due to their (possible or guaranteed) incorrectness. In most cases, incorrectness is guaranteed to occur when the input data is the output of another indicator, but how else? Most indicators in order to calculate the value at any bar must use a certain amount of history data. But where can they be found "at the beginning of time"? They aren't present there, and therefore they are forced to begin generating their output values not from the starting history bar, but later (to the right), from the bar to the left of which the necessary amount of history data already exists.

Now, thanks to the details I have described above, the answer to the question

where does its value come from? // we are talking about the parameter begin

The answer is: in spite of the fact that this parameter is passed in the function by the terminal, the input indicator must take care of its contents! The terminal itself can check only price input rows (in this case the value of begin will be 0 and this is a correct value).Therefore, when you write any indicator (except for the purely experimental ones), you should make sure that it informs the terminal about the index of the beginning of the correct data in its output buffer. Is it clear? Otherwise, the "descendants" of this indicator can eat very unpleasant incorrect data, and in some cases, they can even get sick... :) Now, how to do it, the PlotIndexSetInteger() function is used, by specifying the identifier of the PLOT_DRAW_BEGIN property. Important! For 100% correctness of the generated indicator property, a single call of PlotIndexSetInteger(....PLOT_DRAW_BEGIN, ...) in OnInit()! Why so? Because our indicator can be itself formed on the data of another indicator, which has an initial indent on the history. That is, we have a non-zero value of begin on the input history, and there is no possibility to receive it in OnInit().

  PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod-1+begin);

And we have to make it (preferably once) in OnCalculate(), because in OnInit the value of begin is unknown.

Which of course leaves us with the right to make a preliminary (although not very meaningful) call as well

  PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod);

In OnInit().

This is exactly what is done in that indicator (Custom Moving Average.mq5) from which you took your sample for studying.

2. can a variable of the double type be of the int type?

Yes, a variable of double type can be initialized painlessly with a value of int type, if it is defined by a constant. // which is exactly what we can do in your example.

3. It seems that the terminal is also responsible for the value of variable prev_calculated

There is a subtlety here. In most cases, this value will be equal to the value returned by the OnCalculate() function in the previous call. In other words, in fact, it is in your hands. :) On the other hand, at first call there will be a zero value. And besides, the value can be reset (by the terminal) to zero always, when the terminal wants it. For example, this can happen during the quotes correction by a broker, during communication restart after a break, during reinitialization of a previous (input) indicator and so on.

4. it is not clear where in the interval from 0 to limit-1 the indicator is calculated

In this case, these values can't be calculated correctly (we don't have enough history for calculations). That's why they are simply assigned zero values.

// I would prefer to assign them corresponding input data, but it doesn't change the essence of the matter.

Reason: