Features of the mql5 language, subtleties and tricks - page 50

 
fxsaber:

This is a minor problem. Yes, the compiler optimizer does not yet know how to optimize such string moments. But it is the string assignment that is the problem of slowdown.

I believe it is of paramount importance. Which would be more efficient: faster string assignment or exclusion of it from the code? Of course, there are cases when we need string assignment by itself, but how often do we see that? In the vast majority of cases, we are dealing only with temporary variables.

And how much faster these string operations can be is also a question. You make it sound as if it can be sped up many times over. I doubt it. They have already optimized-over-optimized everything there many times over. Let them squeeze out another 20-30% - it won't make a difference.

By the way, have you ever tried to declare a string variable as a constant?

So if you write something like this

if ((OrderSymbol() == Symb) && (OrderMagicNumber == Magic))

it's always better to shove OrderSymbol clause to the end of general condition.

Well, that's for sure. The OrderSymbol has nothing to do with it, neither does MQL. The string operations are very expensive, so it's not worth using them in vain.

 

And so in between

fxsaber:

For example, if we run a real ticks run on FIBO for a month, it will be about 1 million ticks. If you get the value of PositionGetString on each tick and compare it with something, the performance will be acceptable, but if you first assign the result of the function to a string variable and then compare it, the duration of the run will increase by about a second.


If it seems to be a trifle, it is an erroneous view. When such an EA is run in optimization mode for several thousand passes, that extra second will result in additional hours of waiting. I.e. a harmless string assignment may cause additional hours of waiting during optimization. Be careful and take this nuance into account.

I hope you understand that this approach is extremely inefficient. Why should we get PositionGetString at each tick? What can change there? Especially considering that you yourself opened this position, so everything is already known in advance.

So, if we are talking about optimizing the performance, then first of all we need to optimize the program logic itself.

 
Alexey Navoykov:

And how fast these string operations can be accelerated is also a question. You make it sound as if you can speed it up many times over there. I doubt it. They have already optimized-over-optimized everything there many times over. Even if you manage to squeeze another 20-30%, it won't make a difference.

At times.

By the way, haven't you tried to declare a string variable as a constant?

I did.
 
Alexey Navoykov:

Why get PositionGetString on every tick? What can change there? Especially considering that you opened this position yourself, so everything is already known in advance.

So, if we are talking about optimizing performance, then first of all we need to optimize the program logic itself.

A fighting robot with such logic: there should be no open positions in EURUSD at such a time interval. If there are any, close them.

GBPUSD position is open. How to fulfill the condition above without checking OrderSymbol on every tick?

Or, do you suggest to write a special version of the Expert Advisor specifically for the Strategy Tester? A person has bought a fighting robot and is testing it. How to explain in the Market that everything is optimized by speed?

 
fxsaber:

A fighting robot with the following logic - there should be no open positions in EURUSD at such a time interval. If there are, then close them.

You have an open GBPUSD position. How to fulfill the condition above without checking OrderSymbol on every tick?

Or, do you suggest to write a special version of the Expert Advisor specifically for the Strategy Tester? A person has bought a fighting robot and is testing it. Should I write in the Market that everything is specially optimized by speed for the tester?

Well, it is enough to check only the tickers of the current open positions (and thus maintain an array of them). If there is a new ticket, then all the other checks should be carried out with it. Why check the same thing a million times?

By the way, MQL5 has trade events. Therefore, there is no need to check it on every tick.

 
Alexey Navoykov:

Well, it is enough to check only the tickers of the current open positions (and, accordingly, keep an array of them).

It will not be much cheaper.

And by the way, MQL5 has trade events. Therefore, there is no need to check on every tick.

Sometimes cross-platform solutions are written. Moreover, there is no guarantee that all trade events will be obtained.

 
fxsaber:

It won't be much cheaper.

The difference between integer operations is not much cheaper than string operations? Well, suit yourself.

 
Alexey Navoykov:

The difference between integer operations is not much cheaper than string operations? Well, suit yourself.

I don't know why you need it, but you've got me bored. And I have to agree that the option with an array of tickets would be more productive.

However, from the point of view of some logic, this variant looks very artificial, laid on a technical nuance, rather than a logical construction of the program.

But still I will take it into account. Of course, I have never encountered this approach in kodobase.

 

The lack of multiple inheritance in MQL is depressing, of course. However, you can get out of it using available means: templates and macros - you can't do without them )

Here is what I have made. All source classes should be declared as templates that define the parent class.

class CBase { };  // базовый класс

// Макросы, задающие список наследования:

#define  INHERIT1(T)  T<CBase>

#define  INHERIT2(T1, T2)  T2<INHERIT1(T1)>

#define  INHERIT3(T1, T2, T3)  T3<INHERIT2(T1,T2)>

#define  INHERIT4(T1, T2, T3, T4)  T4<INHERIT3(T1,T2,T3)>


// Различные пользовательские классы:

template<typename TParent>
class A : public TParent { public: void a() { Print("A"); } };

template<typename TParent>
class B : public TParent { public: void b() { Print("B"); } };

template<typename TParent>
class C : public TParent { public: void c() { Print("C"); } };


class X : public INHERIT3(A, B, C)  {  };   // Объявляем класс, наследуемый от A, B, C


template<typename T>
void SomeFunc(B<T>& obj)  { obj.b(); }   // Проверочная функция, принимающая класс B


void OnInit()
{
  X x;
  x.a();
  x.b();
  x.c();
  
  SomeFunc(x);
}

Of course there are some subtleties, related to the fact that classes are inherited sequentially (in the order we've set), rather than in parallel (as in true multiple inheritance). In particular, they will have different priorities when an overload occurs. Besides, if the same template class participates in an inheritance chain several times, they will be completely different classes that are not related to each other in any way. So you have to be careful here. But there are no problems with interfaces, you can inherit without restrictions.

 
Alexey Navoykov:

The lack of multiple inheritance in MQL is depressing, of course. However, you can get out of it using available means: templates and macros - you can't do without them )

Here is what I have made. All source classes should be declared as templates that define the parent class.

Of course there are some subtleties, related to the fact that classes are inherited sequentially (in the order we've set), rather than in parallel (as in true multiple inheritance). In particular, they will have different priorities when an overload occurs. Besides, if the same template class participates in an inheritance chain several times, they will be completely different classes that are not related to each other in any way. So you have to be careful here. But there are no problems with interfaces; you can inherit without restrictions.

That's a good trick. The whole point is in applying the pattern to TParent. I haven't seen it like that before.

Reason: