MT5 et la vitesse en action - page 4

 
Je comprends que tout dépend de l'équipement
 
Alexsandr San:
Je comprends que cela dépend de l'équipement

Pas du tout !

2020.05.29 15:08:44.938 Terminal        Windows 7 Service Pack 1 build 7601, Intel Core i7-6850 K  @ 3.60 GHz, 23 / 31 Gb memory, 43 / 226 Gb disk, IE 11, UAC, Admin, GMT+3
 
Alexsandr San:
Je suppose que cela dépend du matériel.

Je ne pense pas ))))

Et même pas depuis un ordinateur occupé...

 
prostotrader:

Pas du tout !

oui ! votre machine et la précédente ont des résultats différents - donc je me trompe, pas les moyens de puissance

 
Aleksey Mavrin:

Qu'est-ce que onMain ? Comment peut-il y avoir plus d'un événement dans la file d'attente de onMain si chaque événement appelle onMain pour gérer la file d'attente ?

OnMain est une fonction. Il ne s'agit pas d'un code réel, mais d'un cas particulier - une réponse à l'affirmation "Il n'y a aucun moyen de connaître l'état de la file d'attente réelle actuellependant l'exécution de la fonction OnMain".Il s'agit d'une approche différente des calculs eux-mêmes

 
A100:

OnMain est une fonction. Ilne s'agit pas du code actuel, mais d'un cas particulier - une réponse à l'affirmation "Il n'y a aucun moyen de connaître l'état de la file d'attente réelle actuellependant l'exécution de la fonction OnMain". Il s'agit d'uneapproche différente des calculs eux-mêmes.

Donc, juste au cas où, OnMain...

:) ;)
 
fxsaber:


Dans Combat Advisors, j'ai enveloppé des fonctions partout dans des endroits suspects à _B(FuncName(...), AlertTime). Voici un court extrait du journal des entrées les plus récentes.

La colonne de temps indique la fréquence des gels.

Vous substituez des concepts.

Voici votre déclaration originale :

Malheureusement, un tel appel HistorySelect dure 5-30 millisecondes (je l'ai mesuré moi-même dans la Release-EX5). Lorsque le conseiller expert effectue plusieurs mises à jour de ce type dans OnTick (dans le bon sens du terme, cela devrait être fait après toute pause. Par exemple, après chaque OrderSend.), tout devient follement cher/long. HistorySelect peut ajouter jusqu'à plusieurs secondes dans un seul OnTick.

Même dans votre terminal, le temps moyen de 0,2 ms par appel est sensiblement inférieur aux valeurs spécifiées dans la déclaration originale.

Vous dites maintenant que, parfois, le temps d'exécution d'une fonction peut être sensiblement plus long que la moyenne. C'est une autre question.

Toute requête HistorySelect() est un appel à part entière aux bases terminales sous synchroniseurs. C'est inévitable. Oui, compte tenu de la présence de la synchronisation des accès, nous ne pouvons pas garantir un temps très court d'exécution de cette fonction.

La solution proposée en ajoutant les fonctions HistoryDealsSelect() et HistoryOrdersSelect() ne change absolument rien en ce sens.

Le script pour vérifier le temps maximum et moyen :

void OnStart()
  {
   MqlTick Tick;
   SymbolInfoTick(_Symbol, Tick);
//---
   ulong start,end,max_time=0,avr_time=0;
   int   count=100000;
   for(int i=0; i<count; i++)
     {
      start=GetMicrosecondCount();
      HistorySelect(Tick.time, INT_MAX);
      end=GetMicrosecondCount()-start;
      //--- >1 ms
      if(end>1000)
         Print(" > 1 ms for one HistorySelect: ",DoubleToString(end/1000.0,2)," ms");
      //---
      if(end>max_time)
         max_time=end;
      avr_time+=end;
     }
   Print("Last tick time. Selected orders: ",HistoryOrdersTotal(),"; max time: ",DoubleToString(max_time/1000.0,3)," ms; avr time: ",DoubleToString(avr_time/1000.0/count,3)," ms; ",count," iterations");
//---
   Tick.time=(Tick.time/86400)*86400;
   max_time=0;
   for(int i=0; i<count; i++)
     {
      start=GetMicrosecondCount();
      HistorySelect(Tick.time, INT_MAX);
      end=GetMicrosecondCount()-start;
      //--- >1 ms
      if(end>1000)
         Print(" > 1 ms for one last day HistorySelect: ",DoubleToString(end/1000.0,2)," ms");
      //---
      if(end>max_time)
         max_time=end;
      avr_time+=end;
     }
   Print("Last day. Selected orders: ",HistoryOrdersTotal(),"; max time: ",DoubleToString(max_time/1000.0,3)," ms; avr time: ",DoubleToString(avr_time/1000.0/count,3)," ms; ",count," iterations");
//---
   HistorySelect(0, INT_MAX);
   Print("Orders total: ",HistoryOrdersTotal());
  }
2020.05.29 17:22:04.195 TestHistorySelect (EURJPY,H1)   Last tick time. Selected orders: 0; max time: 0.034 ms; avr time: 0.001 ms; 100000 iterations
2020.05.29 17:22:06.771 TestHistorySelect (EURJPY,H1)   Last day. Selected orders: 141; max time: 0.101 ms; avr time: 0.027 ms; 100000 iterations
2020.05.29 17:22:08.039 TestHistorySelect (EURJPY,H1)   Orders total: 31448
 
Anton:

Un script pour vérifier les temps maximum et moyen :

Je ne commenterai pas votre opinion avant de la citer. Voici le résultat de l'exécution de votre script.

Plus précisément, je ne pouvais pas attendre qu'il se termine, alors j'ai changé le nombre d'itérations de 100K à 1K.

        Last tick time. Selected orders: 0; max time: 3.880 ms; avr time: 1.315 ms; 1000 iterations
        Last day. Selected orders: 2061; max time: 7.131 ms; avr time: 4.309 ms; 1000 iterations
        Orders total: 50113

Est-ce que cela mérite même une note satisfaisante ?

Regardez l'absurdité de la situation. Afin de trouver bêtement le nombre de transactions, nous devons appeler HistorySelect! Ce n'est pas rationnel, c'est le moins que l'on puisse dire.


Je passe au mieux quelques dizaines de millisecondes sur chaque tick uniquement à cause de HistorySelect.

 
A100:

Dans sa forme la plus simple :

Il suffit de modifier son approche des calculs eux-mêmes (faire des retours intermédiaires aussi souvent que la tâche l'exige). Mais si c'est compliqué, considérez à la 1ère étape que OnMain est absent pour vous (vous mettez le code principal non pas dans OnMain mais dans OnTrade2XX), donc vous n'avez rien à apprendre dans OnMain

Merci, c'est exactement comme ça que je l'ai compris depuis le début et c'est pour ça que j'ai dit que je ne le comprenais pas complètement. Voici un exemple de scénario simple.


Vous faites un OrderSend. Si une certaine position n'a pas clôturé sur la marque juste après l'envoi de l'ordre, vous faites un autre envoi d'ordre. Tout cela est logique et doit être programmé. Async n'est pas utilisé.


Maintenant, la situation qui s'est produite pour notre robot. Vous avez envoyé un OrderSend et pendant son exécution, le Limiter s'est déclenché et le TP de la position mentionnée ci-dessus a été exécuté.


Quelle est l'implémentation du robot de manière schématique ? Je ne sais pas comment l'implémenter sans freiner HistorySelect ou OnTradeTransaction - une béquille qui donne accès à l'historique complet des transactions à n'importe quel endroit du code. Si un mécanisme d'accès à la file d'attente des événements était mis en œuvre, l'exemple ci-dessus serait résolu de manière élémentaire.


Tous ceux qui connaissent bien MT5, y compris les développeurs, veuillez me montrer comment mettre en œuvre cette logique de trading simple (je n'ose même pas parler de complexe)( deux lignesen gras ci-dessus).

 
A100:

OnMain est une fonction. Il ne s'agit pas du code actuel, mais d'un cas particulier - une réponse à l'affirmation " Il n'y a aucun moyen de connaître l' état de la file d'attente réelle actuelle pendant l'exécution de la fonction OnMain". Il s'agit d'uneapproche différente des calculs eux-mêmes.

Eh bien, ça l'est, n'est-ce pas. Et c'est de ça que les gars parlaient. Pour le mettre en œuvre, vous devez modifier la structure d'exécution des programmes MQL, soit a) au moins en une structure à deux fils, soit b) ajouter un mécanisme d'accès et de gestion des files d'attente.

Avec la structure actuelle, le système que vous proposez est impossible à mettre en œuvre.