MQL4 Book  Creation of a Normal Program  Data Function

Data Function


A normal Expert Advisor used in our practical work favorably compares to its simple analogs, because it provides a trader with high-quality information support.

During trading, the situation changes all the time, various events take place. To make proper decisions, a trader must be fully informed. For this purpose, various functions are used in Expert Advisors. These functions are aimed at informing the user about a certain set of facts and processes.

In simple Expert Advisors, as a rule, this task is performed by the standard function Comment() that displays the preset text in the upper left corner of the symbol window. This information output method is not quite comfortable, since the text can often be superimposed onto the price chart. So this method can only be used in a limited amount of cases, to display short messages.

We will consider here a conceptually different method of displaying information - the entire message is shown in a separate window, whereas graphical objects are used to form message texts. The use of graphical objects produces a tangible advantage, since you can move objects (unlike texts shown using Comment()) creating, in this manner, your message history.

A separate subwindow for displaying of information is created using a custom indicator adjusted correspondingly. The only purpose of this indicator is the creation of that subwindow, so no calculations are performed in the indicator, nor indicating lines are built in it. The code of the indicator Inform.mq4 may look as follows:

//--------------------------------------------------------------------
// Inform.mq4
// The code should be used for educational purpose only.
//--------------------------------------------------------------------
#property indicator_separate_window // Separate indicator window
//--------------------------------------------------------------------
int start() // Special function start()
{
}
//--------------------------------------------------------------------

Generally, a programmer may add into the indicator his or her desired code and contribute to its properties. For example, you can display indicating lines in a certain part of the indicator subwindow. In the above example, a simple code of the indicator is given, in the window of which graphical objects will be shown.


User-Defined Function Inform()

int Inform(int Mess_Number,int Number=0,double Value=0.0)

The function displays in the subwindow of the indicator Inform.mq4 messages created using graphical objects. The function controls the position of graphical objects in the indicator subwindow: every new message is displayed in the lower part of the window (lower line) and colored in the desired color, the previously shown messages being moved into the upper part of the window (one line upward). If no new messages are displayed within 15 seconds, all previously displayed messages in the window will be colored in gray (in order not to create diversions for the user) when the program refers to the function.

Parameters:

Mess_Number - message number that can take the following values:

  • (zero) 0 - no message is displayed, this mode is used to reset the timer;
  • (minus one) -1 - all graphical objects created by the function will be deleted;
  • (one or more) - the number of the message to be displayed in the indicator subwindow;

Number - integer used in some messages;

Value - real number used in some messages.

The function Inform() that creates graphical objects, like other functions in a normal EA,is formed as an include file, Inform.mqh:

//----------------------------------------------------------------------------
// Inform.mqh
// The code should be used for educational purpose only.
//----------------------------------------------------------------------- 1 --
// Function that displays graphical messages on the screen.
//----------------------------------------------------------------------- 2 --
int Inform(int Mess_Number, int Number=0, double Value=0.0)
{
// int Mess_Number // Message number
// int Number // Integer to be passed
// double Value // Real number to be passed
int Win_ind; // Indicator window number
string Graf_Text; // Message line
color Color_GT; // Color of the message line
static int Time_Mess; // Last publication time of the message
static int Nom_Mess_Graf; // Graphical messages counter
static string Name_Grf_Txt[30]; // Array of graphical message names
//----------------------------------------------------------------------- 3 --
Win_ind= WindowFind("inform"); // Searching for indicator window number
if (Win_ind<0)return; // If there is no such a window, leave
//----------------------------------------------------------------------- 4 --
if (Mess_Number==0) // This happens at every tick
{
if (Time_Mess==0) return; // If it is gray already
if (GetTickCount()-Time_Mess>15000)// The color has become updated within 15 sec
{
for(int i=0;i<=29; i++) // Color lines with gray
ObjectSet( Name_Grf_Txt[i], OBJPROP_COLOR, Gray);
Time_Mess=0; // Flag: All lines are gray
WindowRedraw(); // Redrawing objects
}
return; // Exit the function
}
//----------------------------------------------------------------------- 5 --
if (Mess_Number==-1) // This happens at deinit()
{
for(i=0; i<=29; i++) // By object indexes
ObjectDelete(Name_Grf_Txt[i]);// Deletion of object
return; // Exit the function
}
//----------------------------------------------------------------------- 6 --
Nom_Mess_Graf++; // Graphical messages counter
Time_Mess=GetTickCount(); // Last publication time
Color_GT=Lime;
//----------------------------------------------------------------------- 7 --
switch(Mess_Number) // Going to message
{
case 1:
Graf_Text="Closed order Buy "+ Number;
PlaySound("Close_order.wav"); break;
case 2:
Graf_Text="Closed order Sell "+ Number;
PlaySound("Close_order.wav"); break;
case 3:
Graf_Text="Deleted pending order "+ Number;
PlaySound("Close_order.wav"); break;
case 4:
Graf_Text="Opened order Buy "+ Number;
PlaySound("Ok.wav"); break;
case 5:
Graf_Text="Opened order Sell "+ Number;
PlaySound("Ok.wav"); break;
case 6:
Graf_Text="Placed pending order "+ Number;
PlaySound("Ok.wav"); break;
case 7:
Graf_Text="Order "+Number+" modified into the market one";
PlaySound("Transform.wav"); break;
case 8:
Graf_Text="Reopened order "+ Number; break;
PlaySound("Bulk.wav");
case 9:
Graf_Text="Partly closed order "+ Number;
PlaySound("Close_order.wav"); break;
case 10:
Graf_Text="New minimum distance: "+ Number;
PlaySound("Inform.wav"); break;
case 11:
Graf_Text=" Not enough money for "+
DoubleToStr(Value,2) + " lots";
Color_GT=Red;
PlaySound("Oops.wav"); break;
case 12:
Graf_Text="Trying to close order "+ Number;
PlaySound("expert.wav"); break;
case 13:
if (Number>0)
Graf_Text="Trying to open order Sell..";
else
Graf_Text="Trying to open order Buy..";
PlaySound("expert.wav"); break;
case 14:
Graf_Text="Invalid password. EA doesn't function.";
Color_GT=Red;
PlaySound("Oops.wav"); break;
case 15:
switch(Number) // Going to the error number
{
case 2: Graf_Text="Common error."; break;
case 129: Graf_Text="Wrong price. "; break;
case 135: Graf_Text="Price changed. "; break;
case 136: Graf_Text="No prices. Awaiting a new tick.."; break;
case 146: Graf_Text="Trading subsystem is busy"; break;
case 5 : Graf_Text="Old version of the terminal."; break;
case 64: Graf_Text="Account is blocked."; break;
case 133: Graf_Text="Trading is prohibited"; break;
default: Graf_Text="Occurred error " + Number;//Other errors
}
Color_GT=Red;
PlaySound("Error.wav"); break;
case 16:
Graf_Text="Expert Advisor works only for EURUSD";
Color_GT=Red;
PlaySound("Oops.wav"); break;
default:
Graf_Text="default "+ Mess_Number;
Color_GT=Red;
PlaySound("Bzrrr.wav");
}
//----------------------------------------------------------------------- 8 --
ObjectDelete(Name_Grf_Txt[29]); // Deleting 29th (upper) object
for(i=29; i>=1; i--) // Cycle for array indexes ..
{ // .. of graphical objects
Name_Grf_Txt[i]=Name_Grf_Txt[i-1];// Raising objects:
ObjectSet( Name_Grf_Txt[i], OBJPROP_YDISTANCE, 2+15*i);
}
Name_Grf_Txt[0]="Inform_"+Nom_Mess_Graf+"_"+Symbol(); // Object name
ObjectCreate (Name_Grf_Txt[0],OBJ_LABEL, Win_ind,0,0);// Creating
ObjectSet (Name_Grf_Txt[0],OBJPROP_CORNER, 3 ); // Corner
ObjectSet (Name_Grf_Txt[0],OBJPROP_XDISTANCE, 450);// Axis Х
ObjectSet (Name_Grf_Txt[0],OBJPROP_YDISTANCE, 2); // Axis Y
// Текстовое описание объекта
ObjectSetText(Name_Grf_Txt[0],Graf_Text,10,"Courier New",Color_GT);
WindowRedraw(); // Redrawing all objects
return;
}
//----------------------------------------------------------------------- 9 --

In block 2-3, the variables used in the function are described. To store the names of graphical objects, the array Name_Grf_Txt is used. According to the method accepted in the function, the program creates a new graphical object for each new message. The total amount of objects is 30, each object represents a text entry located in one line. In case of large screen resolution, the amount of lines to be shown can be increased by increasing of the amount of objects to be created.

In block 3-4, the number of the subwindow of the indicator "Inform" is calculated for messages to be shown in. If the indicator is not attached, the function stops its operations. If there is no window, the messages cannot be displayed, but this does not affect the workability of the EA - all other functions will work in their normal modes, trades will be performed, as well.

In block 4-5, the message colors are analyzed. The function with the parameter Mess_Number=0 is called in the Expert Advisor at every tick (see the function start() in Expert Advisor usualexpert.mq4). If all objects are gray in the preceding history, the function ends its operations. However, if the value of the variable Time_Mess is nonzero, the properties of all objects are changed, namely, all objects will be colored in gray.

If (block 5-6) the parameter Mess_Number=-1 is specified in the function call, all objects previously created at the execution of the function are deleted. This may be necessary when the EA is detached from the symbol window. In this case, according to the common rule, each application program must delete all objects it created during execution (see the function deinit() in the Expert Advisor usualexpert.mq4).

If the control in the program is passed to block 6-7, this means that it is necessary to create a new graphical object with required properties and place it in the lower part of the indicator subwindow (in the lower line; here, the term of "line" is conditional; in fact, the location of graphical objects is determined by the preset coordinates). Each newly created object has its unique name. To create object names, we use the historical number of the message, this is why the messages counter is placed in block 6-7 (at a later stage, the value of the variable Nom_Mess_Graf is used to form a unique name, block 8-9). It is here where the last publication time is accounted and the basic color is established for new messages (green).

Block 7-8 consists of the operator 'switch', inside which the control is passed according to the value of the parameter Mess_Number specified in the function call. In each 'case' of this operator of the variable Graf_Text, a new value is assigned that is the content of the message to be displayed. A special color is set for some messages, for example, red for important messages. All messages are accompanied with sounds that are the execution of the standard function PlaySound() (see Wave Files).

The creation of a new graphical object and replacing of the existing ones are performed in block 8-9. The amount of objects is limited, so one object (the oldest one) is deleted every time when a new message is published. All other existing objects are moved one line upwards. Objects are moved by changing their properties - vertical coordinates. The horizontal coordinates of objects remain unchanged.

After all necessary preparations have been made (all objects are moved one line upwards), a new object with new unique name and with properties partially determined in block 7-8 is created. The type of the graphical object is Text Label. The objects of this type are positioned relative to the symbol window, which allows the user to move price chart arbitrarily, without affecting the positions of messages.

The function Inform() can be called from any location in the program where, implicitly, a text message should be displayed. As a result of long processing, messages are accumulated in the window. The user can view the messages history by resizing the indicator subwindow (for example, by dragging up its upper edge). Optionally, you can also set the window height in such a way that the visible space displays the desired amount of message lines (three-four lines are usually recommended).


Fig. 156. Symbol window. Message in the indicator Subwindow.

It is easy to see that the diversity of messages displayed by the function can be increased. If you are going to expand the program, it is sufficient just to add the new version of 'case' in the operator 'switch' (block 7-8).