Download MetaTrader 5

How to create a list or dynamic array of structures in MQL5?

To add comments, please log in or register
Follow the news. View our company's official channel!
Pawel Wojnarowski
685
Pawel Wojnarowski 2012.08.08 21:23 
Like in the topic - does anyone know? Unfurtunately CList and CArrayObj from the standard library don't allow struct type.
Documentation on MQL5: Standard Library
Documentation on MQL5: Standard Library
  • www.mql5.com
Standard Library - Documentation on MQL5
Heinz Traub
314
Heinz Traub 2012.08.09 00:37  
Enigma71fx:
Like in the topic - does anyone know? Unfurtunately CList and CArrayObj from the standard library don't allow struct type.

I never came up with this in MQL5 so i gave it a try. You're right, you can't create pointers to structures so you can't rely on a classic C linked list.

Dynamic array of structures technically means this:

struct MyStruct
{
    int i;
    bool b;
};

MyStruct dyn_array[]; // Dynamic array of structures.

I don't know what you're trying to do but these arrays should be enough to work with.

Pawel Wojnarowski
685
Pawel Wojnarowski 2012.08.09 11:58  
TripleHeinz:

I never came up with this in MQL5 so i gave it a try. You're right, you can't create pointers to structures so you can't rely on a classic C linked list.

Dynamic array of structures technically means this:

I don't know what you're trying to do but these arrays should be enough to work with.

Hello TripleHeinz,

Basically as I often use the standard library CList and CArrayObj, I wanted to use these built-in functionalities for dealing with groups of structures. Specifically, I am developing an universal EA framework, which will be capable of trading with a group of 1...n EAs. This basically implies that beside the general framework input parameters, there are also sets of input parameters for each of the EAs - like stop loss parameters, position sizing parameters, indicator parameters etc. I wanted to store all these parameters as structures, not classes (as you basically only need to read/write parameters, so all this overhead related to classes like virtual function table, writing getters/setters is not necessary) and add such structures to each EAs parameter list (e.g. each EA would have CList *ParamList and I could add my own structures like StopLossParams, PosSizingParams or built in ones like MqlParam to this list.

Other issue that I can think of - imagine that for some purposes you want to store groups of MqlTradeRequest or MqlTradeResult. Currently you could only create a static array and have to resize it once in a while. Not very handy to be honest. Handling this in a dynamic array would be much more elegant.

Even worse issue - imagine that you design your own "base" structure of data, e.g. structA. Then you derive structB, structC, structD which differ a little bit, but you would like to store them in one list or dynamic array of objects. Currently not possible with standard library due to lack of pointers to structures (or hopefully I am missing something).

Heinz Traub
314
Heinz Traub 2012.08.09 23:54  
Enigma71fx:

Hello TripleHeinz,

Basically as I often use the standard library CList and CArrayObj, I wanted to use these built-in functionalities for dealing with groups of structures. Specifically, I am developing an universal EA framework, which will be capable of trading with a group of 1...n EAs. This basically implies that beside the general framework input parameters, there are also sets of input parameters for each of the EAs - like stop loss parameters, position sizing parameters, indicator parameters etc. I wanted to store all these parameters as structures, not classes (as you basically only need to read/write parameters, so all this overhead related to classes like virtual function table, writing getters/setters is not necessary) and add such structures to each EAs parameter list (e.g. each EA would have CList *ParamList and I could add my own structures like StopLossParams, PosSizingParams or built in ones like MqlParam to this list.

Other issue that I can think of - imagine that for some purposes you want to store groups of MqlTradeRequest or MqlTradeResult. Currently you could only create a static array and have to resize it once in a while. Not very handy to be honest. Handling this in a dynamic array would be much more elegant.

Even worse issue - imagine that you design your own "base" structure of data, e.g. structA. Then you derive structB, structC, structD which differ a little bit, but you would like to store them in one list or dynamic array of objects. Currently not possible with standard library due to lack of pointers to structures (or hopefully I am missing something).

Hi,

Currently i'm working on an universal EA framework too! (i'm in the early stage though) I believe it's the way to go to get maximum dynamism in the market. Until a small time ago i was inclined by small and simple EAs but now i believe that the great deal is to coordinate a bunch of simple EAs together. Keep the hard work and don't forget to add a benchmark mechanism to change directions in case all is going downwards, these kind of frameworks allow this feature.

I understand all of your points:

...I wanted to store all these parameters as structures, not classes (as you basically only need to read/write parameters, so all this overhead related to classes like virtual function table, writing getters/setters is not necessary)...

You can use container classes and treat them in the same manner as structures with no extra overhead plus gaining access to dynamic pointers wich is what you really would like to use in a framework. You can access class members directly in the same way as structures, just declare them as public, no need to implement getters and setters. Regarding to virtual functions, in my opinion the keyword only exist because MQL5 does not support interfaces or asbtract classes (yet), in the meanwhile there's no big damage in using them.

...Other issue that I can think of - imagine that for some purposes you want to store groups of MqlTradeRequest or MqlTradeResult. Currently you could only create a static array and have to resize it once in a while. Not very handy to be honest. Handling this in a dynamic array would be much more elegant...

You can create dynamic arrays of these structures too (example at my first post). But, please realize that resizing would need to be applied to dynamic arrays too. Static arrays have its initial memory space preallocated, that's the only difference to our concerns.

Even worse issue - imagine that you design your own "base" structure of data, e.g. structA. Then you derive structB, structC, structD which differ a little bit, but you would like to store them in one list or dynamic array of objects. Currently not possible with standard library due to lack of pointers to structures (or hopefully I am missing something).

Even with access to pointers to structures the solution would be much HORRIBLE: The only way to link structures that don't know about each other would be to use void pointers (void*) but in that case it would require to implement a mechanism to know wich type of structure is at any index and then perform the right cast. Class inheritance and the Base/Derived model was brought to address this issue in the most elegant manner using no extra pointers at all. As mentioned before, classes have access to dynamic pointers wich are used to reference an object whose derived type is unknown.

I must say that after reading all your needs, OOP is your best aproach and the most ELEGANT one, trust me. MQL5 implemented OOP to bring life to these complex frameworks. All is there for you to use it and with less (or none) overhead than what you think: Take advantadge of the power of refence types!

After saying that, if you insist in using structures to store data then the most elegant solution would be to create your own List object, it is totally possible in MQL5: Create a dynamic array of your structure and wrap it inside a class then you can implement the basic methods (Add, Remove, IndexOf). But this would not solve all of your needs, this just would pack a single type of structs in a convenient manner and also you would have to create a different class for each type, that's why these wrapper classes are implemented using templates in other languages but they're not supported by MQL5.

I insist, OOP. All your problems solved clean. Don't know at wich stage your program is but sooner or later you would need to use class interfaces to attach EAs to your framework. Structures are kept for simple data types and interaction with plain C APIs. In your case use classes to store data. Hope this serves as guidance.

Pawel Wojnarowski
685
Pawel Wojnarowski 2012.08.10 10:47  

 Hi,

 Thanks for spending your time on a detailed answer. Obviously I am developing my app in the OO manner (to be honest I'd never come back to MQL4 due to lack of OOP), I was just wondering if using structures to store data will give me better runtime efficiency. 

 

TripleHeinz:

(...) You can use container classes and treat them in the same manner as structures with no extra overhead plus gaining access to dynamic pointers wich is what you really would like to use in a framework. You can access class members directly in the same way as structures, just declare them as public, no need to implement getters and setters. Regarding to virtual functions, in my opinion the keyword only exist because MQL5 does not support interfaces or asbtract classes (yet), in the meanwhile there's no big damage in using them. (...)

In your case use classes to store data. Hope this serves as guidance.

I also thought about declaring all attributes in such classes as public, but as far as I know most of C++ authorities recommend keeping most of class attributes as private or protected - so I was not sure if it won't be against sound programming rules if I create classes that have no methods and only attributes, which are public and can be accessed from anywhere and by anything in my app.

Just one more question - if in my current approach I have classes for storing parameters with only getters/setters, and I store groups of parameter objects in CArrayObj or CList, is there any advantage in introducing my own containers? I have checked in the profiler that my current approach consumes almost nothing in terms of time, so I guess that I could stay with it. What's your opinion?

 

Heinz Traub
314
Heinz Traub 2012.08.10 17:17  

I also thought about declaring all attributes in such classes as public, but as far as I know most of C++ authorities recommend keeping most of class attributes as private or protected - so I was not sure if it won't be against sound programming rules if I create classes that have no methods and only attributes, which are public and can be accessed from anywhere and by anything in my app.

MetaQuotes also suggests using encapsulation and gives a few basic pros:

This approach offers several advantages. First, by function name we can understand what it does - sets or gets the value of a class member. Secondly, perhaps in the future we will need to change the type of the m_name variable in the CPerson class or in any of its derivative classes.

In this case, we'll need just to change the implementation of functions SetName() and GetName(), while objects of the CPerson class will be available for using in a program without any code changes because the user will not even know that the data type of m_name has changed.

I think those C++ authorities recommend the use of encapsulation for a matter of "programming best practices" and even related to "programming styles" but there's no standard about how to code using C++ nor MQL5, if the capability of making class members public is there then its sane to use it.

Also in the case of C++ itself there are no authorities, in C++ there's everything but a standard, C++ it's only a language specification but there's no corporation behind it, there's no official compiler nor official documentation (the most important thing for programmers), this is why there're so many C++ variants. Unlike MQL5...but this is beyond the discussion.

Just one more question - if in my current approach I have classes for storing parameters with only getters/setters, and I store groups of parameter objects in CArrayObj or CList, is there any advantage in introducing my own containers? I have checked in the profiler that my current approach consumes almost nothing in terms of time, so I guess that I could stay with it. What's your opinion?

I would stick to the std CList or CArrayObj as you mention. Those are ready to use and very complete classes, they do everithing we need and with haste. I use CList the most, it's the best container class ever, it's easy to insert or remove objects at any index and you can still manipulate objects by indices as in arrays.


MQL5 compiler optimizations are out of public knoledge but yesterday i read a topic from MetaQuotes here that states (look at the end) that the compiler uses a lot of function inlining, to put it in a simple manner, this means that no matter if you're using getters/setters or not, you'll always get the best performance posible. Also the resulting executable size in most cases is extremely small (wich is good).

Right now i use class containers with only public attributes and no methods (the same as you). I use static functions to manipulate the attributes of these classes but after reading that post yesterday i'm going to implement getters and setters and move the functions to manipulate the members into the class itself. This would move my code to my own "programming best practices standard" and to the ones of the C++ authorities :)

With function inlining we both should stop worring about performance hits.

Pawel Wojnarowski
685
Pawel Wojnarowski 2012.08.10 18:06  

TripleHeinz:
MQL5 compiler optimizations are out of public knoledge but yesterday i read a topic from MetaQuotes here that states (look at the end) that the compiler uses a lot of function inlining, to put it in a simple manner, this means that no matter if you're using getters/setters or not, you'll always get the best performance posible. Also the resulting executable size in most cases is extremely small (wich is good). 

 That sounds great :) If so, then I'll definitely stay with the current solution. Thanks a lot for all your help and best of luck with work on your framework!

To add comments, please log in or register