Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

16
Create Your Own Trading Robot in 6 Steps! MetaQuotes | 22 March, 2012 One More Time about the MQL5 Wizard The world around us is changing rapidly, and we try to keep up with it. We do not have time to learn something new, and this is a normal attitude of a normal human being. Traders are people just like everyone else, they want to get maximum results for the minimum of effort. Specially for traders, MetaEditor 5 offers a wonderful MQL5 Wizard. There are several articles describing how to create an automated trading system using the wizard, including a "light version" MQL5 Wizard for Dummies and a "version from developers " - MQL5 Wizard: New Version. It all seems good - a trading robot is created in 5 mouse clicks, you can test it in the Strategy Tester and optimize the parameters of a trading system, you can let the resulting robot trade on your account without the need to do anything else manually. But the problem arises when the a trader/MQL5 developer wants to create something of his own, something unique which has never been described anywhere, and is going to write his own module of trading signals. The trader opens the MQL5 documentation, gets to the Standard Library, and is horrified to see... Five Terrible Classes True, the MQL5 Wizard greatly simplifies the creation of Expert Advisors, but first you need to learn what will be used as input for it. To automatically create an Expert Advisor using the MQL5 Wizard, make sure that its components adhere to five basic classes of the section Base Classes of Expert Advisors: CExpertBase is a base class for four other classes. CExpert is the class for creating a trading robot; this is the class that trades. CExpertSignal is a class for creating a module of trading signals; the article is about this class . CExpertTrailing is a class for trailing a protecting Stop Loss. CExpertMoney is the money management class. Here is the whole force of the "great and terrible" approach that is called Object-oriented programming (OOP). But don't be afraid, now almost everyone has a cell phone with lots of function, and almost no one knows how it works. We do not need to study all this, we will only discuss some functions of the CExpertSignal class. MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print= 1 of 16 4/15/2012 2:48 AM

Transcript of Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

Page 1: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

Create Your Own Trading Robot in 6 Steps!MetaQuotes | 22 March, 2012

One More Time about the MQL5 WizardThe world around us is changing rapidly, and we try to keep up with it. We do not have time to learn something new, and this is anormal attitude of a normal human being. Traders are people just like everyone else, they want to get maximum results for theminimum of effort. Specially for traders, MetaEditor 5 offers a wonderful MQL5 Wizard. There are several articles describing how tocreate an automated trading system using the wizard, including a "light version" MQL5 Wizard for Dummies and a "version fromdevelopers " - MQL5 Wizard: New Version.

It all seems good - a trading robot is created in 5 mouse clicks, you can test it in the Strategy Tester and optimize the parametersof a trading system, you can let the resulting robot trade on your account without the need to do anything else manually. But theproblem arises when the a trader/MQL5 developer wants to create something of his own, something unique which has never beendescribed anywhere, and is going to write his own module of trading signals. The trader opens the MQL5 documentation, gets tothe Standard Library, and is horrified to see...

Five Terrible Classes

True, the MQL5 Wizard greatly simplifies the creation of Expert Advisors, but first you need to learn what will be used as input forit. To automatically create an Expert Advisor using the MQL5 Wizard, make sure that its components adhere to five basic classesof the section Base Classes of Expert Advisors:

CExpertBase is a base class for four other classes.CExpert is the class for creating a trading robot; this is the class that trades.CExpertSignal is a class for creating a module of trading signals; the article is about this class.CExpertTrailing is a class for trailing a protecting Stop Loss.CExpertMoney is the money management class.

Here is the whole force of the "great and terrible" approach that is called Object-oriented programming (OOP). But don't beafraid, now almost everyone has a cell phone with lots of function, and almost no one knows how it works. We do not need tostudy all this, we will only discuss some functions of the CExpertSignal class.

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

1 of 16 4/15/2012 2:48 AM

Page 2: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

In this article we will go through the stages of creating a module of trading signals, and you will see how to do this without havingto learn OOP or the classes. But if you want, you can go a little further then.

1. Creating a Class from Scratch

We will not alter any existing module of trading signals to our needs, because it's the way to get confused. Therefore, we willsimply write our own class, but first we will use the Navigator to create a new folder to store our signals in MQL5/Include/Expert/.

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

2 of 16 4/15/2012 2:48 AM

Page 3: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

Right-click on the folder we have created, select "New File" and create a new class for our module of trading signals.

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

3 of 16 4/15/2012 2:48 AM

Page 4: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

Fill in the fields:

Class Name - the name of the class. This will be a module for generating signals at the intersection of two movingaverages, so let's name it MA_Cross.Base Name is the class from which our class is derived. And we should derive it from the base class CExpertSignal.

Click "Finish" and a draft of our module us ready. It's all east so far. We only need to add the #include declaration to the resultingfile so that the compiler knows where to find the base class CExpertSignal

#include "..\ExpertSignal.mqh" // CExpertSignal is in the file ExpertSignal

The result:

//+------------------------------------------------------------------+//| MA_Cross.mqh |//| Copyright 2012, MetaQuotes Software Corp. |//| http://www.mql5.com |//+------------------------------------------------------------------+#property copyright "Copyright 2012, MetaQuotes Software Corp."#property link "http://www.mql5.com"#property version "1.00"

#include "..\ExpertSignal.mqh" // CExpertSignal is in the file ExpertSignal//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+class MA_Cross : public CExpertSignal {private:

public: MA_Cross(); ~MA_Cross();

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

4 of 16 4/15/2012 2:48 AM

Page 5: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

};//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+MA_Cross::MA_Cross() { }//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+MA_Cross::~MA_Cross() { }//+------------------------------------------------------------------+

Check the resulting class (it must be free of compilation errors) and click F7. There are no errors and we can move on.

2. A Handle to the Module

Our class is completely empty, it has no errors and we can test it - let's try to create a new Expert Advisor in the MQL5 Wizardbased on it. We reach the step of selecting a module of trading signals and see ... that our module is not there.

And how can it be there? We do not add any indications for the MQL5 Wizard to understand that our class could be somethinguseful. Let's fix this. If you look at the modules of the standard package, you'll see that each of them contains a header at thebeginning of the file. This is the handle of the module compiled according to certain rules. And the rules are very simple.

Open, for example, the source code of the module of AMA based trading signals (see the logic description in Signals of theAdaptive Moving Average.) And run the MQL5 Wizard choosing this module. Compare:

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

5 of 16 4/15/2012 2:48 AM

Page 6: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

The last block in the handle refers to the module parameters, the first line contains the name of the module to be displayed in theMQL5 Wizard. As you can see, there is nothing complicated. Thus, the handle of each module contains the following entries:

Title - the module name to be shown in the MQL5 Wizard.Type - the version of the module of signals. It must always be SignalAdvanced.Name - the name of the module after its is selected in the MQL5 Wizard and is used in comments for describing internalparameters of the generated Expert Advisor (preferably specified).ShortName - a prefix for automatic naming of external parameters in the generated Expert Advisor (in the form ofSignal_<ShortName>_<ParameterName>).Class - the name of the, which is contained in the module.Page - a parameter to get Help for this module (only for modules from the standard delivery).

Next comes the description of the parameters in the form of Parameter=list_of_values, in which the following is specified (comma-separated):

The name of the function to set the value of the parameter when starting the Expert Advisor.1.The parameter type can be enumeration.2.The default value for the parameter, i.e. the value that will be set to the parameter, if you do not change it in the MQL5Wizard.

3.

Description of the parameter, which you see when you start the Expert Advisor generated in the MQL5 Wizard.4.

Now, knowing all this, let's create the handle of our module of trading signals. So, we are writing a module for getting tradingsignals at the intersection of two moving averages. We need to set at least four external parameters:

FastPeriod - the period of the fast moving averageFastMethod - the type of smoothing of the fast moving averageSlowPeriod - the period of the slow moving averageSlowMethod - the type of smoothing of the slow moving average

You could also add a shift and the type of prices to calculate each of the moving averages, but it does not change anythingfundamentally. So the current version is as follows:

// wizard description start//+------------------------------------------------------------------+//| Description of the class |//| Title=Signals at the intersection of two MAs |//| Type=SignalAdvanced |//| Name=My_MA_Cross |//| ShortName=MaCross |//| Class=MA_Cross |//| Page=Not needed |//| Parameter=FastPeriod,int,13,Period of fast MA |//| Parameter=FastMethod,ENUM_MA_METHOD,MODE_SMA,Method of fast MA |//| Parameter=SlowPeriod,int,21,Period of slow MA |//| Parameter=SlowMethod,ENUM_MA_METHOD,MODE_SMA,Method of slow MA |

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

6 of 16 4/15/2012 2:48 AM

Page 7: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

//+------------------------------------------------------------------+// wizard description end

The module handle is ready, and we have described the following in it:

The name displayed in the MQL5 Wizard - "Signals at the intersection of two moving averages".1.Four external parameter to configure the trading signals.2.

FastPeriod - the period of the fast moving average with the default value of 13.FastMethod - the type of smoothing of the fast moving average, simple smoothing by default.SlowPeriod - the period of the slow moving average with the default value of 21.SlowMethod - the type of smoothing of the slow moving average, simple smoothing by default.

Save the changes and compile. There should not be any errors. Run the MQL5 Wizard to check. You see, our module is nowavailable for selection, and it shows all of our parameters!

Congratulations, our module of trading signal looks great now!

3. Methods for Setting Parameters

Now it is time to work with the external parameters. Since our trading module is represented by the class MA_Cross, then itsparameters must be stored within the same class as private members. Let's add four lines (equal to the number of parameters) tothe class declaration. We've already described the parameter in the handle and know the following:

class MA_Cross : public CExpertSignal {private:

//--- Configurable module parametersint m_period_fast; // Period of the fast MAint m_period_slow; // Period of the slow MAENUM_MA_METHOD m_method_fast; // Type of smoothing of the fast MAENUM_MA_METHOD m_method_slow; // Type of smoothing of the slow MA

But how do the values of the external parameters of the module appear in the appropriate members of our class MA_Cross? It'sall very simple, you only need to declare public methods of the same name in the class, namely, to add four lines to the publicsection:

class MA_Cross : public CExpertSignal

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

7 of 16 4/15/2012 2:48 AM

Page 8: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

{private:

//--- Configurable module parametersint m_period_fast; // Period of the fast MAint m_period_slow; // Period of the slow MA

ENUM_MA_METHOD m_method_fast; // Type of smoothing of the fast MA ENUM_MA_METHOD m_method_slow; // Type of smoothing of the slow MA

public://--- Constructor of class

MA_Cross();//--- Destructor of class

~MA_Cross();//--- Methods for settingvoid FastPeriod(int value) { m_period_fast=value; }void FastMethod(ENUM_MA_METHOD value) { m_method_fast=value; }void SlowPeriod(int value) { m_period_slow=value; }void SlowMethod(ENUM_MA_METHOD value) { m_method_slow=value; }

};

When you generate an Expert Advisor on the basis of this module using the MQL5 Wizard and run it on the chart, these fourmethods are automatically called when initializing the Expert Advisor. So here is a simple rule:

The rule of parameter creation in the module - for each parameter that we have declared in the handle, we shouldcreate a private member in the class for storing its value and a public member for setting a value to it. The method name mustmatch the name of the parameter.

And the last moment is to set default values for our parameters that will be used in case the methods of value setting are notcalled. Each declared variable or class member must be initialized. This technique allows to avoid many of hard-to-find errors.

For automatic initialization, the best suiting one is the class constructor; it is always the first one to be called when creating anobject. For default values, we will use those written in the module handle.

class MA_Cross : public CExpertSignal {private:

//--- Configurable module parametersint m_period_fast; // Period of the fast MAENUM_MA_METHOD m_method_fast; // Type of smoothing of the fast MAint m_period_slow; // Period of the slow MAENUM_MA_METHOD m_method_slow; // Type of smoothing of the slow MA

public://--- Constructor of class

MA_Cross(void);//--- Destructor of class

~MA_Cross(void);//+------------------------------------------------------------------+//| Constructor |//+------------------------------------------------------------------+MA_Cross::MA_Cross(void) : m_period_fast(13), // Default period of the fast MA is 3 m_method_fast(MODE_SMA), // Default smoothing method of the fast MA m_period_slow(21), // Default period of the slow MA is 21 m_method_slow(MODE_SMA) // Default smoothing method of the slow MA { }

Here the class members are initialized using the initialization list.

As you can see, we haven't used moving average indicators yet. We found a simple rule - as many parameters are stated inthe handle of the module, so many methods and members should be in the class that implements the module. There isnothing complicated! However, don't forget to set default values of parameters on the constructor.

4. Check the Correctness of Input Parameters

We have created parameters for our trading module, written methods for setting values to them, and now comes the nextimportant phase - the correctness of parameters must be checked. In our case, we must check the periods of moving averagesand the type of smoothing for their calculation. For this purpose you should write your own ValidationSettings() method in theclass. This method is defined in the parent class CExpertBase, and in all its children it is obligatorily redefined.

But if you do not know anything about object-oriented programming, just remember - in our class we should write theValidationSettings() function, which requires no parameters and returns true or false.

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

8 of 16 4/15/2012 2:48 AM

Page 9: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

class MA_Cross : public CExpertSignal {...

//--- Constructor of class MA_Cross(void);

//--- Destructor of class ~MA_Cross(void);

//--- Checking correctness of input databool ValidationSettings();

... };//+------------------------------------------------------------------+//| Checks input parameters and returns true if everything is OK |//+------------------------------------------------------------------+bool MA_Cross:: ValidationSettings() {

//--- Call the base class methodif(!CExpertSignal::ValidationSettings()) return(false);//--- Check periods, number of bars for the calculation of the MA >=1if(m_period_fast<1 || m_period_slow<1)

{PrintFormat("Incorrect value set for one of the periods! FastPeriod=%d, SlowPeriod=%d",

m_period_fast,m_period_slow);return false;

}//--- Slow MA period must be greater that the fast MA period

if(m_period_fast>m_period_slow) {

PrintFormat("SlowPeriod=%d must be greater than FastPeriod=%d!", m_period_slow,m_period_fast);

return false; }//--- Fast MA smoothing type must be one of the four values of the enumeration

if(m_method_fast!=MODE_SMA && m_method_fast!=MODE_EMA && m_method_fast!=MODE_SMMA && m_method_fast!= {

PrintFormat("Invalid type of smoothing of the fast MA!");return false;

}//--- Show MA smoothing type must be one of the four values of the enumeration

if(m_method_slow!=MODE_SMA && m_method_slow!=MODE_EMA && m_method_slow!=MODE_SMMA && m_method_slow!= {

PrintFormat("Invalid type of smoothing of the slow MA!");return false;

}//--- All checks are completed, everything is ok

return true; }

As you can see, in the public part of the MA_Cross class we've added declaration of the ValidationSettings() method, and thenadded the method body in the following form:

bool MA_Cross:: ValidationSettings()

First comes the return type, then the class name, then scope resolution operator ::, and all this is followed by the name of thepreviously declared method. Do not forget that the name and type of parameters must match in the declaration and description ofthe class method. However, the compiler will warn you of such an error.

Note that first the base class method is called, and then input parameters are checked.

//--- Call the base class methodif(!CExpertSignal::ValidationSettings()) return(false);

//--- Our code to check the values of parameters

If you do not add this line, the generated Expert Advisor will not be able to initialize our module of trading signals.

5. Where Are Our Indicators?

It's time to work with the indicators, since all the preparatory work with the parameters for them have been completed. Eachmodule of trading signals contains the InitIndicators() method, which is automatically called when you run the generated ExpertAdvisor. In this method, we must provide indicators of moving averages for our module.

First, declare the InitIndicators() method in the class and paste its draft:

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

9 of 16 4/15/2012 2:48 AM

Page 10: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

public://--- Constructor of class

MA_Cross(void);//--- Destructor of class

~MA_Cross(void);//--- Methods for settingvoid FastPeriod(int value) { m_period_fast=value; }void FastMethod(ENUM_MA_METHOD value) { m_method_fast=value; }void SlowPeriod(int value) { m_period_slow=value; }void SlowMethod(ENUM_MA_METHOD value) { m_method_slow=value; }//--- Checking correctness of input databool ValidationSettings();//--- Creating indicators and timeseries for the module of signalsbool InitIndicators(CIndicators *indicators);

};...//+------------------------------------------------------------------+//| Creates indicators |//| Input: a pointer to a collection of indicators |//| Output: true if successful, otherwise false |//+------------------------------------------------------------------+bool MA_Сross::InitIndicators(CIndicators* indicators) {//--- Standard check of the collection of indicators for NULL

if(indicators==NULL) return(false);//--- Initializing indicators and timeseries in additional filters

if(!CExpertSignal::InitIndicators(indicators)) return(false);//--- Creating our MA indicators

... Some code here//--- Reached this part, so the function was successful, return true

return(true); }

So there is nothing complicated, we declare the method and then simply create the method body, as we have done for theValidationSettings() method. Above all, do not forget to insert the class name and the operator :: in the function definition. Wehave a draft, which we can insert into a code to create moving averages. Let's do this properly - for each indicator we create aseparate function in the class, which returns true if successful. The function can have any name, but let it reflect its purpose, solet's call the functions CreateFastMA() and CreateSlowMA().

protected://--- Creating MA indicatorsbool CreateFastMA(CIndicators *indicators);bool CreateSlowMA(CIndicators *indicators);

};//+------------------------------------------------------------------+//| Creates indicators |//| Input: a pointer to a collection of indicators |//| Output: true if successful, otherwise false |//+------------------------------------------------------------------+bool MA_Cross::InitIndicators(CIndicators *indicators) {//--- Standard check of the collection of indicators for NULL

if(indicators==NULL) return(false);//--- Initializing indicators and timeseries in additional filters

if(!CExpertSignal::InitIndicators(indicators)) return(false);//--- Creating our MA indicators

if(!CreateFastMA(indicators)) return(false);if(!CreateSlowMA(indicators)) return(false);

//--- Reached this part, so the function was successful, return truereturn(true);

}//+------------------------------------------------------------------+//| Creates the "Fast MA" indicator |//+------------------------------------------------------------------+bool MA_Cross::CreateFastMA(CIndicators *indicators) {... Some code//--- Reached this part, so the function was successful, return true

return(true); }//+------------------------------------------------------------------+//| Creates the "Slow MA" indicator |//+------------------------------------------------------------------+bool MA_Cross::CreateSlowMA(CIndicators *indicators) {... Some code

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

10 of 16 4/15/2012 2:48 AM

Page 11: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

//--- Reached this part, so the function was successful, return truereturn(true);

}

That's all, we only need to write code that generates the MA indicators and somehow integrates the handles of these indicatorsinto the trading module, so that the module can use the values of these indicators. That is why a pointer to a variable of typeCIndicators is passed as a parameter. The following is written in Documentation about it:

The CIndicators is a class for collecting instances of timeseries and technical indicators classes. The CIndicators classprovides creation of instanced of technical indicator classes, their storage and management (data synchronization, handleand memory management).

This means that we must create our indicators and place them in this collection. Since only indicators of the CIndicator form andits children can be stored in the collection, we should use this fact. We will use CiCustom, which is the above mentioned child. Foreach moving average we announce an object of type CiCustom in the private part of the class:

class MA_Cross : public CExpertSignal {private: CiCustom m_fast_ma; // The indicator as an object CiCustom m_slow_ma; // The indicator as an object

//--- Configurable module parametersint m_period_fast; // Period of the fast MAENUM_MA_METHOD m_method_fast; // Type of smoothing of the fast MAint m_period_slow; // Period of the slow MAENUM_MA_METHOD m_method_slow; // Type of smoothing of the slow MA

Of course, you can create your own indicator class, which will be derived from CIndicator, and implement all the necessarymethods for use with the MQL5 Wizard. But in this case we want to show how you can use any custom indicator in the moduleof trading signals using CiCustom.

Here's how it looks in the code:

//+------------------------------------------------------------------+//| Creates the "Fast MA" indicator |//+------------------------------------------------------------------+bool MA_Cross::CreateFastMA(CIndicators *indicators) {//--- Checking the pointer

if(indicators==NULL) return(false);//--- Adding an object to the collection

if(!indicators.Add(GetPointer(m_fast_ma))) {

printf(__FUNCTION__+": Error adding an object of the fast MA");return(false);

}//--- Setting parameters of the fast MA

MqlParam parameters[4];//--- parameters[0].type=TYPE_STRING; parameters[0].string_value="Examples\\Custom Moving Average.ex5"; parameters[1].type=TYPE_INT; parameters[1].integer_value=m_period_fast; // Period parameters[2].type=TYPE_INT; parameters[2].integer_value=0; // Shift parameters[3].type=TYPE_INT; parameters[3].integer_value=m_method_fast; // Averaging method//--- Object initialization

if(!m_fast_ma.Create(m_symbol.Name(),m_period,IND_CUSTOM,4,parameters)) {

printf(__FUNCTION__+": Error initializing the object of the fast MA");return(false);

}//--- Number of buffers

if(!m_fast_ma.NumBuffers(1)) return(false);//--- Reached this part, so the function was successful, return true

return(true); }

In the CreateFastMA() method, first check the pointer of the collection of indicators, and then add a pointer of the fast MAm_fast_ma to this collection. Then declare the MqlParam structure, which is especially designed for storing parameters of customindicators, and fill it with values.

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

11 of 16 4/15/2012 2:48 AM

Page 12: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

We use Custom Moving Average from the standard terminal delivery pack as the custom MA indicator. The name of the indicatormust be indicated relative to the folder data_folder/MQL5/Indicators/. Since Custom Moving Average.mq5' from the standardpackage is located in data_folder/MQL5/Indicators/Examples/, we specify its path including the Examples folder:

parameters[0].string_value="Examples\\Custom Moving Average.ex5";

If you look at the code for this indicator, you can see all the required data:

//--- input parametersinput int InpMAPeriod=13; // Periodinput int InpMAShift=0; // Shiftinput ENUM_MA_METHOD InpMAMethod=MODE_SMMA; // Method

The values of the structure contain the type-value pairs:

parameter type - string (to transfer the name of the indicator)1.the name of the executable file of the custom indicator - "Custom Moving Averages.exe"2.parameter type - int (value of the period)3.period of the moving average4.parameter type - int (shift value)5.horizontal shift of the average in bars6.parameter type - int (enumeration value is an integer)7.method of averaging8.

After filling the structure, the indicator is initialized by the Create() method of all the required parameters: symbol name and thetimeframe on which it is calculated, the type of the indicator from the ENUM_INDICATOR enumeration, the number of indicatorparameters and the MqlParam structure with parameter values. And the last one is specifying the number of indicator buffersusing the NumBuffers() method.

The CreateSlowMA() method for creating the slow moving average is simple. When using custom indicators in the module, do notforget that the Expert Advisor generated by the MQL5 Wizard will also run in the tester. So at the beginning of our file we add theproperty #property tester_indicator that communicates to the tester the location of required indicators:

#include "..\ExpertSignal.mqh" // The CExpertSignal class is in the file ExpertSignal#property tester_indicator "Examples\\Custom Moving Average.ex5"

If we use several different indicators, we should add this line for each of them. So, we have added the indicators. For moreconvenience, let's provide two methods of receiving MA values:

//--- Checking correctness of input databool ValidationSettings(void);//--- Creating indicators and timeseries for the module of signalsbool InitIndicators(CIndicators *indicators);//--- Access to indicator datadouble FastMA(const int index) const { return(m_fast_ma.GetData(0,index)); }double SlowMA(const int index) const { return(m_slow_ma.GetData(0,index)); }

As you can see, the methods are very simple, they used the GetData() method of the SIndicator parent class, which returns avalue from the specified indicator buffer at the specified position.

If you need classes for working with classical indicators of the standard package, they are available in section Classes for workingwith indicators. We are ready to proceed to the final stage.

6. Define the LongCondition and ShortCondition Methods

Everything is ready to make our module work and generate trading signals. This functionality is provided by two methods thatmust be described in each child of CExpertSignal:

LongCondition() checks the buy conditions and returns the strength of the Long signal from 0 to 100.ShortCondition() - checks the sell condition and returns the strength of the Short signal from 0 to 100.

If the function returns a null value, it means that there is no trading signal. If there are conditions for the signal, then you canestimate the strength of the signal and return any value not exceeding 100. Evaluation of the signal strength allows you to flexiblybuild trading systems based on several modules and market models. Read more about this in MQL5 Wizard: New Version.

Since we are writing a simple module of trading signals, we can agree that the buy and sell signals are valued equally (100). Let'sadd necessary methods in the class declaration.

...

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

12 of 16 4/15/2012 2:48 AM

Page 13: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

bool InitIndicators(CIndicators *indicators);//--- Access to data of the indicatorsdouble FastMA(const int index) const { return(m_fast_ma.GetData(0,index)); }double SlowMA(const int index) const { return(m_slow_ma.GetData(0,index)); }//--- Checking buy and sell conditionsvirtual int LongCondition();virtual int ShortCondition();

Also, let's create the description of functions. This is how the buy signal is checked (it's all the same with the sell signal):

//+------------------------------------------------------------------+//| Returns the strength of the buy signal |//+------------------------------------------------------------------+int MA_Cross::LongCondition() {

int signal=0;//--- For operation with ticks idx=0, for operation with formed bars idx=1

int idx=StartIndex();//--- Values of MAs at the last formed bar

double last_fast_value=FastMA(idx);double last_slow_value=SlowMA(idx);

//--- Values of MAs at the last but one formed bardouble prev_fast_value=FastMA(idx+1);double prev_slow_value=SlowMA(idx+1);

//---If the fast MA crossed the slow MA from bottom upwards on the last two closed barsif((last_fast_value>last_slow_value) && (prev_fast_value<prev_slow_value))

{ signal=100; // There is a signal to buy }//--- Return the signal value

return(signal); }

Note that we have declare the idx variable, to which the value returned by the StartIndex() function of the parent classCExpertBase is assigned. The StartIndex() function returns 0, if the Expert Advisor is designed to work on all ticks, and in this casethe analysis starts with the current bar. If the Expert Advisor is designed to work at open prices, StartIndex() returns 1 and theanalysis starts with the last formed bar.

By default StartIndex() returns 1, which means that the Expert Advisor generated by the MQL5 Wizard will only run at theopening of a new bar and will ignore incoming ticks during formation of the current bar.

How to activate this mode and how it can be used will be described later in the finishing stroke.

The module is ready for use, so let's create a trading robot in the MQL5 Wizard based on this module.

Checking an Expert Advisor in the Tester

To test the efficiency of our module, let's generate an Expert Advisor based on it in the MQL5 Wizard and run it on the chart. The"Inputs" tab of the appeared start window contains the parameters of the MA_Cross module.

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

13 of 16 4/15/2012 2:48 AM

Page 14: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

All other parameters have also been added by the MQL5 Wizard while generating the EA based on the selected moneymanagement module and position maintenance module (Trailing Stop). Thus, we only had to write a module of trading signalsand received a ready solution. This is the main advantage of using the MQL5 Wizard!

Now let's test the trading robot in the MetaTrader 5 Strategy Tester. Let's try to run a quick optimization of key parameters.

In these settings of input parameters, more than half a million of passes is required for full optimization. Therefore, we choose fastoptimization (genetic algorithm) and additionally utilize MQL5 Cloud Network to accelerate the optimization. The optimization hasbeen done in 10 minutes and we have got the results.

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

14 of 16 4/15/2012 2:48 AM

Page 15: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

As you can see, creating a trading robot in MQL5 and optimization of input parameters have taken much less time than would berequired for writing the position management servicing logic, debugging and searching for the best algorithms.

Finishing Stroke

You can skip this item or go back to it later when you are completely comfortable with the technique of writing a module oftrading signals.

If you open the source code of the Expert Advisor generated by the MQL5 Wizard, you will find the global variableExpert_EveryTick with the false value. Based on this variable, the StartIndex() function returns its value. It communicates to theExpert Advisor the mode it should run in.

//+------------------------------------------------------------------+//| TestMA_Cross.mq5 |//| Copyright 2012, MetaQuotes Software Corp. |//| http://www.mql5.com |//+------------------------------------------------------------------+#property copyright "Copyright 2012, MetaQuotes Software Corp."#property link "http://www.mql5.com"#property version "1.00"//+------------------------------------------------------------------+//| Include |//+------------------------------------------------------------------+#include <Expert\Expert.mqh>//--- available signals#include <Expert\MySignals\MA_Cross.mqh>//--- available trailing#include <Expert\Trailing\TrailingNone.mqh>//--- available money management#include <Expert\Money\MoneyFixedLot.mqh>//+------------------------------------------------------------------+//| Inputs |//+------------------------------------------------------------------+//--- inputs for expertinput string Expert_Title ="TestMA_Cross"; // Document nameulong Expert_MagicNumber =22655; // Expert Advisor IDbool Expert_EveryTick =false; // Work of the EA inside the bar//--- inputs for main signalinput int Signal_ThresholdOpen =10; // Signal threshold value to open [0...100]input int Signal_ThresholdClose =10; // Signal threshold value to close [0...100]

If you set Expert_EveryTick true and compile the code, the trading robot will analyze each incoming tick, and thus make decisionson the values of the current incomplete bar. Do this only if you understand how it works. Not all trading systems are designed towork inside the bar.

You can also add a keyword input for the Expert_EveryTick parameter, and then you will have a new input parameter of theExpert Advisor, which you can set at the EA startup on a chart or in the tester:

input bool Expert_EveryTick =false; // Work of the EA inside the bar

And now it's time to summarize what we have done.

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

15 of 16 4/15/2012 2:48 AM

Page 16: Create Your Own Trading Robot in 6 Steps! - MQL5 Articles

6 Steps to Create a Module of Trading SignalsIf you have mastered MQL5, then you no longer need to write an Expert Advisor from scratch. Just create a module of tradingsignals and, based on this module, automatically generate a trading robot with the enabled trailing and trade volumemanagement modules. And even if you are not familiar with OOP or do not want to delve much into the structure of trade classes,you can just go through 6 steps:

Create a new class using the MQL5 Wizard in a separate folder MQL5/Include/MySignals/. Our module of trading signals willbe stored there.

1.

Create a module handle that describes the parameters, their type and default values.2.Declare module parameters in the class and add methods for initialization in the constructor.3.Check the input parameters and do not forget to call ValidationSettings() of the CExpertSignal base class.4.Create indicator-objects and add a predefined initialization method InitIndicators().5.Identify conditions of trading signals in the methods LongCondition() and ShortCondition().6.

Each step is simple and requires little skill in MQL5 programming. You only need to write your module once, following theinstructions, and further verification of any trade idea will take no more than an hour, without tiring hours of coding anddebugging.

From Simple to Complex

Remember that the trading strategy implemented by your trading robot created using the MQL5 Wizard, is as complex as themodule of trading signals it uses. But before you start to build a complex trading system based on a set of rules for entry and exit,split it into several simple systems and check each one separately.

Based on simple modules you can create complex trading strategies using the ready-made modules of trading signals, but this is atopic for another article!

MQL5 Site / Create Your Own Trading Robot in 6 Steps! - MQL5 Articles http://www.mql5.com/en/articles/367?print=

16 of 16 4/15/2012 2:48 AM