MQL4参考 语言基础 更新的MQL4

What's New in MQL4

Starting from build 600, MQL4 programming language has been completely revised reaching the level of MQL5 - now you can develop trading robots in MQL4/5 using the unified MetaEditor development environment, single style, libraries and debugging tools.

MQL4 is popular among automated system developers due to the ease of learning and a huge amount of code generated for many years of using MetaTrader 4 terminal. However, the language also has some drawbacks arising from its main advantage - a simple programming language does not allow development of complex systems and hinders porting of debugged libraries from high-level languages. Therefore, we decided to implement in it the maximum possible amount of MQL5 language functions and features fully preserving MQL4 functionality. In other words, all powerful MQL5 functions, including ООP and the native code compiler, will become available in MQL4.

To achieve this, we have developed a unified compiler that automatically supports both MQL4 and MQL5 languages. MetaEditor will also become a unified application both for MetaTrader 4 and MetaTrader 5 platforms. Thus, it will be possible to compile both MQL4 and MQL5 from any version. MQL5 Storage also becomes available for work.

Protection of MQL4 applications rises to MQL5 level. New EX4/EX5 files are provided with a serious and completely revised protection. This means that the Market of secure EX4 applications also becomes available to MetaTrader 4.

Besides, MQL4 now features new graphical objects and new functions for working with charts. MQL5 Standard Library is to be ported to MQL4 providing developers with new possibilities in creating their own graphical interfaces and trading libraries. Now, you can create full-fledged applications in MetaTrader 4 using the resources.
 

Changes in MQL4 Language

Added new char, short, long, uchar, ushort, uint, ulong and double data types. This will allow transferring codes from other C++ like languages. Data of various types is processed at different rates. Integer data is the fastest one to be processed. A special co-processor is used to handle the double-precision data. However, due to the complexity of the internal representation of floating-point data, it is processed slower than integer one. Typecasting has also been implemented.

Strings are now presented in Unicode format, though they were in ANSI format (single byte ones) before. That should be considered if the program uses DLLs and passes string variables to them.

Predefined Volume variable is now of long type. The time series for accessing the volumes also consist of long type arrays. It is recommended to use explicit casting of data having this type to the target type in old MQL4 programs to avoid type overflow error.

Structures and classes, object pointers, void type and this key word allowing an object to receive a reference to itself have been added. All object-oriented programming standards are supported:

ООP allows developing programs using classes. This facilitates debugging and development of large applications, as well as provides ability to reuse previously generated code multiple times due to inheritance. However, that does not mean that you cannot generate your MQL4 code in procedure-oriented style as before. You can develop your programs as you did in the past if you don't need the new features.

init(), deinit() and start() predefined functions have remained for compatibility, however, OnInit(), OnDeinit(), OnStart(), OnCalculate() and OnTick() ones can now be used instead. Besides, new predefined OnTimer(), OnChartEvent() and OnTester() handler functions have been implemented. In the previous MQL4, predefined functions could have any parameters and any return type, and they could be called by their names, not signatures. In the new MQL4, all predefined functions should strictly correspond to their signatures. In other words, they should have precisely defined set of parameters and return type.

Now, variable names cannot contain special characters and points, and new MQL4 language keywords cannot be used as names. Old MQL4 programs can be recompiled with the new compiler in order to easily correct all such errors while following the compiler's messages.

The Precedence rule now matches C language standards. If you are unsure, you can insert parentheses in old MQL4 apps to clearly indicate the priority to increase reliability.

Shortened conditions check is now used in logical operations, unlike the old MQL4 version where all expressions have been calculated and the check has been performed afterwards. Suppose there is a check of two conditions with the use of logical AND:

  if(condition1 && condition2)
    {
     // some block of statements
    }

If condition1 expression is false, calculation of condition2 expression is not performed, as false && true result is still equal to false.

 

ArrayCopyRates() function behavior has changed. In the previous MQL4 versions this function was used for copying price series to array double[][6]. Now, if you need to receive a time series, use the arrays of the MqlRates structure elements:

//--- Structure that stores information about the prices, volumes and spread.
struct MqlRates
  {
   datetime time;         // Period start time
   double   open;         // Open price
   double   high;         // The highest price of the period
   double   low;          // The lowest price of the period
   double   close;        // Close price
   long     tick_volume;  // Tick volume
   int      spread;       // Spread
   long     real_volume;  // Trade volume
  };

Also the new function format can be used for virtual copying, when there is no actual copying, and accessing the copied values you actually access the price data.

int  ArrayCopyRates(
   MqlRates&  rates_array[],   // MqlRates array, passed by reference
   string     symbol=NULL,     // symbol
   int        timeframe=0      // timeframe
   );

To provide compatibility with old MQL4 programs, the previous call format is also preserved, but now it leads to actual copying of data into a double-type array.

int  ArrayCopyRates(
   void&     dest_array[][],    // destination array, passed by reference
   string    symbol=NULL,       // symbol
   int       timeframe=0        // timeframe
   );

This means that when the values in the time series change (new bars are added, restructuring, the last bar's Close price is uodated), you must re-copy the required data into the dest_array[][]. The receiver array will be automatically allocated for the required number of copied bars, even if it was declared statically.

 

Changed RateInfo history data storage format. RateInfo structure was presented as follows in the old version:

struct RateInfo
  {
   unsigned int      ctm;   // bar open date
   double            open;  // Open price
   double            low;   // Low price
   double            high // High price
   double            close// Close price
   double            vol;   // volume
  };

In the new format, RateInfo structure features fields for storing spread and trading volume:

//--- Standard quote presentation in the new terminal version
struct RateInfo
  {
   INT64             ctm;               // open date and time
   double            open;              // Open price (absolute value)
   double            high;              // Low price
   double            low;               // High price
   double            close;             // Close price
   UINT64            vol;               // tick volume
   INT32             spread;            // spread
   UINT64            real;              // trade volume
  };

Thus, if MQL4 programs contain DLLs for passing/accepting price data, the corresponding functions in the source codes should be rewritten and recompiled considering format changes to ensure proper operation.

Old EX4 applications and DLLs based on old RateInfo format will not work in the new terminal. Conversion to the new format is required.

 

In file operations, the number of simultaneously opened files can now reach 64 ones, while there could be no more than 32 ones in the old MQL4. Until recently, the files were always opened in FILE_SHARE_READ or FILE_SHARE_WRITE mode. Now, the necessary opening mode should be specified explicitly.

For FileWrite(), FileWriteArray(), FileWriteDouble(), FileWriteInteger() and FileWriteString() functions the type of returned value has been changed from int to uint. The functions return the number of bytes, actually written or 0 in case of error (in old version of MQL4 the negative number is returned in case of error).

Working with functions, scope of variables and memory release in local arrays has also been changed. Since the number of changes is large enough, the new #property strict property has been introduced to provide maximum compatibility with the previous approach to developing MQL4 programs. When creating new MQL4 application using MQL wizard, this property is always added to the template.

The string representation of datetime type depends on compilation mode:

  datetime date=D'2014.03.05 15:46:58';
  string str="mydate="+date;
//--- str="mydate=1394034418" - old compiler/new compiler without #property strict
//--- str="mydate=2014.03.05 15:46:58" - new compiler with #property strict

The table below contains the differences between MQL4, new MQL4 without using strict and new MQL4 with specified strict compilation mode:

#property strict

When compiling libraries in the strict mode, the export modifier should be added for each exported function, otherwise the function will not be accessible from outside.

The table of differences between compilers:

Old MQL4 compiler

New MQL4 compiler

New MQL4 with #property strict

init(), start() and deinit() entry points may have any parameters and any return type

init(), start() and deinit() have been remained intact for compatibility,

while new OnInit(), OnStart(), OnCalculate(), OnTick(), OnTimer(), OnChartEvent(), OnTester() and OnDeinit() should strictly correspond to their signatures

Ditto

The result of the return from init() function is not analyzed by the runtime subsystem

The result of the return from init() and OnInit() functions is not analyzed by the runtime subsystem

If a non-zero value is returned from OnInit(), the operation of an Expert Advisor or an indicator is stopped, the program is unloaded

Virtually any variable names (except for the reserved words) are possible, including special characters and points

Variable names cannot have special characters and points.

The list of the reserved words has been expanded. Thus, such widespread words as short, long, const, etc. cannot be used as names

Ditto

Variable scope is from declaration (even in the nested block) to the function end

Ditto

Variable scope is from declaration to the end of the block, in which the variable is declared

Implicit initialization of all the variables (both global and local ones) by zero

Ditto

Only global variables are initialized. In local variables, only strings are initialized implicitly

Local arrays are not released when exiting the function

Local arrays are released when exiting the function

Local arrays are released when exiting {} block

"Array out of range" does not cause a critical error

Ditto, except for the arrays of structures and classes, for which this error is critical one

"Array out of range" is a critical error causing the program to stop

No structures and classes

Structures and classes are present. Additional data types are implemented

Ditto

Strings are single-byte.

datetime is a 32-bit integer

Predefined Volume variable is of double type

Strings are unicode ones.

datetime is a 64-bit integer

Predefined Volume variable is of long type

Ditto

ArrayCopyRates() performs virtual copying to double[][6] array

ArrayCopyRates() performs virtual copying to MqlRates[] array. Copying to double[][6] array has remained intact for the sake of compatibility, however, that copying is real, not virtual.

Ditto

The functions may not return values even if they have a type. To do this, return(0) is automatically inserted by the compiler in the function end

Ditto

Functions of any type should return a value

The number of simultaneously opened files is 32

The number of simultaneously opened files is 64

Ditto

The files are always opened in FILE_SHARE_READ, FILE_SHARE_WRITE mode **

FILE_SHARE_READ and/or FILE_SHARE_WRITE should be specified explicitly

Ditto

The names of extern variables are displayed for scripts in the input parameters window

The names of extern and input variables are displayed for scripts in show_inputs mode in the input parameters window

String comments instead of extern and input variable names are displayed for scripts in show_inputs mode in the input parameters window

* Please pay special attention to "Array out of range" error - many old custom indicators will display this error in strict mode of the new compiler when launched on the chart. It is recommended to find the cause and eliminate it.

**  In the new MQL4 and MQL5, FILE_SHARE_READ and FILE_SHARE_WRITE flags are responsible for the files shared use mode. There were no such files in the old MQL4.

 

Changes in File Structure

In the previous builds of MetaTrader 4 client terminal (509 and older), all MQL4 applications were stored in the following subdirectories of <terminal_installation_folder>\experts\ root directory:

  • \experts - Expert Advisors (trading robots),
  • \experts\indicators - custom indicators,
  • \experts\scripts - scripts (MQL4 applications for a single run on the chart),
  • \include - source code MQH and MQ4 files implemented into other programs,
  • \libraries - libraries in the form of MQ4 source codes and EX4 executable files compiled from them. They are used for the dynamic call of the functions contained there by other MQL4 programs,
  • \files - special "file sandbox". MQL4 applications are allowed to execute file operations only within this directory.

 
In the new MQL4 version, the file structure for storing the source codes has changed. Now, all MQL4 applications should be located in the appropriate folders of <data_folder>\MQL4\ directory:

  • \Experts - Expert Advisors (trading robots),
  • \Indicators - custom indicators,
  • \Scripts - scripts (MQL4 applications for a single run on the chart),
  • \Include - source code MQH and MQ4 files implemented into other programs,
  • \Libraries - libraries in the form of MQ4 source codes and EX4 executable files compiled from them. They are used for the dynamic call of the functions contained there by other MQL4 programs,
  • \Images - image files for using in resources,
  • \Files - special "file sandbox". MQL4 applications are allowed to execute file operations only within this directory.

When updating MetaTrader 4 terminal from build 509 to the newer version, all MQ4, MQH and EX4 files from standard root directories of the previous version are automatically copied and relocated to the appropriate folders. Subfolders additionally created by a user, as well as files contained there are not processed. They should be relocated to the new place manually if necessary.
 

No files or folders are deleted during the update! All file copy operations including used file paths are fixed in the terminal Journal during the update.

 
No automatic re-compilation of the old EX4 files to the new version is performed during the update. Users are free to decide what source codes should be compiled to the new EX4 version. All old EX4 will work in the new MetaTrader 4 terminal. EX4 libraries compiled by the new compiler can be called only from the EX4 programs that have also been compiled in the new version.

In some cases, you may need to edit the path in #include for included files (if relative paths have changed) in the source files. Please note that MetaEditor's root directory is now <data_folder>\MQL4\. All programs should be located in the correct subdirectories.

You can find the data folder (<data_folder>) for each copy of MetaTrader 4 terminal on your computer via the terminal menu or in MetaEditor: File - Open Data Folder.