Discussing the article: "Developing a multi-currency Expert Advisor (Part 1): Collaboration of several trading strategies" - page 2

 
fxsaber #:

It won't hurt, 100%. It's just an unnecessary entity. OOP architecturally follows the principle from the general to the particular. You have made the general (base class) "private". Although all that is called there is CStrategy::Tick().

Here I followed this approach. Suppose we can create a linear hierarchy Base class -> Inheritor1 -> Inheritor2 -> Inheritor3. The inheritor classes progressively complicate their parent class, but there is no branching of the inheritance tree anywhere, i.e. all classes have only one successive inheritor. Then if we are going to create real objects of only a few classes that will be the successors of Inheritor3, and all the code of the parent classes is compact enough, we will make a base class at once, including the content of the first three successors.

In this article, the base class really, by and large, only contains CStrategy::Tick(). But further on it is planned to add more general code for all strategies.

 
fxsaber #:

It seems to be a compiler error that it doesn't swear at this method signature when called like this.

Here, as I understand, it is due to the fact that pointers in MQL5 are not the same as pointers in C++. That's why this variant is suitable.

 
fxsaber CObject.

You don't use it.


I noticed that it is quite common practice to inherit from CObject.

I don't quite get the idea, what exactly is not used, although it could be?

Inheritance from CObject is only done for the sake of later use of Save() and Load()

 
Yuriy Bykov #:

Not quite getting the idea, what exactly is not being used, although it could be?

I will give the code in full.

class CObject
  {
private:
   CObject          *m_prev;               // previous item of list
   CObject          *m_next;               // next item of list

public:
                     CObject(void): m_prev(NULL),m_next(NULL)            {                 }
                    ~CObject(void)                                       {                 }
   //--- methods to access protected data
   CObject          *Prev(void)                                    const { return(m_prev); }
   void              Prev(CObject *node)                                 { m_prev=node;    }
   CObject          *Next(void)                                    const { return(m_next); }
   void              Next(CObject *node)                                 { m_next=node;    }
   //--- methods for working with files
   virtual bool      Save(const int file_handle)                         { return(true);   }
   virtual bool      Load(const int file_handle)                         { return(true);   }
   //--- method of identifying the object
   virtual int       Type(void)                                    const { return(0);      }
   //--- method of comparing the objects
   virtual int       Compare(const CObject *node,const int mode=0) const { return(0);      }
  };

Briefly speaking, this class is intended for forming and working with lists, including possible sorting.

Inheritance from CObject is done only for the sake of using Save() and Load() later on

From a cannon at sparrows. Why not add these two virtual methods to CStrategy?

 
fxsaber #:

From a cannon on sparrows. Why not add these two virtual methods to CStrategy?

Yes, I agree. I will add save methods to CStrategy and the rest of the base classes instead of inheriting from CObject

 
Yuriy Bykov #:

You make OOP conversion from classic (input + without OOP) SimpleVolumes.mq5 into SimpleVolumesStartegy.mqh.

Why didn't you make SimpleVolumes.mq5 via #include SimpleVolumesStartegy.mqh ?

 
fxsaber #:

you can clearly see the cumbersomeness with inputs due to OOP. It would be good to remove it.

Camouflaged.

int OnInit() {
   expert.AddStrategy(new CSimpleVolumeStrategy(
                         magic_ + 1, "EURGBP", PERIOD_H1,
                         NormalizeDouble(0.34 * depoPart_, 2),
                         130, 0.9, 1.4, 231, 3750, 50, 600, 3)
                     );
   expert.AddStrategy(new CSimpleVolumeStrategy(
                         magic_ + 2, "EURGBP", PERIOD_H1,
                         NormalizeDouble(0.10 * depoPart_, 2),
                         159, 1.7, 0.8, 248, 3600, 495, 39000, 3)
                     );

   int res = expert.Init();   // Инициализация всех стратегий эксперта

   return(res);
}

Since they started to show the work of the TC portfolio, it would be good to deal with the portfolio loading (inputs) properly.

 
fxsaber #:

You make an OOP conversion from the classic (input + no OOP) SimpleVolumes.mq5 to SimpleVolumesStartegy.mqh.

Why didn't you make SimpleVolumes.mq5 via #include SimpleVolumesStartegy.mqh ?

Because I wanted to demonstrate the process of transition from a regular EA (input + without OOP), which is written without the aim of using it in parallel mode with different settings (this is the SimpleVolumes.mq5 role) to another EA, in which this parallel use can be done (this is the SimpleVolumesExpert.mq5 role). For this purpose we needed OOP-transformation in SimpleVolumesStartegy.mqh.

 
fxsaber #:

Since they started to show the work of the TC portfolio, it would be good to deal with the portfolio loading (inputs) competently.

We will definitely deal with it in the next parts. There is still a lot of things to deal with, so it was not possible to present everything at once.

I'm very grateful for all your comments, because now is the right time for them - for articles I'm redoing almost from scratch my previously written code for the last several years, which hasn't been cleaned and optimised without much need. So the code does its job, but there are some places that are no longer needed but have not been cleaned up, as well as some places where, as you can see now, it is possible to simplify the code or apply a different architectural approach in general.

Ideally I would like to get to the level of full automation of optimisation and selection of a good portfolio of strategy parameters using your excellent libraries.

 
Yuriy Bykov #:

Because I wanted to demonstrate the process of moving from a regular EA (input + without OOP)

Got it.