MQL4 - Learn Global Variables.
Several application programs can operate in the client terminal at the same time. In some cases the necessity may occur to pass some data from one program to another. Specially for this MQL4 has global variables of the client terminal.
Global variable of Client Terminal is a variable, the value of which is available from all application programs started in a client terminal (abbreviated form: GV).
Note, global variable of client terminal and global variable are different variables with similar names. The scope of global variables is one program, in which the variable is declared; while the scope of global variables of client terminal is all programs launched in the client terminal. |
Properties of GlobalVariables
As distinct from other variables, GV can be not only created from any program, but also deleted. GV value is stored on a hard disk and saved after a client terminal is closed. Once declared GV exists in the client terminal for 4 weeks from the moment of the last call. If during this period none of programs called this variable, it is deleted by the client terminal. GV can be only of double type.
Functions for Working with GlobalVariables
There is a set of functions in MQL4 for working with GV (see also GlobalVariables). Let's analyze those that will be used in further examples.
Function GlobalVariableSet()
datetime GlobalVariableSet( string name, double value)
This function sets up a new value of a global variable. If a variable does not exist, system creates a new global variable. In case of a successful execution the function returns the time of the last access, otherwise 0. To get an error information, function GetLastError() should be called.
Parameters:
name - Name of a global variable.
value - New numeric value.
Function GlobalVariableGet()
double double GlobalVariableGet( string name)
The function returns the value of an existing global variable or, in case of error, returns 0. To get an error information, function GetLastError() should be called.
Parameters:
name - Name of a global variable.
Function GlobalVariableDel()
bool GlobalVariableDel( string name)
This function deletes a global variable. In case of a successful deletion the function returns TRUE, otherwise - FALSE. To get an error information, function GetLastError() should be called.
Parameters:
name - Name of a global variable.
To show the convenience and benefit of using GlobalVariables, let's solve the following problem:
Problem 24. Several Expert Advisors work in a terminal at the same time. Deposit is $10 000. Total cost of all opened orders must not exceed 30% of the deposit. Equal amount should be allocated to each Expert Advisor. Create an EA program that would calculate the sum allocated for trading. |
Calculation of the sum allocated to an EA for trading is not difficult. However, for conducting this calculation we need to know the number of Expert Advisors launched in a program at the same time. There is no function in MQL4 that could answer this question. The only possibility of counting the number of launched programs is that each program should announce itself by changing the value of a certain GV. Further all programs needing this information can refer to this GV and detect the current condition.
It should be noted here, that in general case not every program is intended for solving such a problem. If an Expert Advisor occurs that does not announce its existence, it will not be counted. That is why in this case the problem definition presupposes using only those EAs that contain a necessary code - both for changing the GV value and for further reading the value of this variable.
Here is an Expert Advisor that demonstrates using GlobalVariables (globalvar.mq4); it can be used for solving Problem 24:
//--------------------------------------------------------------------
// globalvar.mq4
// The code should be used for educational purpose only.
//--------------------------------------------------------------------
int Experts; // Amount of EAs
double Depo=10000.0, // Set deposit
Persent=30, // Set percentage
Money; // Desired money
string Quantity="GV_Quantity"; // GV name
//--------------------------------------------------------------------
int init() // Special funct. init()
{
Experts=GlobalVariableGet(Quantity); // Getting current value
Experts=Experts+1; // Amount of EAs
GlobalVariableSet(Quantity, Experts); // New value
Money=Depo*Persent/100/Experts; // Money for EAs
Alert("For EA in window ", Symbol()," allocated ",Money);
return; // Exit init()
}
//--------------------------------------------------------------------
int start() // Special funct. start()
{
int New_Experts= GlobalVariableGet(Quantity);// New amount of EAs
if (Experts!=New_Experts) // If changed
{
Experts=New_Experts; // Now current
Money=Depo*Persent/100/Experts; // New money value
Alert("New value for EA ",Symbol(),": ",Money);
}
/*
...
Here the main EA code should be indicated.
The value of the variable Money is used in it.
...
*/
return; // Exit start()
}
//--------------------------------------------------------------------
int deinit() // Special funct. deinit()
{
if (Experts ==1) // If one EA..
GlobalVariableDel(Quantity); //..delete GV
else // Otherwise..
GlobalVariableSet(Quantity, Experts-1); //..diminish by 1
Alert("EA detached from window ",Symbol()); // Alert about detachment
return; // Exit deinit()
}
//--------------------------------------------------------------------
This EA contains three special functions. Briefly: all special functions are started by a client terminal: function init() - when an EA is attached to a security window, deinit() - when an EA id detached from a security window, start() - when ticks come. The head program part contains declaration of global variables (the scope of such variables is the whole program).
Money allocation between the EAs depends on one changeable parameter - number of simultaneously working EAs. That is why the GV that reflects the amount of EAs should be the only one, Its name is set in the line:
string Quantity = "GV_Quantity"; // GV name
Note: GlobalVariable name can be calculated in an executable program (names of other variables are set by a programmer at the stage of program creation). |
Let's analyze in details how the value of the variable Quantity is changed and processed when the program is executed. First of all, EA that is attached to a security window must announce its existence so that other EAs working in the terminal could know about it. This must be done possibly early (possibly close to the moment of attaching an EA to a security window). The best suiting place for it is the special function init(). In the first line of this function, EA requests the current value of the variable Quantity; function GlobalVariableGet() is used for this purpose:
Experts = GlobalVariableGet(Quantity); // Getting current value
Now the value of GV Quantity, no matter what it was at the moment of EA's attachment, must be increased by 1. It means that the EA that is being attached increases by 1 the amount of EAs simultaneously working in the terminal:
Experts = Experts+1; // Amount of EAs
Global variable Experts is used in the program for convenience sake. Its value is not available for other EAs. To change the value of GV Quantity, use the function GlobalVariableSet() that sets new GV value:
GlobalVariableSet(Quantity, Experts); // New value
It means new value of Experts is assigned to GV Quantity. Now this new GV value is available for all programs operating in the terminal. After that it calculates the desired sum allocated for trading to a just-attached EA and an Alert is created (here alerts are needed only for illustrating when and in what EA events happen; in a real program alerts are used only when needed).
Money = Depo*Persent/100/Experts; // Money for EAs
Alert("For EA in the window ", Symbol()," allocated ",Money);
Please note, that our EA calculated the desired sum only on the basis of attached EAs (it also counted itself). When init() execution is finished, control is passed to the client terminal and the EA starts waiting for a new tick. When a new tick comes, terminal will launch the special function start().
Now inside our Problem the purpose o the EA is tracing a current amount of attached EAs - Expert Advisors can be attached and detached; consequently, the amount of simultaneously working EAs may change. Depending on this our EA should recalculate the sum allocated in accordance with problem settings. So, the first thing done by the EA at each new tick is requesting the new value of GV Quantity:
int New_Experts= GlobalVariableGet(Quantity);// New amount of EAs
and if this new value New_Experts differs from the last known Experts, the new value is considered as a current one, Money allocated to an EA for trading is recalculated and the corresponding Alert is created:
if (Experts != New_Experts) // If changed
{
Experts = New_Experts; // Now current
Money = Depo*Persent/100/Experts; // New money amount
Alert("New value for EA ",Symbol(),": ",Money);
}
If variables New_Experts and Experts are identical, calculation is not made, in further EA code (in the function start()) the value of the variable Money calculated earlier is used. So depending on the situation at each tick either a new Money value is calculated or the previous one is used.
At the stage of detachment each Expert Advisor included into calculations in Problem 24 must inform other Expert Advisors that it has been detached, i.e. the number of Expert Advisors working at the same time diminished. Moreover, if this EA is the last one, GV must be deleted. The execution of deini() identifies the detachment of an EA, so the corresponding code should be located exactly in this function:
int deinit() // Special funct. deinit()
{
if (Experts ==1) // If one EA..
GlobalVariableDel(Quantity); //..delete GV
else // Otherwise..
GlobalVariableSet(Quantity, Experts-1); //..diminish by 1
Alert("EA detached from window ",Symbol()); // Alert about detachment
return; // Exit deinit()
}
All calculations in deinit() are conducted within one operator - if. If the number of EAs is equal to 1, i.e. this EA is the last one, GV is deleted using the function ClobalVariableDel(), in other cases (i.e. when the number of EAs is more than 1) a new value smaller by 1 is assigned to the variable Quality using GlobalVariableSet() function. EAs that remain attached to a security window will detect the new Quality value at the beginning of start() execution and will recalculated the desired value of Money.
It's easy to see that values of GlobalVariables can be read or changed from any executed EA using corresponding functions. Direct calculations with GV values are not allowed. For using GV values in a usual expression, this value must be assigned to any other variable and use this variable in calculations. In our case for this purpose two variables are used - Experts and New_Experts in the following lines:
Experts = GlobalVariableGet(Quantity); // Getting current value
int New_Experts= GlobalVariableGet(Quantity);// New amount of EAs
It is recommended to compile and start globalvar.mq4 in several windows of different securities. Depending on events sequence, corresponding events are displayed in the window of Alert function. For example:
Fig. 55. Alerts in the window of Alert function as a result of successive attachment and detachment
of the EA globalvar.mq4 in windows of three different securities.
There is an option in the client terminal to open the toolbar "Global Variables" where in real time mode one can see all currently open GlobalVariables and their values. This toolbar is available via client terminal menu Service >> Global Variables (F3 key):
Fig. 56. Toolbar of GlobalVariables at the moment when at the same time
three EAs
globalvar.mq4 are executed.
After all EAs have been detached, this toolbar does not contain any records about open global variables of client terminal.
Errors in Using GlobalVariables
If we start EA globalvar.mq4 in windows of different securities and successively trace all events, we will see that the code operates successfully. However it is so only if pauses between events are quite large. Pay attention to the operator 'if' in deinit():
if (Experts ==1) // If one EA..
In this case the value of the global variable Experts is analyzed. Though it reflects the GV value, it may get old (it should be remembered all programs operate in real time mode). To understand the reasons, let's see the following diagram:
Fig. 57. Detachment of an EA from EUR/USD window before the third tick.
Fig 57. shows development of events concerning the value of GV Quantity. Let's trace how this value will change depending on what is going on. Suppose the EA's execution started at the moment t 0. At this moment GV Quantity does not yet exist. In the period t 0 - t 1 EA's special function init() is executed, as a result GV Quantity is created, its value at the moment t 1 is equal to 1. Next ticks of EUR/USD launch the special function start(). However in the period t 0 - t 6 there is only one EA in the client terminal, that is why the value of GV Quantity does not change.
At the moment t 6 the second EA is attached to GBP/USD chart. AS a result of its init() execution value of GV Quantity changes and at the moment t 7 is equal to 2. After that at the moment t 8 the third EA is attached to USD/CHF chart, as a result at the moment t 9 GV Quantity is equal to 3.
At the moment t 10 a trader decides to remove an EA from EUR/USD window. Note, last time the variable Experts of the EA operating in this window was changed during the execution of start() launched at the second tick, i.e. in the period t 4 - t 5. At the moment t 10 the value of Experts in the EA operating in EUR/USD window is still equal to 1. That is why when deinit() of this EA is executed, GV Quantity will be deleted as a result of execution of the following lines:
if (Experts ==1) // If one EA..
GlobalVariableDel(Quantity); //..delete GV
Thus, though there are still two EAs attached, GlobalVariable is deleted! It's not difficult to understand, what consequences this even will have in the calculations of attached EAs. At start() execution, these EAs will detect that the current value of New_Experts is equal to zero, that's why the new value of Experts will also be zeroed. As a result the value of Money cannot be calculated, because in the formula used for calculations Experts is in the denominator. Thus further calculations in EAs will be erroneous.
Besides, at the execution of EAs' deinit() functions (when detaching from GBP/USD and USD/CHF) GV will be opened again, but the value will be equal to -1 after one of them is detached and -2 after the last one is detached. All this will result in a negative value of Money. Important is the fact that after all EAs are detached, GV Quantity will remain open in the client terminal and further will influence operation of all EAs that use its value.
There is also another possible case. Gig. 58 shows how GV value will change if before an EA is detached one more tick comes.
Fig. 58. Detaching EA from EUR/USD window after the third tick.
Events reflected in Fig. 58 in the period t 0 - t 9 fully coincide with event shown in Fig. 57. In accordance with the diagram, at the moment t 12 the third tick comes for EUR/USD; as a result during start() execution the value of Experts will change and will be equal to 3. It means after removing the EA from EUR/USD chart as a result of deinit() execution the value of Experts will be set equal to 2, i.e. correctly reflecting the number of EAs remaining operating.
On the bases of this reasoning it can be concluded that the EA globalvar.mq4 is created incorrectly. The algorithmic error in this case consists in the fact that for analyzing the situation the value of Experts variable that does not reflect the actual amount of simultaneously working EAs in all cases is used in the function deinit(). For the case described in Fig, 58 the value of Experts is true, while for the case in Fig. 57 - it is not. So the general result of EA operation depends on accidental events, namely on the sequence of receiving ticks of securities, with which the EA works.
In this case the error can be easily fixed. We need simply to update the value of Experts before analysis (before the execution of the operator if):
int deinit() // Special funct. deinit()
{
Experts = GlobalVariableGet(Quantity); // Getting current value
if (Experts ==1) // If one EA..
GlobalVariableDel(Quantity); //..delete GV
else // Otherwise..
GlobalVariableSet(Quantity, Experts-1); //..diminish by 1
Alert("EA detached from window ",Symbol()); // Alert about detachment
return; // Exit deinit()
}
Such algorithmic errors are dangerous because they are not always obvious and it is hard to detect them. But this does not mean that a user should refuse using GlobalVariables. However, it means that a code of any program must be constructed correctly taking into account all events that can influence the program performance.
Using global variables in practical work may be very helpful: for example, this helps to inform about critical events on another security (reaching of a certain price level, its breaking, etc.), about attachment of another Expert Advisor (with the purpose of sharing authority), conduct synchronized trading upon several securities at the same time. Global variable of client terminal can also be created from an indicator that calculates some important events; the value of such a variable can be used by any operating Expert Advisor or script.
Source: book.mql4.com/variables/globals.
No comments:
Post a Comment