Discussion of article "Universal Expert Advisor: Integration with Standard MetaTrader Modules of Signals (Part 7)"

To add comments, please log in or register
MetaQuotes Software Corp.
Moderator
200875
MetaQuotes Software Corp.  

New article Universal Expert Advisor: Integration with Standard MetaTrader Modules of Signals (Part 7) has been published:

This part of the article describes the possibilities of the CStrategy engine integration with the signal modules included into the standard library in MetaTrader. The article describes how to work with signals, as well as how to create custom strategies on their basis.

The below diagram shows the general scheme of vertical inheritance of classes used in the process of automatic generation of strategies:

 

Fig. 1. Inheritance of standard classes of the strategy generator

The figure only shows basic and some derived classes. The scheme does not feature all indicators inherited from CIndicators. Separate trailing, money management and signal modules are not included into the scheme. Instead, only the basic relationships are outlined. One of the featured groups is of interest to us: the signal classes CExpertSignal and its child classes. In Figure 1, the group is highlighted by a green dotted line.

Author: Vasiliy Sokolov

Amy Liu
905
Amy Liu  

Thank Vasiliy for your contribution. I learned a lot. I downloaded all the code but it has a compiling error in file Panel.mqh:

'At' - object pointer expected Panel.mqh 210 39

'At' - object pointer expected Panel.mqh 228 37

Can you please check it? 

 

Shephard Mukachi
50
Shephard Mukachi  
Amy Liu:

Thank Vasiliy for your contribution. I learned a lot. I downloaded all the code but it has a compiling error in file Panel.mqh:

'At' - object pointer expected Panel.mqh 210 39

'At' - object pointer expected Panel.mqh 228 37

Can you please check it? 

 


Hi Amy. I have just completed reading through Vasiliy Sokolov articles. If you are still interested in finding out the solution. Please post the error log here. I recall coming across that error and realised that there is an ".\Panel\Panel.mqh" in declarations in StrategiesList file.  Panel.mqh does not exist. Instead, try going to https://www.mql5.com/en/articles/2411 and download the Panel File from there. I believe it has the Panel.mqh file.

This series by Vasiliy's is really good as a framework. I learn't a lot too,but when there are issues with a library, if the author does not offer support, you could be left stuck if you are not a good programmer. Which is the point Alain Verleyen made in your other discussions. But those spending time to share their knowledge and skill here are completely amazing. I am eternally grateful.

Universal Expert Advisor: A Custom Trailing Stop (Part 6)
Universal Expert Advisor: A Custom Trailing Stop (Part 6)
  • 2016.06.16
  • Vasiliy Sokolov
  • www.mql5.com
The sixth part of the article about the universal Expert Advisor describes the use of the trailing stop feature. The article will guide you through how to create a custom trailing stop module using unified rules, as well as how to add it to the trading engine so that it would automatically manage positions.
Rodrigo Haller
11
Rodrigo Haller  

Hi, Vasily.

Thanks for all of your articles.

The Universal Expert Advisor is really impressive in terms of complexity and Software architecture.

For this particular version, I'd like to raise a point in this piece of code here:

CAdapterMACD::CAdapterMACD(void)
{
   m_params.symbol = Symbol();
   m_params.period = Period();
   m_params.every_tick = false;
   m_params.signal_type = SIGNAL_MACD;
   m_params.magic = 1234;
   m_params.point = 1.0;
   m_params.usage_pattern = 2;
   CSignalMACD* macd = m_signal.CreateSignal(m_params);
   macd.PeriodFast(15);
   macd.PeriodSlow(32);
   macd.PeriodSignal(6);
}

Note that after creating the signal, we continued to configure it by setting our own period of the MACD indicator (15, 32, 6). This is easy to do, because the CreateSignal method has returned the corresponding object.

Actually, the MacD parameters (15, 32 and 6) are taking no effect here, since CreateSignal() method initializes the MacD signal before the params are updated.

In this case, I'd suggest to split the CSignalAdapter::CreateSignal() method in two parts, where in the first one, the signal is in fact created and returned just like it is, and the second part would be the signal initialization, after all "Signal Dependant" parameters (in this case, PeriodFast, PeriodSlow and PeriodSignal) are set:

CExpertSignal* CSignalAdapter::CreateSignal(MqlSignalParams& params)
{
   DeleteSignal();
   switch(params.signal_type)
   {
      case SIGNAL_AO:
         m_signal = new CSignalAO();
         break;
      case SIGNAL_AC:
         m_signal = new CSignalAC();
         break;
      case SIGNAL_ADAPTIVE_MA:
         m_signal = new CSignalAMA();
         break;
      case SIGNAL_CCI:
         m_signal = new CSignalCCI();
         break;
      case SIGNAL_DeMARKER:
         m_signal = new CSignalDeM();
         break;
      case SIGNAL_DOUBLE_EMA:
         m_signal = new CSignalDEMA();
         break;
      case SIGNAL_ENVELOPES:
         m_signal = new CSignalEnvelopes();
         break;
      case SIGNAL_FRAMA:
         m_signal = new CSignalFrAMA();
         break;
      case SIGNAL_MA:
         m_signal = new CSignalMA();
         break;
      case SIGNAL_MACD:
         m_signal = new CSignalMACD();
         break;
      case SIGNAL_PARABOLIC_SAR:
         m_signal = new CSignalSAR();
         break;
      case SIGNAL_RSI:
         m_signal = new CSignalRSI();
         break;
      case SIGNAL_RVI:
         m_signal = new CSignalRVI();
         break;
      case SIGNAL_STOCHASTIC:
         m_signal = new CSignalStoch();
         break;
      case SIGNAL_TRIPLE_EA:
         m_signal = new CSignalTriX();
         break;
      case SIGNAL_TRIPLE_EMA:
         m_signal = new CSignalTEMA();
         break;
      case SIGNAL_WILLIAMS_PER_RANGE:
         m_signal = new CSignalWPR();
         break;
   }
   if(CheckPointer(m_signal)!= POINTER_INVALID)
      m_params = params;
   
   return m_signal;
}

bool CSignalAdapter::Init()
{
   if(m_params.symbol == "") /* CreateSignal method should be called first in order to update m_params */
      return false;
   m_info.Name(m_params.symbol);
   if(!m_signal.Init(GetPointer(m_info), m_params.period, m_params.point))
      return false;
   if(!m_signal.InitIndicators(GetPointer(m_indicators)))
      return false;
   m_signal.EveryTick(m_params.every_tick);
   m_signal.Magic(m_params.magic);
   
   m_open.Create(m_params.symbol, m_params.period);
   m_high.Create(m_params.symbol, m_params.period);
   m_low.Create(m_params.symbol, m_params.period);
   m_close.Create(m_params.symbol, m_params.period);
   
   m_times.Create(m_params.symbol, m_params.period);
   m_spread.Create(m_params.symbol, m_params.period);
   m_tik_vol.Create(m_params.symbol, m_params.period);
   m_real_vol.Create(m_params.symbol, m_params.period);
   
   m_signal.SetPriceSeries(GetPointer(m_open), GetPointer(m_high), GetPointer(m_low), GetPointer(m_close));
   //m_signal.SetOtherSeries(GetPointer(m_spread), GetPointer(m_times), GetPointer(m_tik_vol), GetPointer(m_real_vol));
   int mask = 1;
   mask = mask << m_params.usage_pattern;
   m_signal.PatternsUsage(mask);
   return true;
}

And of course, the newly created Init method needs to be called:

CAdapterMACD::CAdapterMACD(void)
{
   m_params.symbol = Symbol();
   m_params.period = Period();
   m_params.every_tick = false;
   m_params.signal_type = SIGNAL_MACD;
   m_params.magic = 1234;
   m_params.point = 1.0;
   m_params.usage_pattern = 2;
   CSignalMACD* macd = m_signal.CreateSignal(m_params);
   macd.PeriodFast(15);
   macd.PeriodSlow(32);
   macd.PeriodSignal(6);
   m_signal.Init(); /* This call is going to create the CSignalMACD object with the custom parameters */
}


Thank you for the great work, and even more for sharing it, Vasily!


Cheers,

Rodrigo Haller

To add comments, please log in or register