Can I intialize CExpert in OnTimer or OnTick instead of OnInit ?

 

I use CExpert and initialize the constructors in int OnInit():

int OnInit() {

      if(!myExpert.Init(Symbol(),Period(),ExpertEveryTick,ExpertMagicNumber)) {
         //--- failed
         printf(__FUNCTION__+": error initializing expert");
         myExpert.Deinit();
         return(-1);
      }

      CExpertTrade *trade=new CExpertTrade;
      if(trade==NULL) {
         //--- failed
         printf(__FUNCTION__+": error creating trade expert");
         myExpert.Deinit();
         return(-11);
      }
      if(!myExpert.InitTrade(ExpertMagicNumber, trade)) {
         //--- failed
         printf(__FUNCTION__+": error initializing trade expert");
         myExpert.Deinit();
         return(-12);
      }

// I also do InitSignal, InitTrailing, InitMoney

}


I then have a void OnTimer(){} set in which I check for possible call/put options (from the underlying Symbol()). I want to trade the found options, not the Symbol() directly. Therefore, I need to customize CExpertTrade to set the symbol for this option. Unfortunately, CExpert::InitTrade doesn't allow me to customize the symbol directly:


//+------------------------------------------------------------------+
//| Initialization trade object                                      |
//+------------------------------------------------------------------+
bool CExpert::InitTrade(ulong magic,CExpertTrade *trade=NULL)
  {
...
//--- tune trade object
   m_trade.SetSymbol(GetPointer(m_symbol)); // hardcoded
 ...
  }


What's the best approach for this?

1. Approach: Should I create a CExpert within void OnTimer() instead of int OnInit() – is that allowed or possible? Or are there special precautions or restrictions that I need to take into account? 

2. Approach: Should I change CExpert::InitTrade to:

//+------------------------------------------------------------------+
//| Initialization trade object                                      |
//+------------------------------------------------------------------+
bool CExpert::InitTrade(ulong magic,CExpertTrade *trade=NULL, String sybmol) // added symbol as parameter
  {
...
//--- tune trade object
   m_trade.SetSymbol(GetPointer(symbol)); 
 ...
  }

and only intitalize my custom CExpert::initTrade within OnTimer() while leaving the other CExpert initialization in int OnInit()?:

CMyExpertTrade *trade=new CMyExpertTrade;
      if(trade==NULL) {
         //--- failed
         printf(__FUNCTION__+": error creating trade expert");
         myExpert.Deinit();
         return(-11);
      }
      if(!myExpert.InitTrade(ExpertMagicNumber, trade)) {
         //--- failed
         printf(__FUNCTION__+": error initializing trade expert");
         myExpert.Deinit();
         return(-12);
      }

Is that allowed or possible? Or are there special precautions or restrictions that I need to take into account? If I only change CExpertTrade at each void OnTimer(), will CExpert works as usual, except that now the trades are executed with the symbol passed to CMyExpertTrade?

The aim is: All the other things, e.g. signal, trailing, money should be done by using the underlying Symbol(), but only the trades (buying, selling) should be done with the custom Option-Symbol() found in void OnTimer().

I have no way to create the CExpertTrade in int OnInit() because I know the exact option symbol to trade only within void OnTimer() - within int OnInit(), I only know the underlying symbol. Is the "2. Approach" the right approach or is there a more correct solution? 

Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
  • www.mql5.com
To simplify the debugging process and obtain information about operation of a mql5-program, there are special macro constant, values of which are...
 
harryma23:


please edit your post and add your code via the CODE S button looks a bit like </>

if you dont, then moderators might delete your comment.

 

Ok, it seems it can be done easier. The CExpertBase (which is the parent class from CExpert) has a method:

// change working symbol from EURUSD to USDCAD
bool symbolChanged = myExpert.Symbol("USDCAD");

Howerver, calling this will return:

CExpertBase::Symbol: changing of symbol is forbidden

How can I allow CExpert to change the symbol?

 

Ok, I looked into the code and there is no way to change this symbol after CExpert has been fully initialized:

//+------------------------------------------------------------------+
//| Changing work symbol.                                            |
//+------------------------------------------------------------------+
bool CExpertBase::Symbol(string name)
  {
//--- check the initialization phase
   if(m_init_phase!=INIT_PHASE_TUNING)
     {
      Print(__FUNCTION__+": changing of symbol is forbidden");
      return(false);
     }
..
}

As I also intialized myExpert.InitSignal(signal) and myExpert.InitIndicators() within int OnInit(), the intialization state becomes INIT_PHASE_COMPLETE which makes symbol changing afterwards impossible.

 

Yes, you can create the object and initialise it during any event handler or at any time you choose (on the fly), provided you don't try to use its functionality before it is instantiated and properly initialised.

This is normal Object Oriented Programming. There is nothing special about it.

 

> Yes, you can create the object and initialise it during any event handler

So you mean that I can use any of the two approaches? I thought that CExpert can only be initialized within int OnInit() because it also makes use of the lifecyle methods:

OnTick(void);
OnTrade(void);
OnTimer(void);
OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
OnBookEvent(const string &symbol);

For example, in my Expert class I have:

void OnTick() {
    myExpert.OnTick(); // calls CExpert::OnTick
}

Reinitializing myExpert with each void OnTimer() means:

// global variable
CExpert myExpert;

void OnTimer() {
   // ok?
   myExpert.Deinit();
 
/--- Initializing expert
   if(!myExpert.Init(Symbol(),Period(),ExpertEveryTick,ExpertMagicNumber)) {
      //--- failed
      printf(__FUNCTION__+": error initializing expert");
      myExpert.Deinit();
      return(-1);
   }
//--- Creation of signal object
   CSignalMACD *signal=new CSignalMACD;
   if(signal==NULL) {
      //--- failed
      printf(__FUNCTION__+": error creating signal expert");
      myExpert.Deinit();
      return(-2);
   }
//--- Add signal to expert (will be deleted automatically))
   if(!myExpert.InitSignal(signal)) {
      //--- failed
      printf(__FUNCTION__+": error initializing signal expert");
      myExpert.Deinit();
      return(-3);
   }

...
}

I'm not sure if this is really a clean and performant solution. I'd have to recreate the entire objects of CExpert-classes and disrupt the lifecycle methods and maybe more with unforeseeable risks on each void onTimer() just because I want to change the symbol.

It seems that simply re-initializing CTrade within void OnTimer() is the most performant and clean solution (see above "2. Approach"). What do you think?

 

Did I not write ... "provided you don't try to use its functionality before it is instantiated and properly initialised"?

The "life cycle" methods as you call them, are "virtual" and they not called automatically by the event handlers. They have to be called by "you" (the program), as you have demonstrated in your sample code.

Obviously calling "myExpert.OnTick()" before the "myExpert" object is properly instantiated and initialised goes against what I just stated. So, only call that method once you have verified that the object is valid and properly initialised.

Question: Do you have experience with general Object Oriented Programming and how it works, or is this perhaps something new to you which you are in the process of learning?

Perhaps the issue here is the classical X/Y problem, where you are trying to solve the base problem "X" (which you have not described), but having issues with your attempt at solving it with "Y" (which you believe to be the solution).

So, explain your reasoning behind why you have a need to initialise the CExpert object in another event handler?

 

>So, explain your reasoning behind why you have a need to initialise the CExpert object in another event handler?

The aim is: 

I know the exact call/put option symbol to trade only within void OnTimer() - within int OnInit(), I only know the underlying symbol (that is the symbol initialized in int OnInit()). The underlying symbol does and will not change. However, in option trading, you do not trade the underlying symbol. Therefore, I need to pass another symbol-reference to CTrade or CExpert instance so that it can trade the option and not the underlying. 

As the current default implementation of CExpert does not allow me to change the traded symbol afterwards, I must workaround this issue and re-create CExpert on each call within void OnTimer(). I'd have to recreate the entire objects of CExpert-classes (with all its indicators, signals, etc.) only because I want to change the trading symbol for option based on Symbol() - is that really the only solution?


>The "life cycle" methods as you call them, are "virtual" and they not called automatically by the event handlers. They have to be called by "you" (the program), as you have demonstrated in your sample code.


I do not need to call the default implementation CExpert::OnTick():

void OnTick() {
    myExpert.OnTick(); // calls CExpert::OnTick
}

I specifically mentioned it here because I thought the default implementation of CExpert::OnTick would be called automatically by CExpert behind the scene:

   bool              m_on_tick_process;          // OnTick will be processed       (default true)
   bool              m_on_trade_process;         // OnTrade will be processed      (default false)
   bool              m_on_timer_process;         // OnTimer will be processed      (default false)
   bool              m_on_chart_event_process;   // OnChartEvent will be processed (default false)
   bool              m_on_book_event_process;    // OnBookEvent will be processed  (default false)

If you think that this is a X/Y problem, then please provide me the correct solution to this issue. Thanks for helping!

 
harryma23 #:

>So, explain your reasoning behind why you have a need to initialise the CExpert object in another event handler?

The aim is: 

I know the exact call/put option symbol to trade only within void OnTimer() - within int OnInit(), I only know the underlying symbol (that is the symbol initialized in int OnInit()). The underlying symbol does and will not change. However, in option trading, you do not trade the underlying symbol. Therefore, I need to pass another symbol-reference to CTrade or CExpert instance so that it can trade the option and not the underlying. 

As the current default implementation of CExpert does not allow me to change the traded symbol afterwards, I must workaround this issue and re-create CExpert on each call within void OnTimer(). I'd have to recreate the entire objects of CExpert-classes (with all its indicators, signals, etc.) only because I want to change the trading symbol for option based on Symbol() - is that really the only solution? Btw, I do not need to call the default implementation CExpert::OnTick():

If you think that this is a X/Y problem, then please provide me the correct solution to this issue. Thanks for helping!

It is most definitely an X/Y problem.

The current CExpertBase class already has some functionality for working with a different symbol or period (but it's not too well documented) ...

class CExpertBase : public CObject {
protected:
   //--- variables
   ulong             m_magic;          // expert magic number
   ENUM_INIT_PHASE   m_init_phase;     // the phase (stage) of initialization of object
   bool              m_other_symbol;   // flag of a custom work symbols (different from one of the Expert Advisor)
   CSymbolInfo      *m_symbol;         // pointer to the object-symbol
   bool              m_other_period;   // flag of a custom timeframe (different from one of the Expert Advisor)
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
void CExpertBase::CExpertBase(void) : m_magic(0),
                                      m_margin_mode(ACCOUNT_MARGIN_MODE_RETAIL_NETTING),
                                      m_init_phase(INIT_PHASE_FIRST),
                                      m_other_symbol(false),
                                      m_symbol(NULL),
                                      m_other_period(false),
                                      m_period(PERIOD_CURRENT),

It also has methods for setting the symbol and period ...

Public Methods:

Parameters

 

Symbol

Sets the symbol

Period

Sets the timeframe

So study the code for this built-in functionality, and see if it meets your "X" problem needs, without resorting to the "Y" problem.

If however, it is not what you need, then to fix problem X (and not Y), create your own derived CExpert class and modify it with the extra functionality of having two symbol references—one for specifications and quote data, and another for the trading functionality.

In fact, what you want is something similar to what is needed to work with Custom Symbols (e.g. Renko), where one uses the Custom Symbol for data, but trades on the underlying source symbol instead. So, by creating a derived class you will also be able to use for those situations too.

 

>So study the code for this built-in functionality, and see if it meets your "X" problem needs, without resorting to the "Y" problem.

This is what I did at the beginning:) To find a clean solution without the need for a workaround..

As already mentioned here: https://www.mql5.com/en/forum/494171#comment_57905341, the methods for setting the symbol and period cannot be used with the default implementation of CExpert. Am I right?

However, the CExoert class (which extends CExpertBase) has the following default constructor:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CExpert::CExpert(void) : m_period_flags(0),
                         m_expiration(0),
                         m_pos_tot(0),
                         m_deal_tot(0),
                         m_ord_tot(0),
                         m_hist_ord_tot(0),
                         m_beg_date(0),
                         m_trade(NULL),
                         m_signal(NULL),
                         m_money(NULL),
                         m_trailing(NULL),
                         m_check_volume(false),
                         m_on_tick_process(true),
                         m_on_trade_process(false),
                         m_on_timer_process(false),
                         m_on_chart_event_process(false),
                         m_on_book_event_process(false),
                         m_max_orders(1)
  {
   m_other_symbol      =true; // it's only a flag. How can I set the other symbol?
   m_other_period      =true; // it's only a flat. How can I set the other period?
   m_adjusted_point    =10;
   m_period            =WRONG_VALUE;
   m_last_tick_time.min=-1;
  }

But I do not understand how can I set the other_symbol and other_period within CExpert? Do you know how?


> In fact, what you want is something similar to what is needed to work with Custom Symbols (e.g. Renko), where one uses the Custom Symbol for data, but trades on the underlying source symbol instead. So, by creating a derived class you will also be able to use for those situations too.

Yes! This is what I want to achieve: 

- the underlying source symbol (= Symbol()) for data (i.e. CSignal and its indicators); this symbol can be fixed when initializing CExpert.

- the custom symbol (= m_other_symbol ???) with custom period (= m_other_period ???) for trades (i.e. CExpertTrade); this symbol can be changed within void onTimer().

Can I set the custom symbol by using m_other_symbol and m_other_period) without extending from CExpertBase?

I don't understand why CExpert has m_other_symbol = true without the ability to set the other symbol. Or did I miss something?

Can I intialize CExpert in OnTimer or OnTick instead of OnInit ?
Can I intialize CExpert in OnTimer or OnTick instead of OnInit ?
  • 2025.08.28
  • www.mql5.com
I use CExpert and initialize the constructors in int OnInit() : I then have a void OnTimer(){} set in which I check for possible call/put options...
 
harryma23 #:

>So study the code for this built-in functionality, and see if it meets your "X" problem needs, without resorting to the "Y" problem.

This is what I did at the beginning:) To find a clean solution without the need for a workaround..

As already mentioned here: https://www.mql5.com/en/forum/494171#comment_57905341, the methods for setting the symbol and period cannot be used with the default implementation of CExpert. Am I right?

However, the CExoert class (which extends CExpertBase) has the following default constructor:


But I do not understand how can I set the other_symbol and other_period within CExpert? Do you know how?


> In fact, what you want is something similar to what is needed to work with Custom Symbols (e.g. Renko), where one uses the Custom Symbol for data, but trades on the underlying source symbol instead. So, by creating a derived class you will also be able to use for those situations too.

Yes! This is what I want to achieve: 

- the underlying source symbol (= Symbol()) for data (i.e. CSignal and its indicators); this symbol can be fixed when initializing CExpert.

- the custom symbol (= m_other_symbol ???) with custom period (= m_other_period ???) for trades (i.e. CExpertTrade); this symbol can be changed within void onTimer().

Can I set the custom symbol by using m_other_symbol and m_other_period) without extending from CExpertBase?

I don't understand why CExpert has m_other_symbol = true without the ability to set the other symbol. Or did I miss something?


I don't work the Standard Library because it is very buggy in my opinion, so my experience with it is limited.

However, let me play around with it for a while to see if I can come up with a X solution for you, and I will get back to you later today.