
MQL5 Wizard: How to Create a Risk and Money Management Module
Introduction
MetaTrader 5 provides a powerful tool that allows you to quickly check various trading ideas. This is generation of Expert Advisors using the MQL5 Wizard on the basis of ready trading strategies.
An Expert Advisor created with the MQL5 Wizard, is based on four pillars - four base classes:
Figure 1. The structure of the CExpert base class
- The CExpert class (or its subclass) is the main "engine" of an Expert Advisor. An instance of CExpert contains one copy of each class: CExpertSignal, CExpertMoney and CExpertTrailing (or their subclasses):
- CExpertSignal is the basis of the trading signals generator. An instance of the CExpertSignal derived class, included in CExpert, provides an Expert Advisor with information about the possibility of entering the market, levels of entry and placing of protective orders, based on built-in algorithms. The Expert Advisor decides whether to enter the market. More details of the CExpertSignal class and work with it are described in the article "MQL5 Wizard: How to create a module of trading signals".
- The CExpertMoney class is the basis of the risk and money management mechanism. An instance of the CExpertMoney derived class, included in CExpert, provides an Expert Advisor with information about possible volumes for opening positions and placing pending orders, based on built-in algorithms. The Expert Advisor makes a decision about the volume.
- The CExpertTrailing class is the basis of the mechanism of open position support. An instance of the CExpertTrailing derived class, included in CExpert, provides an EA with information about the possibility to modify protective orders of the position, based on built-in algorithms. The Expert Advisor makes a decision about the modification of orders. More details of the CExpertTrailing class and work with it will be described in a separate article.
In addition, the members of the CExpert class are instances of the following classes:
- CExpertTrade (for trading)
- CIndicators (for controlling indicators and timeseries involved in the work of the EA).
- CSymbolInfo (for obtaining information about the instrument)
- CAccountInfo (for obtaining information on the state of the trading account)
- CPositionInfo (for obtaining information about positions)
- COrderInfo (for obtaining information about pending orders)
Hereinafter, under "expert" we mean an instance of CExpert or its subclass.
More details of CExpert and work with it will be described in a separate article.
1. Base Class CExpertMoney
As mentioned above, the CExpertMoney class is the basis of the risk and money management mechanism. For communication with the "outside world", the CExpertMoney class has a set of public virtual method:
Initialization | Description |
virtual Init | Initialization of the class instance provides synchronization of the module data with the data of the EA |
Setting the value of the parameter "Percent of risk" | |
virtual ValidationSettings | Validating the set parameters |
virtual InitIndicators | Creating and initializing all indicators and timeseries required for operation of the risk and money management mechanism |
Methods for checking the necessity to open/turn/close a position |
|
virtual CheckOpenLong | Determining the volume to open a long position |
virtual CheckOpenShort | Determining the volume to open a short position |
virtual CheckReverse | Determining the volume for reversing a position |
virtual CheckClose | Determining the necessity to close a position |
Description of Methods
1.1. Initialization methods
The Init() method is called automatically right after a class instance is added to the expert. Method overriding is not required.
virtual bool Init(CSymbolInfo* symbol, ENUM_TIMEFRAMES period, double adjusted_point);
The Percent() method is called for configuring the appropriate parameter. Its value can be from 0.0 to 100.0, inclusive. The default value is 100.0. Method overriding is not required.
void Percent(double percent);
The ValidationSettings() method is called right from the expert after all the parameters are set. You must override the method if there are additional setup parameters.
virtual bool ValidationSettings();
The overridden method must return true, if all options are valid (usable). If at least one of the parameters is incorrect, it must return false (further work is impossible). The overridden method must call the base class method with the check of the result.
The InitIndicators() method implements the creation and initialization of all necessary indicators and timeseries. It is called from the expert after all the parameters are set and their correctness is successful verified. The method should be overridden if the risk and money management mechanism uses at least one indicator or timeseries.
virtual bool InitIndicators(CIndicators* indicators);
Indicators and/or timeseries should be used through the appropriate classes of the Standard Library. Pointers of all indicators and/or timeseries should be added to the collection of indicators of an expert (a pointer to which is passed as a parameter).
The overridden method must return true, if all manipulations with the indicators and/or timeseries were successful (they are suitable for use). If at least one operation with the indicators and/or timeseries failed, the method must return false (further work is impossible).
1.2. Methods for determining the volume of a position
The CheckOpenLong() method calculates the volume for opening a long position. It is called by an expert to determine the volume for opening a long position. The method must be overridden, if you expect to calculate long position opening volume using the algorithm that differs from that implemented in the base class.
\virtual double CheckOpenLong(double price, double sl);
The method must implement the algorithm for calculating the volume for opening a long position. The method must return the calculated volume.
The CheckOpenShort() method calculates the volume for opening a short position. It is called by an expert to determine the volume for opening a short position. The method must be overridden, if you expect to calculate short position opening volume using the algorithm that differs from the one implemented in the base class.
virtual double CheckOpenShort(double price, double sl);
The method must implement the algorithm for calculating the volume for opening a short position. The method must return the calculated volume.
The CheckReverse() method calculates the volume for reversing a position. It is called by an expert to determine the volume of a trade operation for reversing a position. The method must be overridden, if you expect to calculate position reversing volume using the algorithm that differs from that implemented in the base class (e.g. reversal with a double volume).
virtual double CheckReverse(CPositionInfo* position, double sl);
The method must implement the algorithm for calculating the volume to reverse a position, information about which can be obtained by the position pointer. The method must return the calculated volume for the position reversal.
The CheckClose() methods checks whether it is necessary to close a position (in terms of money management and risk management). It is called by an expert to determine whether it is necessary to close a position. The method must be overridden, if you expect to close a position using the algorithm that differs from the one implemented in the base class (e.g. partial closure).
virtual double CheckClose(CPositionInfo* position);
The method must implement the algorithm for defining the necessity to close a position, information about which can be obtained by the position pointer. The method must return the calculated volume for position closing.
2. Creating a Mechanism of Money and Risk Management
Now, after we have reviewed the structure of the CExpertMoney base class, you can start creating your own risk and money management mechanism. Hereinafter, the risk and money management mechanism will be referred to as "money-manager".
As mentioned above, the CExpertMoney class is a set of public virtual "ropes" - methods, using which the expert may know the opinion of the money-manager about the volume of market entering in one direction or another.
Therefore, our primary goal is to create our own class of the money-manager, deriving it from the CExpertMoney class and overriding the appropriate virtual methods, implementing the required algorithms.
Our second problem (which is not less important) - to make our class "visible" to MQL5 Wizard. But, first things first.
2.1. Creating the class of the trading signals generator
Let's begin.
First, we create (for example, using the same MQL5 Wizard) an include file with the mqh extension.
In the File menu select "Create" (or press Ctrl+N key combination) and indicate the creation of an included file:
Figure 2. Create an include file using MQL5 Wizard
It should be noted that in order for the file to be then "detected" by MQL5 Wizard as a money-manager, it should be created in the folder Include\Expert.
In order not to trash in the Standard Library, create our own folder Include\Expert\Money\MyMoneys, in which we create file SampleMoney.mqh, specifying these parameters in the MQL5 Wizard:
Figure 3. Setting the location of the include file
As a result of MQL5 Wizard operation we have the following pattern:
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| defines | //+------------------------------------------------------------------+ // #define MacrosHello "Hello, world!" // #define MacrosYear 2010 //+------------------------------------------------------------------+ //| DLL imports | //+------------------------------------------------------------------+ // #import "user32.dll" // int SendMessageA(int hWnd,int Msg,int wParam,int lParam); // #import "my_expert.dll" // int ExpertRecalculate(int wParam,int lParam); // #import //+------------------------------------------------------------------+ //| EX5 imports | //+------------------------------------------------------------------+ // #import "stdlib.ex5" // string ErrorDescription(int error_code); // #import //+------------------------------------------------------------------+
The following is only "manual" work. Remove the unnecessary parts and add what is required - the include file ExpertMoney.mqh of the Standard Library with an empty class description.
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Expert\ExpertMoney.mqh> //+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { }; //+------------------------------------------------------------------+
Now it is necessary to choose the algorithms.
As the basis for our money-manager we take the following algorithm: In the "normal" conditions it is proposed to use a fixed, predetermined deal volume. But if the previous position was closed with a loss, it is proposed to open a position with a doubled volume.
Reflect this in our file.
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Expert\ExpertMoney.mqh> //+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management | //| doubling the volume after a loss deal. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { }; //+------------------------------------------------------------------+
Define a list of settings for our money-manager. Actually, there will be no list. All settings are included into a single parameter that will determine the volume of a transaction in "normal" conditions.
The parameter will be stored in a protected data member of the class. Access to the parameter will be implemented through an appropriate public method. In the class constructor, the parameter will be initialized by a default value. To check the parameters, let's override the virtual method ValidationSettings according to the description of the base class.
Let's include these changes in our file:
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Expert\ExpertMoney.mqh> //+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management | //| doubling the volume after a loss deal. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { protected: //--- setup parameters double m_lots; // deal volume for "normal" conditions public: CSampleMoney(); //--- methods to set the parameters void Lots(double lots) { m_lots=lots; } }; //+------------------------------------------------------------------+ //| Constructor CSampleMoney. | //| INPUT: no. | //| OUTPUT: no. | //| REMARK: no. | //+------------------------------------------------------------------+ void CSampleMoney::CSampleMoney() { //--- setting the default values m_lots=0.1; } //+------------------------------------------------------------------+
Separately, let's consider how to implement the ValidationSettings() method. The point is that the base class already has one configuration parameter, which also requires verification.
Implementation of the ValidationSettings() method:
//+------------------------------------------------------------------+ //| Validation of the setup parameters. | //| INPUT: no. | //| OUTPUT: true if the settings are correct, otherwise false. | //| REMARK: no. | //+------------------------------------------------------------------+ bool CSampleMoney::ValidationSettings() { //--- Call the base class method if(!CExpertMoney::ValidationSettings()) return(false); //--- Validation of parameters if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax()) { printf(__FUNCTION__+": the deal volume must be in the range %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax()); return(false); } if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10) { printf(__FUNCTION__+": the volume of the deal must be multiple of %f",m_symbol.LotsStep()); return(false); } //--- Successful completion return(true); }
The settings are ready, now let's proceed with the operation of the money manager. We need a method that will determine whether the previous deal was losing and, if necessary, define its volume. Declare it in the class description:
class CSampleMoney : public CExpertMoney { protected: //--- Setup parameters double m_lots; // deal volume for "normal" conditions public: CSampleMoney(); //--- Methods to set parameters void Lots(double lots) { m_lots=lots; } //--- Methods to validate parameters virtual bool ValidationSettings(); protected: double CheckPrevLoss(); };
Implementation of the method:
//+------------------------------------------------------------------+ //| Defines whether the prev. deal was losing. | //| INPUT: no. | //| OUTPUT: volume of the prev. deal if it's losing, otherwise 0.0 | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckPrevLoss() { double lot=0.0; //--- Request the history of deals and orders HistorySelect(0,TimeCurrent()); //--- variables int deals=HistoryDealsTotal(); // Total number of deals in the history CDealInfo deal; //--- Find the previous deal for(int i=deals-1;i>=0;i--) { if(!deal.SelectByIndex(i)) { printf(__FUNCTION__+": Error of deal selection by index"); break; } //--- Check the symbol if(deal.Symbol()!=m_symbol.Name()) continue; //--- Check the profit if(deal.Profit()<0.0) lot=deal.Volume(); break; } //--- Return the volume return(lot); }
Let's consider our algorithms again in more detail (although it is already detailed).
Without going into nuances, we note that our money-manager will propose to increase the volume of a deal upon receipt of loss in the previous deal. If there was no loss in the previous deal, we will offer to open a position with a fixed volume, which is defined by a certain parameter.
For this purpose, we override the virtual methods CheckOpenLong and CheckOpenShort, filling them with corresponding functionality.
Description of the class:
//+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management | //| doubling the volume after a loss deal. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { protected: //--- Setup parameters double m_lots; // Deal volume for "normal" conditions public: CSampleMoney(); //--- Methods to set the parameters void Lots(double lots) { m_lots=lots; } //--- Methods to validate the parameters virtual bool ValidationSettings(); //--- Methods to define the volume virtual double CheckOpenLong(double price,double sl); virtual double CheckOpenShort(double price,double sl); protected: double CheckPrevLoss(); };
Implementations of CheckOpenLong and CheckOpenShort are virtually identical. Both methods determine the necessity of increasing the volume calling the previously implemented CheckPrevLoss method.
Next we need to take into account that we cannot increase the trade volume indefinitely. There are two limitations on the position volume:
- The maximum volume for a deal for the symbol, specified in the server settings (SYMBOL_VOLUME_MAX).
- Availability of the required amount of free funds on the deposit.
Implementation of methods CheckOpenLong and CheckOpenShort:
//+------------------------------------------------------------------+ //| Defining the volume to open a long position. | //| INPUT: no. | //| OUTPUT: lot-if successful, 0.0 otherwise. | //| REMARK: not. | //+------------------------------------------------------------------+ double CSampleMoney::CheckOpenLong(double price,double sl) { if(m_symbol==NULL) return(0.0); //--- Select the lot size double lot=2*CheckPrevLoss(); if(lot==0.0) lot=m_lots; //--- Check the limits double maxvol=m_symbol.LotsMax(); if(lot>maxvol) lot=maxvol; //--- Check the margin requirements if(price==0.0) price=m_symbol.Ask(); maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent); if(lot>maxvol) lot=maxvol; //--- Return the trade volume return(lot); } //+------------------------------------------------------------------+ //| Defining the volume to open a short position. | //| INPUT: no. | //| OUTPUT: lot-if successful, 0.0 otherwise. | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckOpenShort(double price,double sl) { if(m_symbol==NULL) return(0.0); //--- Select the lot size double lot=2*CheckPrevLoss(); if(lot==0.0) lot=m_lots; //--- Check the limits double maxvol=m_symbol.LotsMax(); if(lot>maxvol) lot=maxvol; //--- Check the margin requirements if(price==0.0) price=m_symbol.Bid(); maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent); if(lot>maxvol) lot=maxvol; //--- Return the trade volume return(lot); }
So we've solved the first problem. The above code is a "source code" of the money-manager class that satisfies our main task.
2.2. Creating a description of the generated money-manager class for the MQL5 Wizard
We now turn to solving the second problem. Our money-manager should be "recognized" by the generator of trading strategies of the MQL5 Wizard.
We've done the first necessary condition: we've placed the file where it will be "found" by the MQL5 Wizard. But this is not enough. The MQL5 Wizard must not only "find" the file, but also "recognize" it. To do this we must add to the original text the class descriptor for the MQL5 Wizard.
Let's consider these rules.
1. The block of comments should start with the following lines:
// wizard description start //+------------------------------------------------------------------+ //| Description of the class |
2. The next line is a text descriptor (what we will see in the MQL5 Wizard when choosing the signal) in the format "//| Title=<Text> |". If the text is too big for one line, you can add one more line (but not more) after it.
In our case, we have the following:
//| Title=Trade with a doubling of lot after a loss |
3. Then comes a line with the class type specified in the format "//| Type=<Type> |". The <Type> field must have the Money value (in addition to money-managers, the MQL5 Wizard knows other types of classes).
Write:
//| Type=Money |
4. The following line in the format "//| Name=<Name> |" is the short name of the signal (it is used by the MQL5 Wizard for generating the names of the global variables of the expert).
We get the following:
//| Name=Sample |
5. The name of a class is an important element of the description. In the line with the format "//| Class=<ClassNameа> |", the <ClassName> parameter must match with the name of our class:
//| Class=CSampleMoney |
6. We do not fill in this line, but it must be present (this is a link to the language reference section):
//| Page= |
7. Further, there are descriptions of the signal setup parameters.
This is a set of rows (the number of rows is equal to the number of parameters).
The format of each line is "//| Parameter=<NameOfMethod>,<TypeOfParameter>,<DefaultValue> |".
Here is our set of parameters:
//| Parameter=Lots,double,0.1 | //| Parameter=Percent,double,100.0 |
8. The block of comment should end with the following lines:
//+------------------------------------------------------------------+ // wizard description end
2-7 We need to give further explanations to items 2-7. Sections of the class descriptor contain key words (Title, Type, Name, Class, Page, Parameter). Unfortunately, MQL5 Wizard cannot interpret all the possible combinations of characters as part of the class description.
Therefore, to avoid unnecessary errors, write it like this:<Description> can contain spaces only for the key word Title. Paragraphs 1 and 8 should be copied "as is".
Let's add the descriptor to the source code.
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Expert\ExpertMoney.mqh> #include <Trade\DealInfo.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Trading with lot doubling after a loss | //| Type=Money | //| Name=Sample | //| Class=CSampleMoney | //| Page= | //| Parameter=Lots,double,0.1 | //| Parameter=Percent,double,100.0 | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management | //| doubling the volume after a loss deal. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { protected: //--- Setup parameters double m_lots; // Deal volume for "normal" conditions public: CSampleMoney(); //--- Methods to set the parameters void Lots(double lots) { m_lots=lots; } //--- Methods to validate the parameters virtual bool ValidationSettings(); //--- Methods to define the volume virtual double CheckOpenLong(double price,double sl); virtual double CheckOpenShort(double price,double sl); protected: double CheckPrevLoss(); }; //+------------------------------------------------------------------+ //| Constructor CSampleMoney. | //| INPUT: no. | //| OUTPUT: no. | //| REMARK: no. | //+------------------------------------------------------------------+ void CSampleMoney::CSampleMoney() { //--- Setting default values m_lots=0.1; } //+------------------------------------------------------------------+ //| Validation of the setup parameters. | //| INPUT: no. | //| OUTPUT: true if the settings are correct, otherwise false. | //| REMARK: no. | //+------------------------------------------------------------------+ bool CSampleMoney::ValidationSettings() { //--- Call the base class method if(!CExpertMoney::ValidationSettings()) return(false); //--- Validating the parameters if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax()) { printf(__FUNCTION__+": The deal volume must be in the range %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax()); return(false); } if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10) { printf(__FUNCTION__+": The deal volume must be multiple of %f",m_symbol.LotsStep()); return(false); } //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Defining the volume to open a long position. | //| INPUT: no. | //| OUTPUT: lot-if successful, 0.0 otherwise. | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckOpenLong(double price,double sl) { if(m_symbol==NULL) return(0.0); //--- Select the lot size double lot=2*CheckPrevLoss(); if(lot==0.0) lot=m_lots; //--- Check the limits double maxvol=m_symbol.LotsMax(); if(lot>maxvol) lot=maxvol; //--- Check the margin requirements if(price==0.0) price=m_symbol.Ask(); maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent); if(lot>maxvol) lot=maxvol; //--- Return the trade volume return(lot); } //+------------------------------------------------------------------+ //|Defining the volume to open a short position. | //| INPUT: no. | //| OUTPUT: lot-if successful, 0.0 otherwise. | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckOpenShort(double price,double sl) { if(m_symbol==NULL) return(0.0); //--- Select the lot size double lot=2*CheckPrevLoss(); if(lot==0.0) lot=m_lots; //--- Check the limits double maxvol=m_symbol.LotsMax(); if(lot>maxvol) lot=maxvol; //--- Check the margin requirements if(price==0.0) price=m_symbol.Bid(); maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent); if(lot>maxvol) lot=maxvol; //--- Return the trade volume return(lot); } //+------------------------------------------------------------------+ //| Defines whether the prev. deal was losing. | //| INPUT: no. | //| OUTPUT: Volume of the prev. deal if it's losing, otherwise 0.0 | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckPrevLoss() { double lot=0.0; //--- Request the history of deals and orders HistorySelect(0,TimeCurrent()); //--- variables int deals=HistoryDealsTotal(); // Total number of deals in the history CDealInfo deal; //--- Find the previous deal for(int i=deals-1;i>=0;i--) { if(!deal.SelectByIndex(i)) { printf(__FUNCTION__+": Error of deal selection by index"); break; } //--- Check the symbol if(deal.Symbol()!=m_symbol.Name()) continue; //---Check the profit if(deal.Profit()<0.0) lot=deal.Volume(); break; } //--- Return the volume return(lot); } //+------------------------------------------------------------------+
Well that's all. The money-manager is ready to use.
For the generator of trading strategies of the MQL5 Wizard to be able to use our money-manager, we should restart MetaEditor (MQL5 Wizard scans the folder Include\Expert only at boot).
After restarting MetaEditor, the created money-manager module can be used in the MQL5 Wizard:
Figure 5. The created money-manager in the MQL5 Wizard
The input parameters specified in the section of description of the money-manager parameters are now available:
Figure 6. Input parameters of the created money-manager in the MQL5 Wizard
The best values of the input parameters of the implemented trading strategy can be found using the Strategy Tester of the MetaTrader 5 terminal.
Figure 7 shows the testing results of the Expert Advisor that trades according to this money management system (EURUSD H1, the testing period: 01.01.2010-05.01.2011).
Figure 7. Results of testing on the history of the strategy with the money management module with a doubling after a loss
When creating an Expert Advisor, we used the module of trading signals implemented in the article "MQL5 Wizard: How to create a module of trading signals". The parameters of the Expert Advisor: (PeriodMA=12, ShiftMA=0, MethodMA=MODE_EMA, AppliedMA=PRICE_CLOSE, Limit=-70, StopLoss=145, TakeProfit=430, Expiration=10, Lots=0.1, Percent=100).
Conclusion
The generator of trading strategies of the MQL5 Wizard greatly simplifies the testing of trading ideas. The code of the generated expert is based on the classes of trading strategies of the Standard Library, which are used for creating certain implementations of trading signal classes, money and risk management classes and position support classes.
The article describes how to develop a custom risk and money management module and enable it in the MQL5 Wizard. As an example we've considered a money management algorithm, in which the size of the trade volume is determined by the results of the previous deal. The structure and format of description of the created class for the MQL5 Wizard are also described.
Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/230





- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
For those who are slightly adventurous, here is a martingale. To trade with fixed lots simply set the increase factor to 0.