Caractéristiques du langage mql5, subtilités et techniques - page 50

 
fxsaber:

Il s'agit d'un problème mineur. Oui, l'optimiseur du compilateur ne sait pas encore comment optimiser de tels moments de chaîne. Mais c'est l'affectation des cordes qui constitue le problème de ralentissement.

Je crois que c'est le principal. Qu'est-ce qui serait le plus efficace : une affectation plus rapide des chaînes de caractères ou leur exclusion du code ? Bien sûr, il y a des cas où nous avons besoin de l'affectation des chaînes en tant que telle, mais combien de fois en avons-nous besoin ? Dans la grande majorité des cas, nous n'avons affaire qu'à des variables temporaires.

La rapidité avec laquelle ces opérations de chaîne peuvent être mises en œuvre est également une question. Vous donnez l'impression qu'il peut être accéléré plusieurs fois. J'en doute. Ils ont déjà optimisé et sur-optimisé tout ce qui s'y trouve plusieurs fois. Supposons qu'ils parviennent à soutirer 20 à 30 % de plus, cela ne fera pas de différence.

Au fait, n'avez-vous pas essayé de déclarer une variable de type chaîne comme constante ?

Donc si tu écris quelque chose comme ça.

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

il est toujours préférable de placer la clause OrderSymbol à la fin de la condition générale.

Bien sûr. Et cela n'a rien à voir avec OrderSymbol, ou MQL. Les opérations sur les chaînes de caractères sont coûteuses en soi, il ne faut donc pas les utiliser en vain.

 

Et donc entre les deux

fxsaber:

Par exemple, si nous exécutons un cycle de ticks réels sur FIBO pendant un mois, cela représentera environ 1 million de ticks. Si, à chaque tick, vous récupérez la valeur de PositionGetString et la comparez à quelque chose, les performances seront acceptables, mais si vous affectez d'abord le résultat de la fonction à une variable de type chaîne de caractères avant de le comparer, la durée d'exécution augmentera d'environ une seconde.


Si cela semble être une petite chose, c'est une vision erronée. Lorsqu'un tel EA est exécuté en mode optimisation pour plusieurs milliers de passages, cette seconde supplémentaire se traduit par des heures d'attente supplémentaires. Par exemple, une affectation de chaîne de caractères anodine peut entraîner des heures d'attente supplémentaires pendant l'optimisation. Soyez prudent et tenez compte de cette nuance.

J'espère que vous comprenez vous-même que cette approche est très inefficace. Pourquoi devrions-nous obtenir PositionGetString à chaque tick? Que peut-elle y changer ? Surtout si l'on considère que vous avez vous-même ouvert ce poste, c'est-à-dire que tout est déjà connu d'avance.

Ainsi, si nous parlons d'optimiser les performances, nous devons d'abord optimiser la logique du programme elle-même.

 
Alexey Navoykov:

Et la question de savoir à quelle vitesse ces opérations de chaîne peuvent être accélérées se pose également. Vous donnez l'impression qu'il peut être accéléré plusieurs fois. J'en doute. Ils ont déjà optimisé et sur-optimisé tout ce qui s'y trouve plusieurs fois. Même si vous parvenez à obtenir 20 à 30 % de plus, cela ne fera pas de différence.

Par moments.

Au fait, n'avez-vous pas essayé de déclarer une variable de type chaîne de caractères comme une constante ?

Oui, je l'ai fait.
 
Alexey Navoykov:

Pourquoi obtenir PositionGetString à chaque tick? Qu'est-ce qui peut y changer ? Surtout si l'on considère que vous avez vous-même ouvert ce poste, c'est-à-dire que tout est déjà connu d'avance.

Eh bien, si nous parlons d'optimiser les performances, nous devons d'abord optimiser la logique du programme lui-même.

Un robot de combat avec une telle logique : il ne devrait y avoir aucune position ouverte sur EURUSD à tel intervalle de temps. S'il y en a, fermez-les.

Vous avez une position ouverte GBPUSD. Comment pouvons-nous remplir la condition ci-dessus sans vérifier OrderSymbol à chaque tick ?

Ou bien vous suggérez d'écrire une version spéciale de l'Expert Advisor juste pour le testeur ? Ici, une personne a acheté un robot de combat et le teste. Comment expliquer au marché que tout est optimisé par la vitesse ?

 
fxsaber:

Un robot de combat avec cette logique - il ne devrait y avoir aucune position ouverte en EURUSD à cet intervalle de temps. S'il y en a, fermez-les.

Vous avez une position ouverte GBPUSD. Comment pouvons-nous remplir la condition ci-dessus sans vérifier OrderSymbol à chaque tick ?

Ou bien vous suggérez d'écrire une version spéciale de l'Expert Advisor juste pour le testeur ? Ici, une personne a acheté un robot de combat et le teste. Devrions-nous écrire dans le Marché que tout est spécialement optimisé par la vitesse pour le testeur ?

Il suffit de vérifier uniquement les tickets des positions actuellement ouvertes (et donc de maintenir un tableau de ces tickets). S'il y a un nouveau ticket, tous les autres contrôles doivent être effectués avec celui-ci. Pourquoi devrions-nous vérifier la même chose un million de fois ?

Au fait, le MQL5 a des événements commerciaux. Il n'est donc pas nécessaire de le vérifier à chaque tic.

 
Alexey Navoykov:

Il suffit de vérifier uniquement les tickers des positions ouvertes actuelles (et de maintenir un tableau de ceux-ci en conséquence).

Ce ne sera pas beaucoup moins cher.

Et d'ailleurs, le MQL5 a des événements commerciaux. Il n'est donc pas nécessaire de vérifier chaque tique.

Parfois, des solutions multiplateformes sont écrites. En outre, il n'existe et ne peut exister aucune garantie d'obtenir tous les événements commerciaux.

 
fxsaber:

Ce ne serait pas beaucoup moins cher.

La différence entre les opérations sur les nombres entiers n'est pas beaucoup moins importante que celle sur les chaînes de caractères ? Eh bien, faites comme vous voulez.

 
Alexey Navoykov:

La différence entre les opérations sur les nombres entiers n'est pas beaucoup moins importante que celle sur les chaînes de caractères ? Eh bien, faites comme vous voulez.

Je ne vois pas pourquoi tu en as besoin, mais tu m'as déconcerté. Et je dois convenir que l'option avec un éventail de billets serait plus productive.

Certes, du point de vue d'une certaine logique, une telle variante semble très artificielle, posée sur une nuance technique, plutôt que sur une construction logique du programme.

Mais je vais tout de même en tenir compte. Bien sûr, je n'ai jamais rencontré cette approche dans kodobase.

 

L'absence d'héritage multiple dans MQL est déprimante, bien sûr. Cependant, vous pouvez le faire fonctionner de toutes les manières possibles - avec des modèles et des macros - vous n'en aurez pas besoin ;).

Voici ce que j'ai fait. Toutes les classes sources doivent être déclarées comme des modèles définissant la classe mère.

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);
}

Bien sûr, il y a quelques subtilités, liées au fait que les classes sont héritées séquentiellement (dans l'ordre que nous avons défini), plutôt que simultanément (comme dans un véritable héritage multiple). En particulier, ils auront des priorités différentes lorsqu'une surcharge se produit. En outre, si une même classe de modèle participe plusieurs fois à la chaîne d'héritage, il s'agira de classes complètement différentes, qui ne sont en aucun cas liées les unes aux autres. Nous devons donc être prudents. Mais il n'y a pas de problème avec les interfaces, vous pouvez hériter sans restrictions.

 
Alexey Navoykov:

L'absence d'héritage multiple dans MQL est déprimante, bien sûr. Cependant, vous pouvez le faire fonctionner de toutes les manières possibles - avec des modèles et des macros - vous n'en aurez pas besoin ;).

Voici ce que j'ai fait. Toutes les classes sources doivent être déclarées comme des modèles définissant la classe mère.

Bien sûr, il y a quelques subtilités, liées au fait que les classes sont héritées séquentiellement (dans l'ordre que nous avons défini), plutôt que simultanément (comme dans un véritable héritage multiple). En particulier, ils auront des priorités différentes lorsqu'une surcharge se produit. En outre, si une même classe de modèle participe plusieurs fois à la chaîne d'héritage, il s'agira de classes complètement différentes, sans aucun lien entre elles. Nous devons donc être prudents. Mais il n'y a aucun problème avec les interfaces, vous pouvez hériter sans limites.

C'est un bon truc. Toute l'astuce consiste à appliquer le modèle au TParent. Je ne l'ai jamais vu comme ça avant.

Raison: