Problème de saisie d'ordres multiples pour un compte en direct avec un courtier spécifique - page 2

 
Malacarne:

BonjourBlindMist, il est judicieux de vérifier votre base de données locale pour vérifier si votre compte est synchronisé avec le serveur du courtier.

Veuillez consulter le post suggéré pour résoudre ce problème.

Je viens de parcourir le post suggéré et il ne mentionne pas comment empêcher les ordres d'être exécutés plusieurs fois...

Même avec la fonction Sleep(), combien de temps devez-vous attendre pour être certain que le trade a échoué ?...

Dans mon EA, j'ai fait en sorte qu'une demande d'envoi d'ordre se termine au bout de 10 secondes avant de réessayer... mais parfois l'ordre est exécuté 15 à 20 secondes après la demande initiale, ce qui entraîne une double transaction indésirable.

 
BlindMist:

Je viens de parcourir le post suggéré et il ne mentionne pas comment empêcher les ordres d'être exécutés plusieurs fois....

Même avec la fonction Sleep(), combien de temps devez-vous attendre pour être certain que la transaction a échoué ?...

Dans mon EA, j'ai fait en sorte qu'une demande d'envoi d'ordre se termine au bout de 10 secondes avant de réessayer... mais parfois l'ordre est exécuté 15 à 20 secondes après la demande initiale, ce qui entraîne une double transaction indésirable.

SalutBlindMist, mon idée à ce sujet, que je pense toujours être la seule façon de le vérifier (au lieu d'un seul test de PositionSelect ou d'un seul Sleep), est de créer quelque chose comme une erreur fatale après une longue attente, ou de sauter dès que vous avez la position du symbole (code ci-dessous).

La seule bonne chose à propos de ce problème est que probablement PositionSelect, tôt ou tard, obtiendra la position mise à jour du serveur, donc ce que nous devons faire est d'attendre un temps maximal (notre timeout) pour indiquer une erreur fatale et faire de petits échantillons pour vérifier si c'est OK (100 ms dans mon exemple).

bool fatalError=false; // atention: declare this as global

....

if (fatalError==false) {
  if (m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0)) {
    Print("Position opened in ", Symbol());
    int maxTimeout=0;
    while (!PositionSelect(Symbol())) {
       Sleep(100);
       maxTimeout++;
       if (maxTimeout>100) {
          Print("### PositionSelect fatal error!");
          fatalError=true;
          break;
       }
    }
    Print("--> PositionSelect delay=",maxTimeout*100);
    break;
  }
}

Une autre façon de faire plus modulaire est de créer une fonction pour contrôler le timeout, par exemple :

bool PositionSelectTimeout(string symbol,int timeout) 
  { // timeout in seconds
   int maxTimeout=0;
   while(!PositionSelect(symbol)) 
     {
      Sleep(100);
      maxTimeout++;
      if(maxTimeout>(timeout*10)) return(false); // fatal error (timeout)
     }
   return(true); // position selected
  }

L'idée principale ici est que ma PositionSelectTimeout() remplace la PositionSelect() originale, comme une solution de contournement bien sûr, puisque seulement MQ peut adresser une solution vraiment bonne et définitive.

Par exemple :

if (PositionSelectTimeout(Symbol(),60)) { // 60 seconds timeout
 ...
}

// instead of ...

if (PositionSelect(Symbol())) {
 ...
}

Donc, à mon avis,FinanceEngineer doit faire la même chose pour résoudre le problème, et insérer ce test à l'intérieur de sa boucle, pour vérifier à nouveau si la position est OK pour prendre une pause.

 
figurelli:

SalutBlindMist, mon idée à ce sujet, que je pense toujours être la seule façon de le vérifier (au lieu d'un seul test de PositionSelect ou d'un seul Sleep), est de créer quelque chose comme une erreur fatale après une longue attente, ou de sauter dès que vous avez la position du symbole (code ci-dessous).

La seule bonne chose à propos de ce problème est que probablement PositionSelect, tôt ou tard, obtiendra la position mise à jour du serveur, donc ce que nous devons faire est d'attendre un temps maximal (notre timeout) pour indiquer une erreur fatale et faire de petits échantillons pour vérifier si c'est OK (100 ms dans mon exemple).

Une autre façon de faire plus modulaire est de créer une fonction pour contrôler le timeout, par exemple :

L'idée principale ici est que ma PositionSelectTimeout() remplace la PositionSelect() originale, comme une solution de contournement bien sûr, puisque seulement MQ peut adresser une solution vraiment bonne et définitive.

Par exemple :

Donc, à mon avis,FinanceEngineer doit faire la même chose pour résoudre le problème, et insérer ce test dans sa boucle, pour vérifier à nouveau si la position est OK pour faire une pause.

Merci figurelli, réponse très détaillée. Je vais essayer et voir si cela améliore mon système.
 
BlindMist:
Merci figurelli, réponse très détaillée. Je vais faire un essai et voir si cela améliore mon système.
Merci, vous êtes le bienvenu.
 
BlindMist:

Je viens de parcourir le post suggéré et il ne mentionne pas comment empêcher les ordres d'être exécutés plusieurs fois...

Même avec la fonction Sleep(), combien de temps devez-vous attendre pour être certain que la transaction a échoué ?...

Dans mon EA, j'ai fait en sorte que la demande d'envoi d'un ordre se termine au bout de 10 secondes avant de réessayer... mais parfois l'ordre est exécuté 15 à 20 secondes après la demande initiale, ce qui entraîne une double transaction indésirable.

15 secondes pour l'exécution d' un ordre. C'est vraiment mauvais. Le problème ici est que nous ne pouvons rien obtenir du serveur du courtier (par exemple, même un simple élément de code de vérification du statut, etc.)
 
FinanceEngineer:
15 secondes pour l'exécution d' un ordre. C'est vraiment mauvais. Le problème ici est que nous ne pouvons rien obtenir du serveur du courtier (par exemple, même un simple morceau de code de vérification du statut, etc).

BonjourFinanceEngineer, vous avez raison, cependant la première chose à faire est de choisir un courtier à faible latence, puisque les marchés sont chaque fois plus rapides, et il sera habituel de tels problèmes.

En outre, il est toujours bon de penser au pire des cas, car vous pouvez avoir un courtier à faible latence, mais à certains moments de la journée un retard important, par exemple lorsque vous avez des nouvelles pertinentes.

Quoi qu'il en soit, OrderSend() dans MT5 n'est pas aussi facile à gérer que dans MT4, car la valeur retournée par MT4 est un ticket. Ce changement était nécessaire pour MT5 car la communication asynchrone des marchés boursiers, introduite dans l'architecture MQL5, permet de communiquer avec le protocole OMS des courtiers (comme FIX, par exemple).

Mais je pense que c'est le grand changement d'OMS pour la gestion des ordres aujourd'hui, car il est très difficile d'obtenir un ticket en temps réel, et MT5 est mis à jour pour ce nouveau scénario, principalement si nous utilisons les marchés boursiers, où nous avons plus de latence.

En ce sens, la chose la plus pertinente à faire après un OrderSend() à MT5 est de vérifier PositionSelect(), et je suggère fortement d'utiliser ma proposition de contournement PositionSelectTimeout(), pour toutes les raisons ci-dessus.

La seule façon que je vois de penser aux pires cas est de gérer toutes les conditions if { } else { } après l'envoi d'un ordre sur le marché, de manière à pouvoir gérer toutes les situations.

J'aimerais aussi avoir des catch { }, mais nous pouvons utiliser GetLastError() pour faire quelque chose d'approchant.

En effet, vous avez également besoin du ticket pour confirmer une position et MT5 OrderSend() ne renvoie pas le ticket de manière aussi synchrone que MT4.

 
BlindMist:

Je viens de parcourir le post suggéré et il ne mentionne pas comment empêcher les ordres d'être exécutés plusieurs fois....

Même avec la fonction Sleep(), combien de temps devez-vous attendre pour être certain que la transaction a échoué ?...

Dans mon EA, j'ai fait en sorte qu'une demande d'envoi d'ordre se termine au bout de 10 secondes avant de réessayer... mais parfois l'ordre est exécuté 15 à 20 secondes après la demande initiale, ce qui entraîne une double transaction indésirable.

Voici le code que j'utilise actuellement. Jusqu'à présent, je n'ai pas de problème. Vous pouvez essayer ce code et voir s'il fonctionne pour ce courtier.

      bool checkOrderSend = OrderSend(request, result);
     
      if(result.retcode==10009 || result.retcode==10008)
      {
          Print("OrderSend was successful. Code: ",result.retcode);

          
          break;
      }
      else
      {
          Print(ResultRetcodeDescription(result.retcode));
      }
     

 
FinanceEngineer:

Voici le code que j'utilise actuellement. Jusqu'à présent, je n'ai pas de problème. Vous pouvez essayer ce code et voir s'il fonctionne pour ce courtier.

      bool checkOrderSend = OrderSend(request, result);
     
      if(result.retcode==10009 || result.retcode==10008)
      {
          Print("OrderSend was successful. Code: ",result.retcode);

          
          break;
      }
      else
      {
          Print(ResultRetcodeDescription(result.retcode));
      }
     

Que faites-vous avec la variable checkOrderSend?

Comment empêchez-vous l'exécution de plusieurs ordres sans vérifier l'achèvement de la transaction du serveur ?

 
figurelli:

Que faites-vous de la variable checkOrderSend ?

Comment empêcher l'exécution de plusieurs ordres sans vérifier l'achèvement de la transaction du serveur ?

Bonjour figurelli

Mon but était de vérifier les codes 10009 et 10008 à la fin de la fonction OrderSend. Parce que j'ai constaté que de nombreuses personnes ne vérifient que l'un ou l'autre des codes de retour (c'est-à-dire 10009 ou 10008) et obtiennent de nombreux ordres multiples, car ils placent normalement une boucle for pour éviter une situation d'absence d'ordre.

Dans mon cas, ma boucle for va essayer 10 fois si je ne reçois aucun ordre de ce courtier. Il est donc probablement utile de préciser que si quelqu'un reçoit des ordres multiples, il doit vérifier s'il arrête sa boucle d'envoi d'ordres en vérifiant à la fois 10009 et 10008.

Cependant, ironiquement, sur un compte de démonstration, la vérification d'un seul code de retour suffit. Cela ne vous posera pas de problème de commande multiple. J'ai donc constaté que le compte réel et le compte de démonstration se comportent légèrement différemment.

Cordialement.

 
FinanceEngineer:

Bonjour figurelli

Mon but était de vérifier les deux codes 10009 et 10008 à la fin de la fonction OrderSend. Parce que j'ai constaté que de nombreuses personnes ne vérifient que l'un ou l'autre des codes de retour (c'est-à-dire 10009 ou 10008) et obtiennent de nombreux ordres multiples, car ils placent normalement une boucle for pour éviter une situation de non-ordre.

Dans mon cas, ma boucle for va essayer 10 fois si je ne reçois aucun ordre de ce courtier. Il est donc probablement utile de préciser que si quelqu'un reçoit des ordres multiples, il doit vérifier s'il arrête sa boucle d'envoi d'ordres en vérifiant à la fois 10009 et 10008.

Cependant, ironiquement, sur un compte de démonstration, la vérification d'un seul code de retour suffit. Cela ne vous posera pas de problème de commande multiple. J'ai donc constaté que le compte réel et le compte de démonstration se comportent légèrement différemment.

Cordialement.

BonjourFinanceEngineer, peut-être serait-il préférable de commencer à vérifier le problème des ordres multiples dans votre code original, car si nous le faisons, nous aborderons probablement d'autres points critiques ici et ne perdrons pas le focus, qu'en pensez-vous ?
Raison: