MQL4 - automated forex trading   /  

MQL4 Book

Login | Register | Language: ru cn en
Dozens financial books in MetaTrader Market

MQL4 Book  Creation of a Normal Program  Structure of a Normal Program

Upgrade to
Book in One File

Structure of a Normal Program


The outstanding feature of a normal program is its structure that allows your to easily use some user-defined functions or other. For convenience, user-defined functions are usually formed as include files (.mqh) that are stored in the folder Terminal_directory\experts\include.

As a rule, a normal program contains all three special functions that call the necessary user-defined functions for execution. User-defined functions, in their turn, can call other user-defined functions for execution, each of them having its own functionally bounded purpose.

An Expert Advisor can contain user-defined functions with the most diverse properties. Some functions, for example, are intended for tracking events and convenient data output, other functions are used to form trade requests, the third functions are intended for various calculations, for example, for defining of trading criteria, calculation of order costs, etc. The decision on what functions to use in a program depends on the EA purpose and on what service the program is intended to provide the user with. In Fig. 155 below, you can see a block diagram of a normal trading EA built on a small set of user-defined functions.



Fig. 155. Block diagram of a normal program (Expert Advisor).


The arrows in the diagram show the relationships between functions. For example, the order accounting function in the EA is called from the special functions init() and start(); it can also be called from any other location in the program. In the right part of the diagram, the connecting arrows are shown that symbolize the possibility to call one user-defined function from another. For example, the function defining trading criteria cannot be called from any special function, but it can be called for execution by a trade function. The data function is called from the special function deinit() and, if necessary, from other functions, for example, from the error processing function, trade functions, or from the event tracking function. The include file of variable declaration cannot be called from any function, since the code contained in it is not the description of a function that can be called and executed. This file contains the lines of global variable declaration, so it is just a part of an EA. In order to understand the way the different parts of an EA interrelate in, let's consider the order of creation and use of include files.

Using Include Files


If an application program contains a great variety of program lines, it is sometimes difficult to debug it - the programmer has to scroll the program text many times in order to make changes in the code in one or another location. In such cases, for convenience, the program can be divided into several fragments, each formed as a separated include file. Include files can contain any code fragments to be used in the program. Each function used in the program is usually formed as an include file. If several functions are logically interconnected, one include file may contain the description of several user-defined functions.

In the section Information about an Account, we consider an example of the protection code that prevents from unauthorized use of business programs. In the Expert Advisor check.mq4, the corresponding part of the program code is represented as the user-defined function Check(), the description of which is directly contained in the source code of the EA. In the EA usualexpert.mq4 (see Fig. 91.3), this function is used, too. However, in this case, the function is formed as the include file Check.mqh.

User-Defined Function Check()

bool Check()

The function returns TRUE, if the conditions of using the application program are complied with. Otherwise, it returns FALSE.

The conditions of using the program are considered as complied with, if:

  • the program is used on a demo account;
  • the account is opened with SuperBank;
  • the user has set the correct value of the external variable Parol when working on a real account.

The include file Check.mqh containing the description of the user-defined function Check():

//----------------------------------------------------------------------------------
// Check.mqh
// The program is intended to be used as an example in MQL4 Tutorial.
//----------------------------------------------------------------------------- 1 --
// The function checking legality of the program used
// Inputs:
// - global variable 'Parol'
// - local constant "SuperBank"
// Returned values:
// true - if the conditions of use are met
// false - if the conditions of use are violated
//----------------------------------------------------------------------------- 2 --
extern int Parol=12345; // Password to work on a real account
//----------------------------------------------------------------------------- 3 --
bool Check() // User-defined unction
{
if (IsDemo()==true) // If it is a demo account, then..
return(true); // .. there are no other limitations
if (AccountCompany()=="SuperBank") // For corporate clients..
return(true); // ..no password is required
int Key=AccountNumber()*2+1000001; // Calculate the key
if (Parol==Key) // If the password is true, then..
return(true); // ..allow the user to work on a real account
Inform(14); // Message about unauthorized use
return(false); // Exit the user-defined function
}
//----------------------------------------------------------------------------- 4 --

It is easy to note that the name of the include file is the same as the name of the function it contains. This is not required by the rules of MQL4. Generally, the name of an include file is not required to be the same as the name of the function it contains. It becomes even clearer, if we consider that one file may contain the description of several functions or of a program fragment that is not a function at all. However, the practice of giving an include file the same name as that of the contained function is feasible. This considerably facilitates the work of a programmer: using the file names, he or she will easily know what functions there are in the folder Terminal_directory\experts\include. In order to include the program fragment contained in the file, you should use the directive #include.

Directive #include


#include <File name>
#include "File name"


The directive #include can be specified in any location in the program. However, all included fragments are placed at the beginning of the source text file. Preprocessor will replace the line #include <file_name> (or #include "file_name") with the contents of the file of the given name.

Angle brackets mean that the file will be taken from the standard directory Terminal_directory\experts\include (the current directory is not viewed). If the file name is enclosed in quotation marks, it will be searched in the current directory, namely, in the directory that contains the basic file of the source text (the standard directory is not viewed).

Below is a normal Expert Advisor, usualexpert.mq4. All include files are placed in the head part of the program.

//----------------------------------------------------------------------------------------
// usualexpert.mq4
// The code should be used for educational purpose only.
//----------------------------------------------------------------------------------- 1 --
#property copyright "Copyright © Book, 2007"
#property link "http://AutoGraf.dp.ua"
//----------------------------------------------------------------------------------- 2 --
#include <stdlib.mqh>
#include <stderror.mqh>
#include <WinUser32.mqh>
//----------------------------------------------------------------------------------- 3 --
#include <Variables.mqh> // Description of variables
#include <Check.mqh> // Checking legality of programs used
#include <Terminal.mqh> // Order accounting
#include <Events.mqh> // Event tracking function
#include <Inform.mqh> // Data function
#include <Trade.mqh> // Trade function
#include <Open_Ord.mqh> // Opening one order of the preset type
#include <Close_All.mqh> // Closing all orders of the preset type
#include <Tral_Stop.mqh> // StopLoss modification for all orders of the preset type
#include <Lot.mqh> // Calculation of the amount of lots
#include <Criterion.mqh> // Trading criteria
#include <Errors.mqh> // Error processing function
//----------------------------------------------------------------------------------- 4 --
int init() // Special function 'init'
{
Level_old=MarketInfo(Symbol(),MODE_STOPLEVEL );//Min. distance
Terminal(); // Order accounting function
return; // Exit init()
}
//----------------------------------------------------------------------------------- 5 --
int start() // Special function 'start'
{
if(Check()==false) // If the usage conditions..
return; // ..are not met, then exit
PlaySound("tick.wav"); // At every tick
Terminal(); // Order accounting function
Events(); // Information about events
Trade(Criterion()); // Trade function
Inform(0); // To change the color of objects
return; // Exit start()
}
//----------------------------------------------------------------------------------- 6 --
int deinit() // Special function deinit()
{
Inform(-1); // To delete objects
return; // Exit deinit()
}
//----------------------------------------------------------------------------------- 7 --

In block 2-3, we included into the program standard files stdlib.mqh, stderror.mqh and WinUser32.mqh using the directive #include. It is not always necessary to use these files in the program. For example, file stderror.mqh contains the definition of standard constants used in error processing. If error processing is not provided in the program (i.e., these constants are not used), then there is no need to include this file into the source text. At the same time, it is usually necessary to include these files in a normal program.

In block 3-4, the program includes some files containing the description of user-defined functions. Using the directive #include in the line below:

#include <Check.mqh>       // Checking legality of programs used

the source text of the program includes the user-defined function Check(). Programmer can see the source code of the EA (in this case, usualexpert.mq4) as it is represented above. However, the source text of the program is modified at compilation, namely, each line containing the directive #include is replaced in the program with the text contained in the file of the given name. Thus, an executable file .ex4 is created on the basis of the full code of the Expert Advisor, in which each line #include<File name> (or #include "File name") is replaced with the corresponding code fragment.

An example of an include file containing a program fragment that is not the function description is file Variables.mqh. This file is included in the program text in the line:

#include <Variables.mqh>   // Description of variables

and contains the description of global variables used by different user-defined functions.

//----------------------------------------------------------------------------
// Variables.mqh
// The code should be used for educational purpose only.
//----------------------------------------------------------------------- 1 --
// Description of global variables
extern double Lots = 0.0;// Amount of lots
extern int Percent = 0; // Allocated funds percentage
extern int StopLoss =100; // StopLoss for new orders (in points)
extern int TakeProfit =40; // TakeProfit for new orders (in points)
extern int TralingStop=100; // TralingStop for market orders (in points)
//----------------------------------------------------------------------- 2 --
int
Level_new, // New value of the minimum distance
Level_old, // Previous value of the minimum distance
Mas_Tip[6]; // Order type array
// [] order type: 0=B,1=S,2=BL,3=SL,4=BS,5=SS
//----------------------------------------------------------------------- 3 --
double
Lots_New, // Amount of lots for new orders
Mas_Ord_New[31][9], // Current order array ..
Mas_Ord_Old[31][9]; // .. old order array
// 1st index = order number in the list
// [][0] cannot be detected
// [][1] order open price (abs. price value)
// [][2] StopLoss of the order (abs. price value)
// [][3] TakeProfit of the order (abs. price value)
// [][4] order number
// [][5] order volume (abs. price value)
// [][6] order type 0=B,1=S,2=BL,3=SL,4=BS,5=SS
// [][7] Order magic number
// [][8] 0/1 the fact of availability of comments
//----------------------------------------------------------------------- 4 --

According to the rules of MQL4, any variable (including global ones) must be declared before the first reference to this variable. For this reason, the file Variables.mqh is included into the program and located above the files of functions that use the values of the variables specified in this file. For the same reason, all global variables are placed in this file.

In some (rare) cases, it is technically possible to declare a global variable in an include file that describes the function, in which the value of this variable is first used in the program. In such cases, it is necessary to keep the file including order. I.e., the program line containing the directive #include that includes the file (with the declaration of a global variable) into the program must be located above in the text than the lines that include other files using the value of this global variable.

In other cases, it is even technically impossible to do this. For example, if we have two include files, each of them using two global variables, one of which is declared in one file and the other is declared in the other file, then we will get an error when compiling such a program, since, regardless the file including order, one of the variables is used before it is declared in the program. This is why it is a usual practice in a normal program to declare all global variables, without any exceptions, in one file that is included in the program before other files containing the description of user-defined functions.

In block 1-2 of the include file Variables.mqh, all external variables are specified, the values of which determine the amount of lots for new orders, the free margin percentage allocated for new orders, the requested prices for stop orders of the market orders to be opened, as well as the distance of TralingStop for modification of StopLoss order. In blocks 2-4, other global variables are given, the sense of which will become clear upon considering the corresponding user-defined functions. The subsections of this section represent include files, each containing the description of the user-defined function of the same name.