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

 
Karputov Vladimir:
Or a money management module. Which one to choose, you need to look at it in more detail.

The concept is not very clear. There are signals for opening positions, but there are also signals for closing them. It would be possible to use voting and so on, and all this in addition to trailing.

And how often do the base classes change? If I wrote my signals module with the previous version of the wizard, I would have to redesign it now.

Just wondering, does anyone seriously use this wizard and Expert Advisors base classes or is it only for lazy people who don't want to do anything by hand?

 
Karputov Vladimir:
Or a money management module. What exactly to choose, you need to look at it in more detail.

I'm sorry, I'm not good at OOP, can you help me understand it?

Here I have made a module of trading signals called СMySignal.mqh. Now I want to implement my own closing signals. For this I create my own capital management module CMyMoney.mqh because CExpert has such a call:

protected:
  CExpertMoney     *m_money;

bool CExpert::CheckClose(void)

  {
   double lot;
//--- position must be selected before call
   if((lot=m_money.CheckClose(GetPointer(m_position)))!=0.0)
      return(CloseAll(lot));

But I want to use the methods of the CMySignal class in the closing logic, I don't want to do all the calculations in CMyMoney again. So in CMyMoney I write something like this:

class CMyMoney : public CExpertMoney

protected:

   //--- input parameters
   virtual bool      CheckCloseLong(void);
   virtual bool      CheckCloseShort(void);

   CMySignal         *filter0;

...

double CMyMoney::CheckClose(CPositionInfo *position)
  {
   double lot;
   lot=position.Volume();
   if(position.PositionType()==POSITION_TYPE_BUY)
     {
      //--- check the possibility of closing the long position
      if(filter0.CheckCloseLong(lot))
         Print(__FUNCTION__+": close long position signal detected. Lot to be closed ",lot); 
     }
   else
     {
      //--- check the possibility of closing the short position
      if(filter0.CheckCloseShort(lot))
         Print(__FUNCTION__+": close short position signal detected. Lot to be closed ",lot);
     }
   return(lot);
  }


And move all the closing logic to the CMySignal class:

class CMySignal : public CExpertSignal

public:

   virtual bool      CheckCloseLong(double &lot);
   virtual bool      CheckCloseShort(double &lot);

bool CMySignal::CheckCloseLong(double &lot)

  {

   //логика закрытия Long

  }

bool CMySignal::CheckCloseShort(double &lot)

  {

   //логика закрытия Short

  }

But it turns out that I'm already dealing with a new filter0 object, not with an already created one. I have to reinitialise the data for it (indicators and so on). How do I get access to the already existing object of CMySignal class? I hope I've made myself clear =)

All this should work through the Wizard in a standard way, so I don't change any base classes. All changes are only possible in my trading signals and money management modules.

 
t101:

I'm sorry, I'm not good at OOP, can you help me understand it?

I have made a module of trading signals called СMySignal.mqh. Now I want to implement my own closing signals. For this I create my own capital management module CMyMoney.mqh because CExpert has such a call:

protected:
  CExpertMoney     *m_money;

bool CExpert::CheckClose(void)

  {
   double lot;
//--- position must be selected before call
   if((lot=m_money.CheckClose(GetPointer(m_position)))!=0.0)
      return(CloseAll(lot));

But I want to use the methods of the CMySignal class in the closing logic, I don't want to do all the calculations in CMyMoney again. So in CMyMoney I write something like this:

class CMyMoney : public CExpertMoney

protected:

   //--- input parameters
   virtual bool      CheckCloseLong(void);
   virtual bool      CheckCloseShort(void);

   CMySignal         *filter0;

...

double CMyMoney::CheckClose(CPositionInfo *position)
  {
   double lot;
   lot=position.Volume();
   if(position.PositionType()==POSITION_TYPE_BUY)
     {
      //--- check the possibility of closing the long position
      if(filter0.CheckCloseLong(lot))
         Print(__FUNCTION__+": close long position signal detected. Lot to be closed ",lot); 
     }
   else
     {
      //--- check the possibility of closing the short position
      if(filter0.CheckCloseShort(lot))
         Print(__FUNCTION__+": close short position signal detected. Lot to be closed ",lot);
     }
   return(lot);
  }


And move all the closing logic to the CMySignal class:

class CMySignal : public CExpertSignal

public:

   virtual bool      CheckCloseLong(double &lot);
   virtual bool      CheckCloseShort(double &lot);

bool CMySignal::CheckCloseLong(double &lot)

  {

   //логика закрытия Long

  }

bool CMySignal::CheckCloseShort(double &lot)

  {

   //логика закрытия Short

  }

But it turns out that I'm already dealing with a new filter0 object, not with an already created one. I have to reinitialise the data for it (indicators and so on). How do I get access to the already existing object of CMySignal class? I hope I've made myself clear =)

All this should work through the Wizard in a standard way, so I don't change any base classes. All changes are only possible in my trading signals and money management modules.

I have a question on the second "sheet" - why do you insert"CMySignal *filter0;" into the money management module?
 
Karputov Vladimir:
I have a question about the second "sheet" - why do you insert"CMySignal *filter0;" into the money management module?

filter0 is a class object of my trading signals module CMySignal. It is created in the Expert Advisor's main file:

CMySignal *filter0=new CMySignal;

I am trying to get access to it from the money management module to transfer all closing calculations to my signals module. I don't see any other ways to implement my own closing logic.
 
t101:

filter0 is a class object of my trading signals module CMySignal. It is created in the main EA file:

CMySignal *filter0=new CMySignal;

I am trying to access it from the money management module to transfer all closing calculations to my signals module. I don't see any other ways to implement my own closing logic.

Look at the implementation of transferring the pointer to the main signal to the signal module(MQL5 Wizard: How to teach an Expert Advisor to open pending orders at any price):

According to our scheme of the idea implementation, it is necessary to declare an internal variable where the pointer to the main signal will be stored.

Since this variable must be internal (with scope only inside the class of the trading signal generator), we will add it to the next 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;         // store reference to the main signal

Also note that I have removed the variables that will not be used in the code.

We will declare the method that will be used to store the pointer to the main signal in another code block - "method of setting the pointer to the main signal". Some unnecessary methods have also been removed.

Perhaps this is what you need. Only the pointer to the main signal will be passed to the capital management module.

 
Karputov Vladimir:

Look at the implementation of passing the pointer to the main signal to the signal module(MQL5 Wizard: How to teach the Expert Advisor to open pending orders at any price):

Perhaps this is what you need. Only the pointer to the main signal will be passed to the money management module.

Why do I need a pointer to the main signal if I need a pointer to my signal, an inheritor of the CExpertSignal class? I want it in my money management module, a descendant of CExpertMoney.
 
t101:
Why do I need a pointer to the head signal if I want a pointer to my signal, a descendant of the CExpertSignal class? I want it in my money management module, an inheritor of CExpertMoney.

Okay. Let's go to the other side. In your money management module, you need to declare a variable like this:

CMySignal    *m_signal;         // store a reference to your signal

and a method like this:

   //--- method of setting the pointer to the main signal
   virtual bool      InitSignal(СMySignal *filter=NULL);

and its implementation

//+------------------------------------------------------------------+
//| Initialisation signal object|
//+------------------------------------------------------------------+
bool CMyMoney::InitSignal(СMySignal *filter)
  {
   m_signal=filter;
   return(true);
  }

Now you can try to access your signal from the money management module via

m_signal.метод вашего модуля сигналов
 
Karputov Vladimir:

All right. Let's go to the other side. In your money management module, you need to declare a variable like this:

and this method:

and its implementation

Now I can try to access my signal from the money management module via

Invalid pointer access when calling a method of my signal module
m_signal.метод вашего модуля сигналов
InitSignal must be called somewhere beforehand?
 
t101:
Invalid pointer access when calling a method of my signals module
InitSignal must be called somewhere beforehand?
Of course "InitSignal" should be called before: from OnInit() of the EA, at the end of the initialisation block of the money management module.
 
Karputov Vladimir:
Of course we need to call "InitSignal" earlier: from OnInit() of the EA, at the end of the initialisation block of the money management module.
Should I manually add it to OnInit()? So I can't do what I want through the Wizard?