MQL5 Wizard: How to Teach an EA to Open Pending Orders at Any Price
Introduction
An Expert Advisor generated using the MQL5 Wizard can only open pending orders at the fixed distance from the current price. This means that if the market situation changes (e.g. a change in market volatility), the Expert Advisor will have to be run again with new parameters.
This would not be suitable for many trading systems. In most cases, the price level for pending orders is determined dynamically by a trading system. And the distance from the current price is constantly changing. In this article, we will discuss how to modify an Expert Advisor generated using the MQL5 Wizard so that it can open pending orders at varying distances from the current price.
1. The Mechanism of Opening Pending Orders in the Expert Advisor Generated Using the MQL5 Wizard
A generated Expert Advisor would have approximately the same code in its header as provided below:
//+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ //--- inputs for expert input string Expert_Title="ExpertMySignalEnvelopes.mq5"; // Document name ulong Expert_MagicNumber =3915; // bool Expert_EveryTick =false; // //--- inputs for main signal input int Signal_ThresholdOpen =10; // Signal threshold value to open [0...100] input int Signal_ThresholdClose =10; // Signal threshold value to close [0...100] input double Signal_PriceLevel =0.0; // Price level to execute a deal input double Signal_StopLevel =85.0; // Stop Loss level (in points) input double Signal_TakeLevel =195.0; // Take Profit level (in points) input int Signal_Expiration =0; // Expiration of pending orders (in bars) input int Signal_Envelopes_PeriodMA =13; // Envelopes(13,0,MODE_SMA,...) Period of averaging input int Signal_Envelopes_Shift =0; // Envelopes(13,0,MODE_SMA,...) Time shift input ENUM_MA_METHOD Signal_Envelopes_Method =MODE_SMA; // Envelopes(13,0,MODE_SMA,...) Method of averaging input ENUM_APPLIED_PRICE Signal_Envelopes_Applied =PRICE_CLOSE; // Envelopes(13,0,MODE_SMA,...) Prices series input double Signal_Envelopes_Deviation=0.2; // Envelopes(13,0,MODE_SMA,...) Deviation input double Signal_Envelopes_Weight =1.0; // Envelopes(13,0,MODE_SMA,...) Weight [0...1.0] //--- inputs for money input double Money_FixLot_Percent =10.0; // Percent input double Money_FixLot_Lots =0.1; // Fixed volume //+------------------------------------------------------------------+
Please note the Signal_PriceLevel parameter. By default, the Expert Advisor is generated with Signal_PriceLevel=0. This parameter defines the distance from the current price. If it is equal to zero, an order will be opened at the current market price. To open a pending order, you should set a non-zero value for the Signal_PriceLevel parameter, i.e. Signal_PriceLevel can be both negative and positive.
The value of Signal_PriceLevel is usually a quite big number. The difference between negative and positive values is shown below:
Signal_PriceLevel=-50:
Fig. 1. Signal_PriceLevel=-50
Signal_PriceLevel=50:
Fig. 2. Signal_PriceLevel=50
Thus, if Signal_PriceLevel=-50, a pending order will be opened at the price that is less favorable than the current price, whereas if Signal_PriceLevel=50, a pending order will be opened at the price that is better than the current price.
This version of the Expert Advisor opens Sell Stop and Buy Stop orders.
2. Where Do We Store Data on the Distance From the Price for Opening a Pending Order?
Let's first take a look at the below figure and then proceed to the comments:
Fig. 3. Storing data on the distance from the current price
Interpretation of the above figure.
Expert Advisor is the Expert Advisor generated using the MQL5 Wizard.
- The ExtExpert object of the CExpert class is declared in the Expert Advisor at the global level.
- Then, in the OnInit() function of the Expert Advisor, we declare a pointer to the signal object of the CExpertSignal class and the signal object is immediately created using the new operator.
- While being in the OnInit() function, we call the InitSignal function of the ExtExpert object and initialize the signal object.
- While being in the OnInit() function, we call the PriceLevel function of the signal object which gets the Signal_PriceLevel parameter.
Thus, the Signal_PriceLevel parameter where the distance from the current price is stored and which was declared in the Expert Advisor is passed to the signal object of the CExpertSignal class.
The CExpertSignal class stores the value of the distance from the current price in the m_price_level variable declared with the protected class scope:
class CExpertSignal : public CExpertBase { protected: //--- variables double m_base_price; // base price for detection of level of entering (and/or exit?) //--- variables for working with additional filters CArrayObj m_filters; // array of additional filters (maximum number of fileter is 64) //--- Adjusted parameters double m_weight; // "weight" of a signal in a combined filter int m_patterns_usage; // bit mask of using of the market models of signals int m_general; // index of the "main" signal (-1 - no) long m_ignore; // bit mask of "ignoring" the additional filter long m_invert; // bit mask of "inverting" the additional filter int m_threshold_open; // threshold value for opening int m_threshold_close;// threshold level for closing double m_price_level; // level of placing a pending orders relatively to the base price double m_stop_level; // level of placing of the "stop loss" order relatively to the open price double m_take_level; // level of placing of the "take profit" order relatively to the open price int m_expiration; // time of expiration of a pending order in bars
3. Structure of the Expert Advisor Generated Using the MQL5 Wizard
The Expert Advisor consists of several blocks with different functionality.
Fig. 4. Structure of the Expert Advisor
Interpretation of the above figure:
- Expert Advisor is the Expert Advisor generated using the MQL5 Wizard.
- CExpert is the base class for implementation of trading strategies.
- CExpertSignal is the base class for creating trading signal generators.
- filter0 ... filtern are trading signal generators, the CExpertSignal class descendants. It should be noted that our trading system is based on the trading signal generator of the Envelopes indicator, but the signals within the generator have been modified. We will talk about those changes in section 7.
4. Expert Advisor Blocks Advisable for Modification
As you could see from the structure of the Expert Advisor generated using the MQL5 Wizard, there are base class blocks. Base classes are part of the Standard Library.
The classes per se are descendants of other base classes and they in turn consist of one or more base classes. Below you can find the first few lines of the code of two classes - CExpert and CExpertSignal:
//+------------------------------------------------------------------+ //| Expert.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "ExpertBase.mqh" #include "ExpertTrade.mqh" #include "ExpertSignal.mqh" #include "ExpertMoney.mqh" #include "ExpertTrailing.mqh" //+------------------------------------------------------------------+ . . . class CExpert : public CExpertBase
and
//+------------------------------------------------------------------+ //| ExpertSignal.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "ExpertBase.mqh" . . . class CExpertSignal : public CExpertBase
I am strongly against any modifications of the base classes:
- When MetaEditor is updated, all changes you make to the base classes are overridden and the base classes are restored to their initial state.
- Inheritance would be more appropriate in this case. But then you will have to modify the ENTIRE Standard Library.
Instead, it would be best to modify the block of the Expert Advisor and trading signal generator modules, especially since our trading system will already have one modified module in use - the trading signal generator of the Envelopes indicator.
So, that's settled: we will make changes to the blocks of the Expert Advisor and the block of the trading signal generator.
5. The Implementation Logic
The pointer will be passed from the Expert Advisor to the trading signal generator.
For this purpose, we need to additionally declare a variable with the protected scope and write a method that stores the pointer from the Expert Advisor in the internal variable:
Fig. 5. The Implementation Logic
6. Trading System
The chart time frame is D1. The indicator to be used is Envelopes with the averaging period of 13 and Exponential averaging method. Types of orders that the Expert Advisor can open are Sell Stop and Buy Stop.
If the previous bar was bullish, we set a Sell Stop order. If the previous bar was bearish, we set a Buy Stop order. In other words, we hope for the pullback:
Fig. 6. Trading System
To generate trading signals as required by the trading system, the standard module of the trading signal generator SignalEnvelopes.mqh has been modified.
Note that here you can use any trading signal generator from the Standard Library.
7. Trading Signal Generator Modification. Getting the Bar Price
So, let's start. I need to say that I prefer saving my programs in MQL5 Storage.
The first thing we should do in order to start modifying the trading signal generator is to create a blank include file, delete everything from it and paste the entire contents of the standard trading signal generator of the Envelopes indicator.
By default the trading signal generator must be located under ...MQL5\Include\Expert\Signal. Not to overload the ...\Signal folder of the Standard Library with too much information, let's create a new folder under the ...\Expert folder and call it \MySignals:
Fig. 7. Creating the MySignals folder
Next, we will create an include file using the MQL5 Wizard.
In MetaEditor, select 'New' under the File menu and then select 'Include file (*.mqh)'.
Fig. 8. MQL5 Wizard. Creating an include file
The name of our signal generator class will be MySignalEnvelopes.
And it will be located under: Include\Expert\MySignals\MySignalEnvelopes. Let's specify it:
Fig. 9. MQL5 Wizard. Location of the include file
After you click 'Finish', the MQL5 Wizard will generate an empty template.
The generated MySignalEnvelopes.mqh file must then be added to MQL5 Storage:
Fig. 10. MQL5 Storage. Adding the file
Once the file has been added, we need to commit the changes to MQL5 Storage:
Fig. 11. MQL5 Storage. Committing the changes
Having completed the above steps, we can proceed to modifying our trading signal generator.
Since the generator is based on the \Include\Expert\Signal\SignalEnvelopes.mqh file, we copy the entire contents of the file and paste it into the generator file, only leaving the original header:
//+------------------------------------------------------------------+ //| MySignalEnvelopes.mqh | //| Copyright © 2013, Vladimir Karputov | //| http://wmua.ru/slesar/ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2013, Vladimir Karputov" #property link "http://wmua.ru/slesar/" #include <Expert\ExpertSignal.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signals of indicator 'Envelopes' | //| Type=SignalAdvanced | //| Name=Envelopes | //| ShortName=Envelopes | //| Class=CSignalEnvelopes | //| Page=signal_envelopes | //| Parameter=PeriodMA,int,45,Period of averaging | //| Parameter=Shift,int,0,Time shift | //| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging | //| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | //| Parameter=Deviation,double,0.15,Deviation | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CSignalEnvelopes. | //| Purpose: Class of generator of trade signals based on | //| the 'Envelopes' indicator. | //| Is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSignalEnvelopes : public CExpertSignal { protected: CiEnvelopes m_env; // object-indicator //--- adjusted parameters int m_ma_period; // the "period of averaging" parameter of the indicator int m_ma_shift; // the "time shift" parameter of the indicator ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator double m_deviation; // the "deviation" parameter of the indicator double m_limit_in; // threshold sensitivity of the 'rollback zone' double m_limit_out; // threshold sensitivity of the 'break through zone' //--- "weights" of market models (0-100) int m_pattern_0; // model 0 "price is near the necessary border of the envelope" int m_pattern_1; // model 1 "price crossed a border of the envelope" public: CSignalEnvelopes(void); ~CSignalEnvelopes(void); //--- methods of setting adjustable parameters void PeriodMA(int value) { m_ma_period=value; } void Shift(int value) { m_ma_shift=value; } void Method(ENUM_MA_METHOD value) { m_ma_method=value; } void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } void Deviation(double value) { m_deviation=value; } void LimitIn(double value) { m_limit_in=value; } void LimitOut(double value) { m_limit_out=value; } //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0=value; } void Pattern_1(int value) { m_pattern_1=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void); protected: //--- method of initialization of the indicator bool InitMA(CIndicators *indicators); //--- methods of getting data double Upper(int ind) { return(m_env.Upper(ind)); } double Lower(int ind) { return(m_env.Lower(ind)); } }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSignalEnvelopes::CSignalEnvelopes(void) : m_ma_period(45), m_ma_shift(0), m_ma_method(MODE_SMA), m_ma_applied(PRICE_CLOSE), m_deviation(0.15), m_limit_in(0.2), m_limit_out(0.2), m_pattern_0(90), m_pattern_1(70) { //--- initialization of protected data m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSignalEnvelopes::~CSignalEnvelopes(void) { } //+------------------------------------------------------------------+ //| Validation settings protected data. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::ValidationSettings(void) { //--- validation settings of additional filters if(!CExpertSignal::ValidationSettings()) return(false); //--- initial data checks if(m_ma_period<=0) { printf(__FUNCTION__+": period MA must be greater than 0"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| Create indicators. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::InitIndicators(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- initialization of indicators and timeseries of additional filters if(!CExpertSignal::InitIndicators(indicators)) return(false); //--- create and initialize MA indicator if(!InitMA(indicators)) return(false); //--- ok return(true); } //+------------------------------------------------------------------+ //| Initialize MA indicators. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::InitMA(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- add object to collection if(!indicators.Add(GetPointer(m_env))) { printf(__FUNCTION__+": error adding object"); return(false); } //--- initialize object if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation)) { printf(__FUNCTION__+": error initializing object"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| "Voting" that price will grow. | //+------------------------------------------------------------------+ int CSignalEnvelopes::LongCondition(void) { int result=0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width) result=m_pattern_1; //--- return the result return(result); } //+------------------------------------------------------------------+ //| "Voting" that price will fall. | //+------------------------------------------------------------------+ int CSignalEnvelopes::ShortCondition(void) { int result =0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width) result=m_pattern_1; //--- return the result return(result); } //+------------------------------------------------------------------+
Now, we will be working on modifications of some parts of the code.
To avoid confusion, the modified code will be highlighted:
//+------------------------------------------------------------------+
//| MySignal.mqh |
//| Copyright © 2013, Vladimir Karputov |
//| http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
The modified code is the code that needs to be copied and pasted into the trading signal generator. I hope that such highlighting will help you better understand the code.
Since we are writing our own class of the trading signal generator, its name should be different from the name of the base class. We therefore replace CSignalEnvelopes with CMySignalEnvelopes throughout the entire code:
Fig. 12. Renaming the class
To ensure that the trading signal generator class is displayed in the MQL5 Wizard under its name, change the class name in the description block
//| Title=Signals of indicator 'Envelopes' |
to
//| Title=Signals of indicator 'MySignalEnvelopes' |
Change the MA period value
//| Parameter=PeriodMA,int,45,Period of averaging |
to 13 (this is only my suggestion, you can set any value you prefer)
//| Parameter=PeriodMA,int,13,Period of averaging |
In addition, we also modify the Deviation parameter
//| Parameter=Deviation,double,0.15,Deviation |
by setting a greater value
//| Parameter=Deviation,double,1.15,Deviation |
According to our implementation logic, we need to declare an internal variable that will store the pointer to the main signal.
Since this must be an internal variable (within the trading signal generator class scope only), it will be added to the following code block:
protected: CiEnvelopes m_env; // object-indicator //--- adjusted parameters int m_ma_period; // the "period of averaging" parameter of the indicator int m_ma_shift; // the "time shift" parameter of the indicator ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator double m_deviation; // the "deviation" parameter of the indicator //--- "weights" of market models (0-100) int m_pattern_0; // model 0 CExpertSignal *m_signal; // storing the pointer to the main signal
Please also note that I deleted the unnecessary variables from the code.
The method for storing the pointer to the main signal will be declared in another code block - the 'method of setting the pointer to the main signal'. Here, I also deleted some irrelevant methods.
public: CMySignalEnvelopes(void); ~CMySignalEnvelopes(void); //--- methods of setting adjustable parameters void PeriodMA(int value) { m_ma_period=value; } void Shift(int value) { m_ma_shift=value; } void Method(ENUM_MA_METHOD value) { m_ma_method=value; } void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } void Deviation(double value) { m_deviation=value; } //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void); //--- method of setting the pointer to the main signal virtual bool InitSignal(CExpertSignal *signal=NULL);
Let's now specify some modified parameters in the constructor and delete the variables that are no longer needed:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CMySignalEnvelopes::CMySignalEnvelopes(void) : m_ma_period(13), m_ma_shift(0), m_ma_method(MODE_SMA), m_ma_applied(PRICE_CLOSE), m_deviation(1.15), m_pattern_0(50)
At this point, we can proceed to modifying the trading signal generation logic according to our trading system.
The code block responsible for a buy signal:
int CMySignalEnvelopes::LongCondition(void) { int result=0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width) result=m_pattern_1; //--- return the result return(result); }
will be as shown below, following the necessary changes:
int CMySignalEnvelopes::LongCondition(void) //---buy
{
int result=0;
int idx =StartIndex();
double open=Open(idx);
double close=Close(idx);
double prlevel;
if(IS_PATTERN_USAGE(0) && close<open)
{
prlevel=GetPriceLevelStopp(open,Open(0));
m_signal.PriceLevel(prlevel);
result=m_pattern_0;
}
//--- return the result
return(result);
}
The code block responsible for a sell signal:
int CMySignalEnvelopes::ShortCondition(void) { int result =0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width) result=m_pattern_1; //--- return the result return(result); }
will be as shown below, following the necessary changes:
int CMySignalEnvelopes::ShortCondition(void) //---sell
{
int result =0;
int idx =StartIndex();
double open=Open(idx);
double close=Close(idx);
double prlevel;
if(IS_PATTERN_USAGE(0) && close>open)
{
prlevel=GetPriceLevelStopp(Open(0),open);
m_signal.PriceLevel(prlevel);
result=m_pattern_0;
}
//--- return the result
return(result);
}
8. A Few Comments on the Signal Code Block
If the required condition for a certain signal is met, we call the GetPriceLevelStopp method that returns a number like "20" or "15" - the value of the distance from the current price.
This is followed by calling the PriceLevel method of the m_signal object (which sets the distance for determining the pending order level price). It should be reminded that m_signal is the CExpertSignal class object that stores the pointer to the main signal.
The code of the GetPriceLevelStopp method is provided below:
double CMySignalEnvelopes::GetPriceLevelStopp(double price_0,double min)
{
double level;
double temp;
temp-=(price_0-min)/PriceLevelUnit();
level=NormalizeDouble(temp,0);
return(level);
}
We need to declare this method in the class header:
protected: //--- method of initialization of the indicator bool InitMA(CIndicators *indicators); //--- methods of getting data double Upper(int ind) { return(m_env.Upper(ind)); } double Lower(int ind) { return(m_env.Lower(ind)); } double GetPriceLevelStopp(double price,double min); };
Another method that we will need is the method of passing the pointer to the main signal to the internal variable:
bool CMySignalEnvelopes::InitSignal(CExpertSignal *signal)
{
m_signal=signal;
return(true);
}
After that we should create an Expert Advisor in the MQL5 Wizard and include in it the signal module 'MySignalEnvelopes'.
We also need to add the InitSignal method call to the code of the Expert Advisor generated using the MQL5 Wizard:
//--- Set filter parameters filter0.PeriodMA(Signal_Envelopes_PeriodMA); filter0.Shift(Signal_Envelopes_Shift); filter0.Method(Signal_Envelopes_Method); filter0.Applied(Signal_Envelopes_Applied); filter0.Deviation(Signal_Envelopes_Deviation); filter0.Weight(Signal_Envelopes_Weight); filter0.InitSignal(signal); //...
For better visualization of the operation of the Expert Advisor, I have provided a short video:
The code of the Expert Advisor generated using the MQL5 Wizard, as well as the code of the signal module, is attached to the article.
Below you can see the testing results of the Expert Advisor. It was tested for EURUSD and USDJPY with the following parameters: testing period 2013.01.01 - 2013.09.01, time frame - D1, Stop Loss level = 85, Take Profit level = 195.
Fig. 13. Testing for EURUSD on D1
Fig. 14. Testing for USDJPY on D1
Conclusion
We have just seen how we can modify the code of the trading signal module for the implementation of the functionality allowing us to set pending orders at any distance from the current price: it may be the Close or Open price of the previous bar or the value of the moving average. There are plenty of options. Important is that you can set any opening price for a pending order.
The article has demonstrated how we can access the pointer to the main signal, and hence the CExpertSignal class methods. I believe that the article will prove useful to traders who trade with pending orders.
Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/723
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi @Vladimir Karputov -- that was a very instructive article, thanks for that!
I personally find this OOP framework in MQL5 quite interesting for building bots by composing objects representing experts, signals, filters, indicators, risk managers, and so on -- very elegant approach in my opinion, as it favours code reuse and extensibility without apparently sacrificing much power... however due to its complexity the learning curve seems fairly steep.
In any case, as I'm transitioning to MQL5 exclusively and have good experience in OOP concepts/languages, I am really keen to adapt it for my own use in prototyping new trading ideas and developing trading systems studying. I have been studying and playing with the library code and was wondering about your recommended best practice approach for the following:
QUESTION: How would you integrate a trend filter for signals received in the expert?
The library includes CExpertBase::m_trend_type property but unfortunately it is not really used anywhere in the examples provided with the platform. I am divided between two design possibilities... Adding a trend filtering object directly in my subclass of CExpert (see code snippet below), which could offer more control on making trading decisions at the level of the expert. Another way to solve it could involve fiddling with the filters of my main signal object and somehow calculate the trend and make a decision inside my subclass of CSignalExpert, e.g. inside CSignalWithTrendFilter::Direction(). Not quite sure yet what are the advantages and disadvantages of one method versus the other, and which one will provide me with more flexibility for requirements of my future projects, i.e. more code reuse without complications and less tweaking of my base classes.
Thanks in advance for you help and recommendations.
I switched to my trading engine a long time ago An attempt at developing an EA constructor - it's more flexible.
OK, I see -- I'm reading the article and will have a look at the attached code... in any case, I'd still appreciate your comment/opinion on the question above if you don't mind. Thanks a lot!
OK, I see -- I'm reading the article and will have a look at the attached code... in any case, I'd still appreciate your comment/opinion on the question above if you don't mind. Thanks a lot!
CExpertSignal is the past. No comments.
CExpertSignal is the past. No comments.
:-)