Structure rules. Learning how to structure programmes, exploring possibilities, errors, solutions, etc. - page 7

 
Urain:

I suggest laying out the basic design patterns:

1. Functional

2. object model

3. Event-driven .

...

type in

4. Component

--

In general, any program (including the one you intend) can be viewed from different angles. // it is understandable.

During the initial analysis of a project, I try to consider at least 4 aspects:

1. Structural: Physical and logical organization of program code and program components.

2. Functional (not to be confused with the functional approach in development): What tasks the program solves (what product it produces), what is its use, what output it should produce, etc.

3. Communicative: What kind of user interface the programme should have, what programmes it communicates with and how, communication protocols, etc...

4. Managerial: How the software is managed, what settings need to be made, degrees of freedom, etc.

All aspects are inextricably linked, but looking from these different angles (+ some more) allows you not to miss important subtleties, and in the early stages just not to yawn something important with far-reaching consequences... )

 
MetaDriver:

...In general, any programme (including a conceived one) can be looked at from different angles. // this is understandable...

I absolutely agree. It is a general philosophical principle - to study a phenomenon from different points of view...

And I'm trying to answer the question "What should a program do and what shouldn't it do?" at the beginning of development. The first part of the question falls within the framework of the system (MTS here), the second part does not, is outside.

Imho, it is very important, regardless of the design model, to have a hierarchy of model elements. The deductive method - "from the general to the particular" - then works well, breaking down the model into its main and constituent blocks.

 
MetaDriver:

To exchange ideas / learn from each other, I suggest taking a more or less practical problem and restructuring it together.

For example, at least outline the basic structure (or more accurately, variants of such structures) for such a problem:

There is an Expert Advisor written like this (for example, for testing a trading idea). Let's assume that the idea in the Strategy Tester (at the client) shows promising results. Now we need to rewrite the Expert Advisor to make it more development-friendly. And in particular, to provide it with a graphical user control panel.

It is desirable either to make the panel switchable (for optimization in the tester), or to move the whole "non-graphical" realization of the EA into a pluggable file (.mqh), which may then be connected to the graphical interface without changes (to exclude) the differences in the operation of "tester" and "graphical" versions.

I would like to hear-read the considerations on the structuring of such a project. In particular, on the implementation of the event-driven control model in such a project. Suppose that the double implementation (tester + panel) is a strict requirement of the customer (i.e. the project must be done in any way, you can only choose the method of implementation).

Shall we try the task?

I think it is obvious that the Expert Advisor control panel and the Expert Advisor are two completely different modules in one program. Therefore, they require to be separated in such a way that each part is independent of the other. It means that if you change a part of an Expert Advisor (for example, change in the logic of placing orders), you do not have to change the panel's logic and vice versa (change in the interface of the panel - no need to change the Expert Advisor's logic). The first thing that springs to mind is the creation of a unified interface through which the panel and the Expert Advisor can communicate. But unfortunately, the creators of MQL5 haven't considered the possibility of creating horizontal links, and therefore, describing the interface between them by means of MQL5 will not work. Then the way of vertical integration remains. An Expert Advisor must be inherited from a base class, which in turn contains methods and data sufficient for interaction with the panel. It means that any EA inherited from the base class will also be able to display and interact with the panel. The implementation of methods, responsible for interaction with the panel, must not be delegated to descendants, but must be done behind the scenes of the base class, i.e. the message "Descendant! If you want to interact with the panel, you must call such-and-such of my methods with such-and-such parameters" does not work at all. Ideally, any derived Expert Advisor that inherits from the base class should simply trade in a convenient way and its actions will be automatically displayed on this panel.

How to organize a universal base class is a separate interesting topic. Several years of practice in this matter have finally led me to my universal scheme. It has turned out to be transparent and universal. If you are interested, I can provide you with its basic flowchart (ha ha, drawing flowcharts is a very useful activity after all). But in any case, everyone has his own way, and a good solution for one will not be a good solution for another.

 
C-4:

If interested, I can give you a schematic diagram (ha-ha, drawing block diagrams is a useful activity after all).

 
sergeev:
Finally something cleared up.... )
 
C-4:

The first thing that comes to mind is creating a unified interface through which the panel and the EA can exchange data. 2.

Unfortunately, the creators of MQL5 did not provide possibilities for creating horizontal links, and therefore, describing the interface between them using MQL5 tools is impossible.

1. unambiguously.

2. What about custom events? It's quite horizontal and universal.

3. then the way of vertical integration remains. An Expert Advisor must be inherited from a base class, which in turn contains methods and data sufficient to interact with the panel. This means that any Expert Advisor inherited from the base class also gets the ability to display and interact with the panel. The implementation of methods, responsible for interaction with the panel, must not be delegated to descendants, but must be done behind the scenes of the base class, i.e. the message "Descendant! If you want to interact with the panel, you must call such-and-such of my methods with such-and-such parameters" does not work at all. Ideally, any derived Expert Advisor inherited from a base class should simply trade in a convenient way, while its actions would be automatically displayed on that panel.

Since I do not agree with point 2, I am not digging this variant yet.

--

I have an alternative, which I find very attractive (variant with "disconnectable" panel). Make the panel in the form of an indicator. If your Expert Advisor is in the Strategy Tester, it simply does not load the panel. The additional bonus is that the panel runs in a different thread leaving more resources for the Expert Advisor.

As for the versatility of the panel, I don't see any major obstacles to the panel being fully configurable through an ini file. In other words, you can prescribe there absolutely all of the data needed to create any panel from a limited set of visual components + event codes which they should generate when interacting with a user.

How to arrange a universal base trading class is a separate interesting topic. Several years of practice on this subject has finally led me to my universal scheme. It turned out to be transparent and universal. If you are interested, I can show you its basic block diagram.....

Come on. I'm even very interested. And practically it can be useful.
 
MetaDriver:

1. unambiguously.

Nahr Why? Over-universalisation is as evil as premature optimisation.

And binding blocks of one module via events... ...is slow and inconvenient.

 
MetaDriver:

Come on. I'm actually quite interested, and it could be useful in practice.

The blue frame is the base class entities. The red frame is the entities of the derived class. You can see that the base class imposes the definition of its logic on the descendant in four methods. This is the way it reduces the description of any strategy to a description of just four situations:

1. If all rules for long position opening have been complied with, the long position is opened in InitBuy() method

2. If all rules for long position closing are met - the long position is closed using SupportBuy() method

3. If all the rules for short position opening are met - then the short position is opened using InitSell() method

4. If all the rules for closing the short position are met - then the short position is closed in the SupportSell() method

According to this logic, the strategy reversal is described not in one method (for example, close long open short), but in two methods that don't depend on each other. It turns out, this approach is very convenient because it allows us, for example, to prohibit selling or forcibly close positions by one click after some general conditions that can be described in a base class are met.

In some cases, a strategy has general data for both sales and purchases that should be recalculated upon the occurrence of some event, for example, the arrival of a new bar. In such cases, it is possible for a strategy to subscribe its own processing methods to the events. It is not possible to open positions in these methods, but it is possible to make various calculations.

Another interesting point is how to handle open positions. The base class stores a separate list of long and short positions. When a new event occurs (for example, OnTick), the class starts to list all open positions and offers to process each of these positions one by one using methods SupportBuy SupportSell. These methods can close only the position which is offered to them by the base class at the moment. All other positions are read-only. Thus, the base class imposes the idea on its descendants that at the moment they must focus on a single position only. When I tested this idea, it turned out that the logic of even the most complex Expert Advisor is much simpler. In addition, it gives automatic support to the notion of hedge, because the Expert Advisor keeps information about its long and short positions.
 
TheXpert: ... The implementation of the trading part depends on strategy, so there's nothing to discuss within the framework of a hypothetical strategy. The implementation of the strategy strangely enough depends on the strategy too :)
MetaDriver: ... The whole trading part is written in the form of a class (CMarketDriver) which completely implements order placement, position tracking, requotes and other trading related stuff. For all the symbols at once. The strategy part just receives recommended market positions for symbols: i.e. it fills array of structures of {string Instrument; double Position} format and requests synchronization with the server: MD.Synchronize(PositionArray). That's all. For now it only trades with market orders but a version that trades with limits set inside spread (to reduce trade costs) is on the way. For trading takeprofits/stops are not used, but MarketDriver can put protective stops in case of a long loss of connection to the server (stop parameters are specified once in the driver settings). By the way, a very successful, almost problem-free structural solution. For testing strategic ideas in the tester - no problems with trading, all attention can be devoted to strategy - all trading has long been debugged and encapsulated in the trading driver.

As soon as you start translating the execution of a strategy to limit orders, you'll get a lot of questions, somehow:

  • the effect of your limiters on the price that hits your strategy part (analyzer/prognosticator/brain).
  • synchronization for a multi-currency strategy
  • Lingering absence of execution in a trend trade (trawl? if yes, how, or spit and follow the market)
  • Partial execution
  • ...

Then a feedback between the "executor" and the "analyzer" will have to be implemented, and moreover the parameters of this non-ideal movement should somehow be built into the analyzer's mathematical model

MetaDriver: ... To check strategic ideas in the tester, a song - no problems with trading ...

Yes, for limiters it really is a song.
 
GaryKa:

As you begin to thoroughly convert execution in the strategy to limit orders

This is just an example of what I was talking about -- the trading part depends on the strategy.