Русский Español Português
preview
From Basic to Intermediate: Definitions (II)

From Basic to Intermediate: Definitions (II)

MetaTrader 5Examples |
151 0
CODE X
CODE X

Introduction

The materials provided here are for educational purposes only. It should not be considered in any way as a final application. Its purpose is not to explore the concepts presented.

In the previous article “From Basic to Intermediate: Definitions (I)” we discuss #define compilation directive. We saw how to use this directive to simplify, speed up, and make our code easier to implement, as well as how to use it creatively and effectively during the language learning phase to make everything a little easier. To use this resource, we must understand what we are doing. In general, we can provide our MQL5 code with a more exotic look. All right.

For this reason, there is a second way to use #define compilation directive. In order not to complicate what was discussed in the previous article, we decided to show this in a separate article. Thus, we can approach the issue more calmly. And you will be able to learn and practice in a much more enjoyable form, which will really make it easier to understand and master the concepts, since this knowledge will be of great importance for what we will see in the following articles, mainly when we start working at the programming level, which I already consider as intermediate.


What is macro?

To put it very simply, a macro is a small procedure that we can use several times in the code. This is a very simplified view of things. In fact, most often (and this extends to other situations that are a bit more complex) we create a macro when a part of code is repeated almost constantly. So instead of writing the same code over and over again, we put it all into one chunk or procedure called a macro.

However, this method of defining a macro is not really suitable. This is due to several factors that make creating such a definition even more difficult.

The problem is that macros are largely (if not almost always) defined in such a way that the code is placed inline, rather than inside the procedure, which would result in calls stacking and de-stacking elements in memory. In my opinion, this is the best definition of the macro. But saying that we use a macro to place the code inline does not mean to make it something special. And this is due to the fact that theoretically we can do this with any procedure or function. I say "theoretically" because I did not notice a big difference in the execution time of functions or procedures declared as inline or not.

You probably have no idea what we are talking about. Let me clarify the situation a little. Like in C and C++, there is a reserved word in MQL5 that I rarely notice with other programmers, at least here. This reserved word is inline. But what does this word mean in practice? Well, usually when a programmer creates a code, he can convert procedure calls or even function calls into inline code if the language allows it. In other words, we stop calling procedures and instead receive the code that grows exponentially in order to run faster. And that means using more memory.

This may seem silly or even crazy. However, when used correctly, forcing the compiler to create a faster code at the expense of using more memory can be a good solution. However, we must be careful when doing this, because if the code grows exponentially, sooner or later we will reach a dead end, since we will need more and more memory, and the performance in processing speed does not compensate for the cost of increasing the memory.

As an example, let's see how this can be done. To do this, look at the code below.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_Fibonacci_Element_Default   11
05. //+------------------------------------------------------------------+
06. void OnStart(void)
07. {
08.     Print("Result: ", Fibonacci_Recursive());
09.     Print("Result: ", Fibonacci_Interactive());
10. }
11. //+------------------------------------------------------------------+
12. uint Fibonacci_Recursive(uint arg = def_Fibonacci_Element_Default)
13. {
14.     if (arg <= 1)
15.         return arg;
16. 
17.     return Fibonacci_Recursive(arg - 1) +  Fibonacci_Recursive(arg - 2);
18. }
19. //+------------------------------------------------------------------+
20. inline uint Fibonacci_Interactive(uint arg = def_Fibonacci_Element_Default)
21. {
22.     uint v, i, c;
23. 
24.     for (c = 0, i = 0, v = 1; c < arg; i += v, c += 2)
25.         v += i;
26. 
27.     return (c == arg ? i : v);
28. }
29. //+------------------------------------------------------------------+

Code 01

Please pay attention to the explanation because it is very important to properly understand what a macro is when we use #define compilation directive to create a routine or procedure that will be used in our code.

Note that code 01 is very similar to what we have already seen in other articles. However, there is something different in line 20. This difference is precisely the reserved word inline. Now that we know how code 01 runs, we can ask: "But what is it about that simple word added in line 20 that makes the code different?”

The answer is that the code will be generated not as you might expect. This is because the same code, if translated into C or C++, will generate a slightly different code. It's not about what we see, but how the compiler will treat this way of writing the code.

Again, I assume that the MQL5 compiler does things in such a way that there is no noticeable difference between the code written as it is done in 01 and other code seen in previous articles. To be honest, I haven't noticed any difference in processing speed when using or not using inline in a procedure or function declaration.

In any case, when the compiler sees line 20, it will understand that EVERY time this Fibonacci_Interactive function appears in the code, ALL THE CODE between lines 20 and 28 must replace the call that exists as Fibonacci_Interactive. Whereas, it is necessary to create a database of local variables present in the procedure or function so that they do not conflict with possible local variables located in the place where the code will be added.

To clarify, this same 01 code will be compiled by the compiler as something like the following:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_Fibonacci_Element_Default   11
05. //+------------------------------------------------------------------+
06. void OnStart(void)
07. {
08.     Print("Result: ", Fibonacci_Recursive());
09.     
10.     {
11.         uint v, i, c, arg = def_Fibonacci_Element_Default;
12. 
13.         for (c = 0, i = 0, v = 1; c < arg; i += v, c += 2)
14.             v += i;
15. 
16.         Print("Result: ",  (c == arg ? i : v));
17. 
18.     }
19. }
20. //+------------------------------------------------------------------+
21. uint Fibonacci_Recursive(uint arg = def_Fibonacci_Element_Default)
22. {
23.     if (arg <= 1)
24.         return arg;
25. 
26.     return Fibonacci_Recursive(arg - 1) +  Fibonacci_Recursive(arg - 2);
27. }
28. //+------------------------------------------------------------------+

Code 02

However, code 02 is actually the code that will be created and executed. But please note that the changes to the code had to be made in a very specific way. And this will be done by the compiler. We, as programmers, only tell the compiler whether it should or should not place a function or procedure inline. But fine-tuning will be compiler’s responsibility.

All right, now you might be thinking, "Okay, there's no reason to worry because everything seems to be the same." Indeed, my dear reader. Here is a simple example. But keep in mind that the function in line 20 of code 01 will be used a thousand times in our code. The compiler will do what is shown in code 02 a thousand times. As a result, the executable file will become larger and larger, take up more and more space, and take more and more time to load. Even if the execution speed were higher, it would not be able to compensate for it.

So, if you understand this, then understanding what a macro is (as we will define it shortly) will be very simple. We can even define the first macro using this code. Notice that between lines 10 and 18 we have a complete code, or rather a block, isolated from the rest of the code. To turn this code into our first macro, we will simply change it to something like what is shown below:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_Fibonacci_Element_Default   11
05. //+------------------------------------------------------------------+
06. void OnStart(void)
07. {
08.     Print("Result: ", Fibonacci_Recursive());
09. 
10. #define macro_Fibonacci_Interactive     {                           \
11.         uint v, i, c, arg = def_Fibonacci_Element_Default;          \
12.         for (c = 0, i = 0, v = 1; c < arg; i += v, c += 2) v += i;  \
13.         Print("Result: ",  (c == arg ? i : v));                     \
14.                                         }
15. }
16. //+------------------------------------------------------------------+
17. uint Fibonacci_Recursive(uint arg = def_Fibonacci_Element_Default)
18. {
19.     if (arg <= 1)
20.         return arg;
21. 
22.     return Fibonacci_Recursive(arg - 1) +  Fibonacci_Recursive(arg - 2);
23. }
24. //+------------------------------------------------------------------+

Code 03

Now the most interesting part: code 03 is almost, let's be honest, almost the same as code 02. However, when being executed, the result will be different from code 02. Do you understand the difference, dear reader? Highly likely, you do not. This is because it is not so obvious when you first get acquainted with the macro.

Now notice the following: all we did different between codes 02 and 03 was adding #define compilation directive in line 10. It is followed by a constant. Yes, the macro IS A CONSTANT, never forget about it.

The macro, when defined, must be contained in ONE SINGLE LINE.

It is NOT POSSIBLE to create a macro that contains more than one line of code. This rule is dictated by the programming language. So, in order for us to create a macro from several lines, a special character at the end of each line must be added. This character can be seen on each of the lines starting from line 10, but be careful and DO NOT PUT THIS LINE on the last one. Otherwise, the macro will not be where we expect it to be and you may get an error warning when trying to compile the code.

Everything seems to be quite simple, does it? More or less. If being attentive, yes, creating macros is quite simple. But if you think that's all you will see in code 03, you are wrong. This will be a macro based on code 02. Please note that when executing code 03 the result will be different from code 02. But why? The reason is that the macro is NOT USED. We simply declare about it. Thus, at the output of code 02, as you can see in the figure below, we will have two messages.

Figure 01

However, when executing code 03, the output will be as follows:

Figure 02

But then how can this problem be solved? To do this, we must instruct the compiler to use the macro in the code. As you can see below, this is very simple.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_Fibonacci_Element_Default   11
05. //+------------------------------------------------------------------+
06. void OnStart(void)
07. {
08.     Print("Result: ", Fibonacci_Recursive());
09. 
10. #define macro_Fibonacci_Interactive     {                           \
11.         uint v, i, c, arg = def_Fibonacci_Element_Default;          \
12.         for (c = 0, i = 0, v = 1; c < arg; i += v, c += 2) v += i;  \
13.         Print("Result: ",  (c == arg ? i : v));                     \
14.                                         }
15. 
16.     macro_Fibonacci_Interactive;
17. }
18. //+------------------------------------------------------------------+
19. uint Fibonacci_Recursive(uint arg = def_Fibonacci_Element_Default)
20. {
21.     if (arg <= 1)
22.         return arg;
23. 
24.     return Fibonacci_Recursive(arg - 1) +  Fibonacci_Recursive(arg - 2);
25. }
26. //+------------------------------------------------------------------+

Code 04

Now, this is correct. When including line 16 in code 04, you get the same result as in image 01, indicating that the code runs as expected. However, that was the easiest part. Now we come to the most interesting part: Let's highlight a separate topic for this. This is necessary because we must first understand what has been shown up to this point in order to understand what will be done next.


Passing arguments to the macro

"Oh my God! I thought we were done, and here you are announcing that one can pass arguments to the macro." Let us now check if I understood the concept of a macro correctly. Correct me if I am wrong.

A macro is code that exists in a routine and that we want to place inline into our code, right? Exactly. You are right. So, if we can create a way to implement an entire function or procedure in a macro, we don't have to create that same function or procedure because it will not matter to the compiler when it compiles the code. Am I right? Again, correctly. However, there is just one small detail: procedures are easier to implement than functions, since functions in most cases require an additional variable. In any case, it is correct.

"Then I get it. If I want to pass an argument to a macro, I just should use the same declaration method as when declaring a function or a procedure. It's simple, it's obvious to me."

Well, in this case you are almost right. This is because we do not declare the arguments being passed in a macro in the same way as it is done when using a function or a procedure. In this case, things work a little differently, and this is where the difficulty lies. Unlike passing parameters in functions and procedures, where we can say "this argument cannot be controlled", "this argument can be", "this argument is of such-and-such a type" and "this argument is of such-and-such a type", in macros we DO NOT HAVE that kind of control. And therefore, to avoid some rather nasty errors, we have no assistance from the compiler.

This is where the difference is. For this reason, many programmers avoid using macros. This is because any carelessness in the code can result in serious trouble, as errors in macros are very difficult to fix precisely because they are difficult to find. The point is that in one part of the code, a macro can produce correct values, but in another part of the same code, a little further, the same macro can produce incorrect values. And being able to detect and fix this type of failure is, in my opinion, one of the most difficult and grueling tasks.

So be very careful when using macros in your code: they are a valuable resource, but they can make you waste hours solving a problem that would otherwise be easy to fix.

So let us now do the following: since code 04 is just a modification of code 01, to the extent that we can use macros, we can modify code 04 to understand how to pass values inside the macro.

Please pay attention to the following: in code 01, in lines eight and nine, we have the option to use two different functions: one where the answer will be recursive, and another one where the answer will be interactive. But in code 04, even though we have both responses, we CANNOT pass the value to the interactive computation part unless we change the value as specified in the definition in line 4. But this is not true, because we want to be able to pass any value, as in the case of code 01.

To make it easier to understand the above said, let us look at the code below.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_Fibonacci_Element_Default   11
05. //+------------------------------------------------------------------+
06. #define macro_Fibonacci_Interactive     {                           \
07.         uint v, i, c, arg = def_Fibonacci_Element_Default;          \
08.         for (c = 0, i = 0, v = 1; c < arg; i += v, c += 2) v += i;  \
09.         Print("Result: ",  (c == arg ? i : v));                     \
10.                                         }
11. //+----------------+
12. void OnStart(void)
13. {
14.     Print("Result: ", Fibonacci_Recursive(15));
15.     macro_Fibonacci_Interactive;
16. }
17. //+------------------------------------------------------------------+
18. uint Fibonacci_Recursive(uint arg = def_Fibonacci_Element_Default)
19. {
20.     if (arg <= 1)
21.         return arg;
22. 
23.     return Fibonacci_Recursive(arg - 1) +  Fibonacci_Recursive(arg - 2);
24. }
25. //+------------------------------------------------------------------+

Code 05

When we run code 05, as a result we will see what is shown in the image below.

Figure 03

Obviously, results are different. This happens because in line 14 of code 05 we pass a value as a function parameter in line 18. In the macro this is not the case, since the value is fixed in the definition of line 4. So, as you can see, working with macros requires some caution and increased attention. To solve this problem one should pass some argument to the macro. To do this, we will slightly change the macro code. This change can be seen in the code below:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_Fibonacci_Element_Default   11
05. //+------------------------------------------------------------------+
06. #define macro_Fibonacci_Interactive(arg) {                          \
07.         uint v, i, c;                                               \
08.         for (c = 0, i = 0, v = 1; c < arg; i += v, c += 2) v += i;  \
09.         Print("Result: ",  (c == arg ? i : v));                     \
10.                                         }
11. //+----------------+
12. void OnStart(void)
13. {
14.     Print("Result: ", Fibonacci_Recursive(15));
15.     macro_Fibonacci_Interactive(14);
16. }
17. //+------------------------------------------------------------------+
18. uint Fibonacci_Recursive(uint arg = def_Fibonacci_Element_Default)
19. {
20.     if (arg <= 1)
21.         return arg;
22. 
23.     return Fibonacci_Recursive(arg - 1) +  Fibonacci_Recursive(arg - 2);
24. }
25. //+------------------------------------------------------------------+

Code 06

Once code 06 is executed, the result will be as follows:

Figure 04

It is clear that the values are different, but we did this on purpose to show that we can pass independent values and that one is not related to the other. This makes it clear that a macro is not related to any other function or procedure.

This was interesting, but not exciting, since the macro goes neither like a function, as it would be in code 01, nor like a separate procedure. In reality, it is just isolated code. However, code 06 still runs as if it were code 02, which is, in most cases, completely useless since it serves absolutely no purpose other than placing what would have been line 15 of code 06 at various other points. But since these codes have a didactic purpose, they are simple and do not require the use of a tool such as macros. However, we are doing it here precisely to explain how to use it and work with it.

Let's think about how to make a macro go like a function. In fact, we CANNOT use a macro like the one in code 06 as a function. If you remember, a function is like a special variable: it always returns a value when we use it to retrieve a value based on the arguments passed to it. Note what we said. I AM NOT SAYING that we cannot use macros as functions. What I mean is that WE CANNOT use THIS MACRO as if it were a function. Be careful not to confuse sheep and goats.

However, despite this initial limitation, we can make THIS MACRO behave like a procedure in which we make a step by referrence. How? It is simple: change the code as shown below:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_Fibonacci_Element_Default   11
05. //+------------------------------------------------------------------+
06. #define macro_Fibonacci_Interactive(arg) {                          \
07.         uint v, i, c;                                               \
08.         for (c = 0, i = 0, v = 1; c < arg; i += v, c += 2) v += i;  \
09.         arg = (c == arg ? i : v);                                   \
10.                                         }
11. //+----------------+
12. void OnStart(void)
13. {
14.     ulong value;
15. 
16.     Print("Result: ", Fibonacci_Recursive((uint)(value = 15)));
17.     macro_Fibonacci_Interactive(value);
18.     Print("Checking: ", value);
19. }
20. //+------------------------------------------------------------------+
21. uint Fibonacci_Recursive(uint arg = def_Fibonacci_Element_Default)
22. {
23.     if (arg <= 1)
24.         return arg;
25. 
26.     return Fibonacci_Recursive(arg - 1) +  Fibonacci_Recursive(arg - 2);
27. }
28. //+------------------------------------------------------------------+

Code 07

Now things become interesting. The thing is that we started using the macro, say, for more noble purposes. Note the following: in line 14 we declare a variable, but WE DO NOT INITIALIZE IT. We initialize it in line 16. You might ask, "What the hell is going on in line 16?” Do not worry, it is not insane.

Please note that the variable in line 14 is of ulong type, while the type expected by the function in line 21 is of uint type. Since we want to use the same value for both the function in line 21 and the macro that will be used below, we should undertake an explicit type conversion to prevent the compiler from issuing warnings. For this reason, the declaration of line 16 looks like this.

Okay, right after that we have line 17. This is where the fun begins. This happens because we pass the variable by reference. Thus, when the macro changes variable’s value, this change will be reflected here in our main code. The value changes in line 9, so one should be vigilant. Otherwise, we might get a time bomb. And to demonstrate that this system works and can be used, we have line 18 where the value of the variable is output to the terminal. Having executed code 07, we will get the image shown below:

Figure 05

All right, I believe it is clear that each time we pass a variable to a macro, we do so by clicking the link. And that is why we must be careful that the macro doesn't change the value incorrectly. But wait a second. The type of macro we see in code 07 is a macro that runs as a procedure. Is there a way to use a macro as a function? That is, we can send one value and receive another in response. Many programmers have this question at the very beginning of learning macros.

Basically, macros are more procedure-oriented, but depending on how we build the code inside the macro, we can make it run as if it were a function. In this case, we handle the codes presented in these articles, we can create an example of this, just as a mode of representing the mechanism. Even though it is not very well thought out and may seem not very interesting, it is worth giving it a try. An example of this can be seen in the code below:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_Fibonacci_Element_Default   11
05. //+------------------------------------------------------------------+
06. #define macro_Ternário(A, B, C, D)  (A == B ? C : D)
07. //+----------------+
08. #define macro_Fibonacci_Interactive(arg) {                          \
09.         uint v, i, c;                                               \
10.         for (c = 0, i = 0, v = 1; c < arg; i += v, c += 2) v += i;  \
11.         arg = macro_Ternário(c, arg, i, v);                         \
12.                                         }
13. //+----------------+
14. void OnStart(void)
15. {
16.     ulong value;
17. 
18.     Print("Result: ", Fibonacci_Recursive((uint)(value = 15)));
19.     macro_Fibonacci_Interactive(value);
20.     Print("Checking: ", value);
21. }
22. //+------------------------------------------------------------------+
23. uint Fibonacci_Recursive(uint arg = def_Fibonacci_Element_Default)
24. {
25.     if (arg <= 1)
26.         return arg;
27. 
28.     return Fibonacci_Recursive(arg - 1) +  Fibonacci_Recursive(arg - 2);
29. }
30. //+------------------------------------------------------------------+

Code 08

Here, in code 08, we can see a small demo of a macro that runs as a function. This macro, defined in line six, is a simple example of how a macro can run as a function. Notice that in line 11 we use it. Essentially, this allows you to hide some of the complexities that may exist in the code, because depending on the name we give the macro, it is much easier to understand how it works.

Please note that the goal here is NOT TO make the code more efficient, but to make it more readable. For example, you can create a set of macros for manipulating date and time values to use the datetime type. This is a typical example for macros with the functionality of a function. To make this more visual, let us create some macros to demonstrate what we are talking about.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. enum eConvert {
05.     FORMAT_DECIMAL,
06.     FORMAT_OCTAL,
07.     FORMAT_HEX,
08.     FORMAT_BINARY
09. };
10. //+------------------------------------------------------------------+
11. #define macro_GetDate(A)            (A - (A % 86400))
12. #define macro_GetTime(A)            (A % 86400)
13. //+----------------+
14. #define macro_GetSec(A)             (A - (A - (A % 60)))
15. #define macro_GetMin(A)             (int)((A - (A - ((A % 3600) - (A % 60)))) / 60)
16. #define macro_GetHour(A)            (int)((A - (A - ((A % 86400) - (A % 3600)))) / 3600)
17. //+----------------+
18. #define PrintX(X)                   Print(#X, " => ", X);
19. //+------------------------------------------------------------------+
                   .
                   .
                   .

Snippet 01

In snippet 01 we have what will be our include file. I include macros to show that over time we can greatly expand our programming capabilities as we gain experience and build a specific library.

To test what these macros do between lines 11 and 18, let us use some test code. Please, find it just below:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #include "Tutorial\File 01.mqh"
05. //+------------------------------------------------------------------+
06. void OnStart(void)
07. {
08.     datetime dt = D'2024.08.15 12:30:27';
09.     ulong v;
10. 
11.     Print("Date And Time: ", dt);
12.     Print("0x", ValueToString(dt, FORMAT_HEX));
13.     PrintX((datetime)(v = macro_GetDate(dt)));
14.     Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL));
15.     PrintX((datetime)(v = macro_GetTime(dt)));
16.     Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL));
17.     PrintX((datetime)(v = macro_GetSec(dt)));
18.     Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL));
19.     PrintX((datetime)(v = macro_GetMin(dt)));
20.     Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL));
21.     PrintX((datetime)(v = macro_GetHour(dt)));
22.     Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL));
23. }
24. //+------------------------------------------------------------------+

Code 09

This is very interesting and exciting because without much effort we can analyze a number of things that would otherwise have to be done with the help of other resources that have not yet been explained. When we run code 09, it will display the following:

Figure 06

Now you will understand why I said that code 09 is quite interesting. In lines 13, 15, 17, 19 and 21 we have calls of the macro. This macro is defined in line 18 of snippet 01. The purpose of the macro is to tell us the name of the variable and its value. In this case, the variable name is a function that uses different macros in each of the lines mentioned in code 09. Note that this is a rather unusual and interesting combination, since the value being returned by each macro is placed into a local variable, and immediately afterwards the hexadecimal value of that variable is printed, as well as its decimal value.

This shows that we are indeed capturing the correct values in datetime format. I know many of you may think this is nonsense, but as you can see, this macro is very useful, especially when we want the code to run as fast and safe as possible. And it makes the whole work of writing the code much easier, more enjoyable and fun.


Final considerations

This article has considered what it is and how to treat macros for coding, as they are one of the resources that are often misused and in other cases completely ignored, precisely due to the lack of knowledge and practice in using them. Many programmers end up not understanding why something they thought was impossible (or even unachievable) can be done by another, often unknown, programmer.

I myself adhere (and I like to think so) to the following thesis:

There are no bad programmers, there are only those who have not found their way. Yes, there are both untrained professionals and professionals who consider themselves prepared, but in fact they are still new to programming.

Such concept that I am trying to convey to you in these articles is intended specifically for those who are just starting to learn programming. If you start on the right path, with a proper understanding of the concepts and reasons for the existence of a particular tool, it will be easier for you to turn your ideas into reality. So, dear readers, you may find this material rather silly and without a specific purpose or task, but if you realise and apply in practice what has been discussed here, you will find that many of the things that previously seemed difficult and tough to you will become quite achievable. Of course, there are still some things to clarify, but we have already taken many steps in the right direction.

Translated from Portuguese by MetaQuotes Ltd.
Original article: https://www.mql5.com/pt/articles/15588

Attached files |
Anexo.zip (4.58 KB)
From Basic to Intermediate: Overload From Basic to Intermediate: Overload
Perhaps this article will be the most confusing for novice programmers. As a matter of fact, here I will show that it is not always that all functions and procedures have unique names in the same code. Yes, we can easily use functions and procedures with the same name — and this is called overload.
Parafrac Oscillator: Combination of Parabolic and Fractal Indicator Parafrac Oscillator: Combination of Parabolic and Fractal Indicator
We will explore how the Parabolic SAR and the Fractal indicator can be combined to create a new oscillator-based indicator. By integrating the unique strengths of both tools, traders can aim at developing a more refined and effective trading strategy.
From Basic to Intermediate: Floating point From Basic to Intermediate: Floating point
This article is a brief introduction to the concept of floating-point numbers. Since this text is very complex please, read it attentively and carefully. Do not expect to quickly master the floating-point system. It only becomes clear over time, as you gain experience using it. But this article will help you understand why your application sometimes produces results different from what you expect.
Neural Networks in Trading: Parameter-Efficient Transformer with Segmented Attention (Final Part) Neural Networks in Trading: Parameter-Efficient Transformer with Segmented Attention (Final Part)
In the previous work, we discussed the theoretical aspects of the PSformer framework, which includes two major innovations in the classical Transformer architecture: the Parameter Shared (PS) mechanism and attention to spatio-temporal segments (SegAtt). In this article, we continue the work we started on implementing the proposed approaches using MQL5.