Discussion of article "MQL5 Wizard: How to Create a Module of Trading Signals" - page 2

 
trolley:

Hi All,

I downloaded the signal from this article and created a MQ5 using the wizard, but the EA does not make any trades. Any ideas?

I had to make the change in the above comments to get the signal to show up in the list, apart from that it compiled OK. Running the EA in the strategy tester does not do anything though :( 

 

EDIT: After inserting print statements in all CSampleSignal class functions, and CExpertSignal class functions, it appears as if the inherited functions are not being overwritten by the CSampleSignal functions-

i.e. in this example, instead of these executing: 

 

The following are executed:

Does that make sense? The functions from the parent class are being executed, when they are being overwritten in the child class ... Any help would be greatly appreciated!!

Hi Trolley,

 

i have the same problem. Have you found any solution or idea on it?

 thanks

 

 

Hi All,

I am wondering how to create a descendant of CExpertSignal with the two patterns "break out" of and "break in" to an observed trading range using the approach proposed here as well as in Exploring Trading Strategy Classes of the Standard Library - Customizing Strategie by Harvester. My perception is that every signal class could (should) be implemented by overloading

//+------------------------------------------------------------------+
//| "Voting" that price will grow.                                   |
//| INPUT:  no.                                                      |
//| OUTPUT: number of "votes" that price will grow.                  |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
int CSignalBreakOutOrIn::LongCondition()
  {
   int result=0;
   int idx   =StartIndex();
//---
   //--- just in case we want some sort of default pattern
   if(IS_PATTERN_USAGE(0)) result=m_pattern_0;                                   // "confirming" signal number 0
   //--- if the model 1 is used, check the condition for pattern 1
   if(IS_PATTERN_USAGE(1) && ConditionForPattern1(idx)) result=m_pattern_1;      // signal number 1
   //--- if the model 2 is used, check the condition for pattern 2
   if(IS_PATTERN_USAGE(2) && ConditionForPattern2(idx)) result=m_pattern_2;      // signal number 2
//--- return the result
   return(result);
  }

and

//+------------------------------------------------------------------+
//| "Voting" that price will fall.                                   |
//| INPUT:  no.                                                      |
//| OUTPUT: number of "votes" that price will fall.                  |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
int CSignalBreakOutOrIn::ShortCondition()
  {
   int result=0;
   int idx   =StartIndex();
//---
   //--- just in case we want some sort of default pattern
   if(IS_PATTERN_USAGE(0)) result=m_pattern_0;                                   // "confirming" signal number 0
   //--- if the model 1 is used, check the condition for pattern 1
   if(IS_PATTERN_USAGE(1) && ConditionForPattern1(idx)) result=m_pattern_1;      // signal number 1
   //--- if the model 2 is used, check the condition for pattern 2
   if(IS_PATTERN_USAGE(2) && ConditionForPattern2(idx)) result=m_pattern_2;      // signal number 2
//--- return the result
   return(result);
  }

Then we find

int CExpertSignal::Direction()
  {
   ...
   int result=LongCondition()-ShortCondition();
   ...
  }

the result of which is tested against signal.m_threshold_open and signal.m_threshold_close in

  1.  bool CExpertSignal::CheckOpenLong(...),
  2.  bool CExpertSignal::CheckOpenShort(...),
  3.  bool CExpertSignal::CheckCloseLong(...),
  4.  bool CExpertSignal::CheckCloseShort(...),
  5.  bool CExpertSignal::CheckReverseLong(...), and
  6.  bool CExpertSignal::CheckReverseShort(...).

The parameters specifying the levels for entering the market and setting stop loss and take profit prices would then be returned by

//+------------------------------------------------------------------+
//| Detecting the levels for buying                                  |
//+------------------------------------------------------------------+
bool CExpertSignal::OpenLongParams(double &price,double &sl,double &tp,datetime &expiration)
  {
  }
//+------------------------------------------------------------------+
//| Detecting the levels for selling                                 |
//+------------------------------------------------------------------+
bool CExpertSignal::OpenShortParams(double &price,double &sl,double &tp,datetime &expiration)
  {
  }

which are invoked by the standard implementation of  bool CExpertSignal::CheckOpenLong(...) and  bool CExpertSignal::CheckOpenShort(...) as defined in the base class. Thus it should suffice to overload 

  1. int CExpertSignal::LongCondition(...),
  2. int CExpertSignal::ShortCondition(...),
  3. bool CExpertSignal::OpenLongParams(...),
  4. bool CExpertSignal::OpenShortParams(...),
  5. bool CExpertSignal::CloseLongParams(...), and
  6. bool CExpertSignal::CloseShortParams(...)

for defining an arbitrary new signal. Note that CExpertTrade contains the code for detecting whether the desired entry price is too far from the current price for placing market orders and uses the entry price choice for automatically deciding whether to place a stop or a limit order.

However, if the trading range is defined to be the region between the highest high (HH) and the lowest low (LL) of the last n bars, then the condition LL < price < HH is always true. Therefore both  int CExpertSignal::LongCondition(...) and  int CExpertSignal::ShortCondition(...)  should always detect the pattern 0 "break out" and whatever value we associate to this pattern the function   int CExpertSignal::Direction() will always return zero!

The natural approach of overloading

  1. bool CExpertSignal::CheckOpenLong(...) and
  2. bool CExpertSignal::CheckOpenShort(...)

such that the former checks

  1. LongCondition()>m_threshold_open and the latter checks
  2. ShortCondition()>m_threshold_open

instead of

  1. m_direction>=m_threshold_open and
  2. -m_direction>=m_threshold_open 

could not be turned into a successful version, yet. As pointed out it would be simple to have bool CExpertSignal::OpenLongParams(...) return the entry price HH and have bool CExpertSignal::OpenShortParams(...) return the entry price LL for completing the signal continuously generating 2 stop orders.

In my eyes it is desirable to have an example showing how to implement this standard break out strategy in terms of the standard library and making it flexible enough by providing the alternative pattern "break in" that results in limit orders at LL and HH. Obviously, such a signal would combine the strategies

  1. buy high and sell higher or sell low and buy lower as well as the alternative
  2. buy low and sell high or sell high and buy low.

by providing them as patterns. I will be extremely grateful for help with finishing this approach.

 
AnonymousTrades:

Hi All,

I am wondering how to create a descendant of CExpertSignal with the two patterns "break out" of and "break in" to an observed trading range using the approach proposed here as well as in Exploring Trading Strategy Classes of the Standard Library - Customizing Strategie by Harvester. My perception is that every signal class could (should) be implemented by overloading the two functions

int CSignalBreakOutOrIn::LongCondition()  { if(IS_PATTERN_USAGE(X) && LongConditionForPatternX(idx)) return(m_pattern_X); }
int CSignalBreakOutOrIn::ShortCondition() { if(IS_PATTERN_USAGE(X) && ShortConditionForPatternX(idx)) return(m_pattern_X); }

Note that CExpertTrade contains the code for detecting whether the desired entry price is too far from the current price for placing market orders and uses the entry price choice for automatically deciding whether to place a stop or a limit order.

[...]

In my eyes it is desirable to have an example showing how to implement this standard break out strategy in terms of the standard library and making it flexible enough by providing the alternative pattern "break in" that results in limit orders at LL and HH. I will be extremely grateful for help with finishing this approach.


I have decided to rephrase my concerns in order to make them as easily understood as possible. In my eyes the two articles

  1. MQL5 Wizard: How to Create a Module of Trading Signals (this one) and
  2. Exploring Trading Strategy Classes of the Standard Library - Customizing Strategies by Harvester Trading

demonstrate in general how to write our own signal classes in the most simple way. I am going to summarise this perception of mine below.

However, still need an idea for finishing the implementation of a signal using this approch to propose buying/selling when the price gets higher/lower than the highest/lowest price observed during the last n periods. This is supposed to result in placing a pair of stop orders above and below the current price. I have already tried to achive this by replacing the condition

  • Direction()>=m_threshold_open  by
  • LongCondition()>=m_threshold_open, for example,

but it still does not seem to work. This does not make any sense to me because I also overloaded the functions OpenLongParams(...) and OpenShortParams(...). They determine the levels at which to place the desired stop orders. Could anybody with more insight into MetaQuotes developers' ideas explain how they would have implemented this most basic break out strategy?

Since the source code is often viewed as the best documentation of any software I spent some time on analyzing the class CExpertSignal in MQL5\Include\Expert\ExpertSignal.mqh

My result was that the functions checking trading conditions essentially reduce to testing the value of the function Direction() { return(LongCondition()-ShortCondition()); } as follows:

bool CExpertSignal::CheckOpenLong(...)     { if(Direction()>=m_threshold_open && OpenLongParams(price,sl,tp,expiration)) return(true); return(false); }
bool CExpertSignal::CheckOpenShort(...)    { if(-Direction()>=m_threshold_open && OpenShortParams(price,sl,tp,expiration)) return(true); return(false); }
bool CExpertSignal::CheckCloseLong(...)    { if(-Direction()>=m_threshold_close && CloseLongParams(price,sl,tp,expiration)) return(true); return(false); }
bool CExpertSignal::CheckCloseShort(...)   { if(Direction()>=m_threshold_close && CloseShortParams(price,sl,tp,expiration)) return(true); return(false); }
bool CExpertSignal::CheckReverseLong(...)  { if(!CheckCloseLong(c_price) || !CheckOpenShort(price,sl,tp,expiration)) return(false); return(true); }
bool CExpertSignal::CheckReverseShort(...) { if(!CheckCloseShort(c_price) || !CheckOpenLong(price,sl,tp,expiration)) return(false); return(true); }

(I have stripped some code which only seems necessary for stable execution without contributing to functionality in any way.)

This summary shows that for any customized strategy class it should be sufficient to overload the functions

  1. int CExpertSignal::LongCondition(...),
  2. int CExpertSignal::ShortCondition(...),
  3. bool CExpertSignal::OpenLongParams(...),
  4. bool CExpertSignal::OpenShortParams(...),
  5. bool CExpertSignal::CloseLongParams(...), and
  6. bool CExpertSignal::CloseShortParams(...)

and Harvester's article 2. linked above explains how to use the macro IS_PATTERN_USAGE(x) in the first two of them such that the resulting signal detects several predefined patterns.

I see this problem: The condition whether the price is between the highest high and the lowest low of the last n bars must always be true. Therefore, both LongCondition(...) and ShortCondition(...) return the same value associated wth the pattern for breakout trading and the value of Direction() is necessarily zero unless the conditions in CheckOpenLong(...) and CheckOpenShort(...) are changed.

But why isn't it sufficient to use LongCondition()>=m_threshold_open and ShortCondition()>=m_threshold_open ?

 
yankai0219:

when  I use the file that you attached to the article,there is something wrong. 

I find the comment about Type should be as follows:

//| Type=SignalAdvanced                                          |

 

Thank you for your message. Your message solved my problem. Cheers!

George

 

Hi,

When I compiled the code, I got three warnings

declaration of 'm_open' hides member samplesignal.mqh 42 23

declaration of 'm_close' hides member samplesignal.mqh 43 23

declaration of 'm_expiration' hides member samplesignal.mqh 52 23


m_open and m_close were defined in ExpertBase.mqh but with different type.

m_expiratin was defined in ExpertSignal.mqh.

Comment out above three lines. Warnings are gone.

George

 
If it is possible to rewrite the exact, complete and executable code of this program and correct its bugs and put it here
 
touhid Qolizadeh #:
If it is possible to rewrite the exact, complete and executable code of this program and correct its bugs and put it here

Here you go!

Cheers, Zarik

Files:
 
ginoit #:

Hi Trolley,

 

i have the same problem. Have you found any solution or idea on it?

 thanks

 

The problem is caused by MetaTrader Wizard itself. Somehow it is not creating the signal object using the SampleSignal class but using the CExpertSignal! Look for the:

   CExpertSignal *signal = new CExpertSignal;

and change it with:

CSampleSignal *signal = new CSampleSignal;


Cheers, Zarik

 
Longsen Chen #:

Hi,

When I compiled the code, I got three warnings

declaration of 'm_open' hides member samplesignal.mqh 42 23

declaration of 'm_close' hides member samplesignal.mqh 43 23

declaration of 'm_expiration' hides member samplesignal.mqh 52 23


m_open and m_close were defined in ExpertBase.mqh but with different type.

m_expiratin was defined in ExpertSignal.mqh.

Comment out above three lines. Warnings are gone.

George


The reason for the warning is because those properties are already defined in the ExpertBase (m_open and m_close) and ExpertSignal (m_expiration). Rename the properties names to something different and the issue will be solved.

Cheers, Zarik

 


Important Note:

In order MetaEditor Wizard to be able to find the signal file (samplesignal.mqh file), The class discriptor should be as following:


// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signal on crossing of the price and the MA                 |
//| entering on the back movement                                    |
//| Type=SignalAdvanced                                              |
//| Name=Sample                                                      |
//| Class=CSampleSignal                                              |
//| Page=                                                            |
//| Parameter=PeriodMA,int,12                                        |
//| Parameter=ShiftMA,int,0                                          |
//| Parameter=MethodMA,ENUM_MA_METHOD,MODE_EMA                       |
//| Parameter=AppliedMA,ENUM_APPLIED_PRICE,PRICE_CLOSE               |
//| Parameter=Limit,double,0.0                                       |
//| Parameter=StopLoss,double,50.0                                   |
//| Parameter=TakeProfit,double,50.0                                 |
//| Parameter=Expiration,int,10                                      |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+

The Type should be SignalAdvanced (which is shown by red color), so change signal to SignalAdvanced in your source code and then MetaEditor Wizard will be able to find the signal file (samplesignal.mqh file).


and finlly metaquotes should edit this article.

Reason: