Mon EA fait une double entrée - page 4

 
doshur:

Puis-je demander si PositionSelect() vérifie le côté client ou le côté serveur ?

J'ai le fort sentiment que le problème est causé par le retard où le serveur (côté courtier) traite la demande et n'a pas mis à jour le côté client, c'est pourquoi PositionSelect() s'exécute à nouveau.

J'ai le sentiment qu'il n'y a pas de différence entre cTrade et MqlTradeRequest et que la fonction Sleep devrait aider à retarder tout ce qui est nécessaire pour que le côté client soit "mis à jour" avant que PositionSelect() ne s'exécute à nouveau, causant une double entrée. En vérifiant à partir de mon onglet journal, >2013.12.20 08:35:00 Trades '800****' : exchange buy 0.01 EURUSD at market placed for execution in 313 ms <

mettre en sommeil plus de 400 devrait être sûr ???

Qu'en pensez-vous ?


"J'ai le fort sentiment que le problème est causé par le délai où le serveur (côté courtier) traite la demande et ne met pas à jour le côté client c'est pourquoi PositionSelect() s'exécute à nouveau".

Je pense également que c'est la cause de la double entrée. Dans mon code, il est théoriquement impossible d'envoyer un nouvel ordre si la taille de la position actuelle est égale ou supérieure à la taille maximale autorisée, donc lorsque PositionSelect() ne reçoit pas à temps le statut de la position actuelle, mon EA enverra à nouveau un nouvel ordre.


"mettre en sommeil plus de 400 devrait être sûr ? ??"

Plus l'intervalle de temps est grand, mieux c'est, mais il y a un problème. Si vous retournez votre position, en deux étapes (LONG à SHORT ou SHORT à LONG), ce délai supplémentaire peut être la cause d'un mauvais prix d'exécution, surtout pendant un événement macro-économique.

 
snelle_moda:


"J'ai le fort sentiment que le problème est causé par le délai où le serveur (côté courtier) traite la requête et n'a pas mis à jour le côté client ; c'est pourquoi PositionSelect() s'exécute à nouveau"

Je pense également que c'est la cause de la double entrée. Dans mon code, il est théoriquement impossible d'envoyer un nouvel ordre si la taille de la position actuelle est égale ou supérieure à la taille maximale autorisée, donc lorsque PositionSelect() ne reçoit pas à temps le statut de la position actuelle, mon EA enverra à nouveau un nouvel ordre.


"Mettre en sommeil plus de 400 devrait être sûr ???"

Plus l'intervalle de temps est grand, mieux c'est, mais il y a un problème. Si vous retournez votre position, en deux étapes (LONG à SHORT ou SHORT à LONG), ce délai supplémentaire peut être la cause d'un mauvais prix d'exécution, surtout pendant un événement macro-économique.

Je pense que cela ne devrait pas être un problème. Mon EA ne s'inverse pas immédiatement lorsque je viens d'envoyer une demande d'achat ou de vente. Je mets mon sleep à 800ms pour que mon EA ait suffisamment de temps pour attendre les mises à jour du broker. J'espère que Sleep pourra résoudre ce problème ici.
 
doshur:
Je ne sais pas si le courtier joue à part ici mais il semble que notre courtier soit le même. Alpari.

Veuillez supprimer le nom du courtier si nécessaire.
Oui, le courtier est le même.
 
snelle_moda:


J'ai eu une autre double entrée depuis le 10 mars 2013. J'utilise les deux méthodes pour envoyer ma commande. Voir mon message précédent.

ah huh... comme je m'y attendais...
 

Voici ce que je viens de mettre en place. J'espère pouvoir résoudre le problème.

if(m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0))
            {
               Sleep(800);

               if(m_Trade.ResultRetcode() == 10009)
               {
                  Print("Position opened in ", Symbol());

                  return;
               }
               else
               {
                  Print("Error opening position in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
               }
            }
            else
            {
               Print("Error with PositionOpen in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
            }
 
doshur:

Voici ce que je viens de mettre en place. J'espère pouvoir résoudre le problème.

Pour autant que je sache, un code de résultat = 10008 indique également qu'une transaction est bien placée.
 

Je pense qu'il est très important de trouver la raison derrière ce problème, bien sûr il est également important d'avoir une solution de contournement (Sleep ?) jusqu'à ce que nous puissions comprendre pleinement ce qui se passe. J'essaie donc de résumer la situation :

  • En utilisant la méthode PositionOpen de la classe CTrade, au moins 3 utilisateurs ont obtenu à un moment donné, 2 transactions dans la même direction au lieu d'une, résultant en une position avec un volume doublé par rapport à ce qui est attendu.
  • Le code posté initialement par doshur, peut expliquer pourquoi il peut voir dans son journal "Position ouverte en..." alors qu'aucune transaction n'a été ouverte. En effet, même si PositionOpen() renvoie true, cela ne signifie pas qu'une transaction a été placée. Voir la documentation. Mais cela ne peut pas expliquer pourquoi un "double" trade a été placé.
  • Je ne vois que deux explications à cette "double" transaction :
  1. PositionSelect() ne retourne pas toujours la situation réelle de la position. Une position est ouverte mais PositionSelect renvoie faux. Bug dans PositionSelect alors.
  2. Un trade est placé mais, lorsque PositionSelect() est appelé au tick suivant, la position n'existe pas encore. Pour comprendre si c'est possible, nous devons connaître le déroulement de l'opération lorsqu'une transaction est placée.
  • Ce problème semble se produire sur le même courtier, avec un symbole où la profondeur de marché est activée (les personnes concernées peuvent-elles le confirmer s'il vous plaît).
  • Ce problème se produit avec un ordre synchrone, l'ordre asynchrone n'a pas été utilisé (veuillez confirmer).
  • Le problème se produit de manière aléatoire.
  • Klammeraffe rapporte ne plus avoir le problème, mais je ne vois pas comment le code qu'il a posté peut expliquer cela. Ce code est-il exécuté à chaque tick ? Ce code est-il exécuté après l'utilisation de PositionSelect() ? Donc peut-être qu'il a supprimé la cause de l'erreur ou que c'est juste aléatoire.
  • Après avoir vérifié le code, je ne vois pas de différence entre l'utilisation de la classe CTrade ou de MqlTradeRequest avec OrderSend directement.

Je suis d'accord avec snella_moda que la meilleure explication est:

I think the problem is the (to slow) execution of the PositionSelect(Symbol()) function. Maybe, the new ticks come in so fast, the EA sends in a new order before it receives a response of the PositionSelect(Symbol()). So the current position size is not calculated properly. In my code, its theoretically impossible to send in a new/double order if the current position size is equal or greater than the max allowed position size, see code. 

Mais c'est difficile à vérifier.

Je pense que la meilleure chose à faire est de demander conseil à Metaquotes. Je vais essayer.

 
angevoyageur:
  • Klammeraffe rapporte ne plus avoir le problème, mais je ne vois pas comment le code qu'il a posté peut expliquer cela. Ce code est-il exécuté à chaque tick ? Ce code est-il exécuté après l'utilisation de PositionSelect() ? Donc peut-être qu'il a supprimé la cause de l'erreur ou que c'est juste aléatoire.

La ligne concernant "chaque tick" pourrait être la raison pour laquelle cela ne se produit plus.

La fonction n'est exécutée que lorsqu'une nouvelle barre apparaît. Donc, très probablement, seul le premier tick d'une barre peut exécuter un trade. Après la première barre, le code obtient un 'return' jusqu'à ce qu'une nouvelle barre apparaisse. Peut-être que cela a résolu le problème pour moi.

Je pense que ce morceau de code provient des articles :

//-------------------------------------------------- Check for new bar     
         static datetime OldTime;
         datetime NewTime[1];
         bool newBar=false;
         
         int copied=CopyTime(Symbol(),Period(),0,1,NewTime);
         if (copied>0)
           {
             if (OldTime != NewTime[0])
               {  
                 newBar=true;
                 OldTime=NewTime[0];
               }
           }
         else
           {
            Print("Error in copying historical times data, error =",GetLastError());
            ResetLastError();
            return;
           }  
         if(newBar==false) return;      
//-------------------------------------------------- Check for new bar
 
Klammeraffe:

La ligne concernant "chaque tick" pourrait être la raison pour laquelle cela ne se produit plus.

La fonction n'est exécutée que lorsqu'une nouvelle barre apparaît. Donc, très probablement, seul le premier tick d'une barre peut exécuter un trade. Après la première barre, le code obtient un 'return' jusqu'à ce qu'une nouvelle barre apparaisse. Peut-être que cela a résolu le problème pour moi.

Je pense que ce morceau de code provient des articles :

Oui, je le pense. Merci.
 
  • Le code posté initialement par doshur, peut expliquer pourquoi il peut voir dans son log "Position opened in..." alors qu'aucune transaction n'a été ouverte. En effet, même si PositionOpen() renvoie true, cela ne signifie pas qu'une transaction a été placée.Voir la documentation. Mais cela ne peut pas expliquer pourquoi un "double" trade a été placé.

Correction. Il y a un double"Position opened in..." et 2 trades ont été ouverts.

  • Ce problème semble se produire sur le même courtier, avec un symbole où la profondeur de marché est activée (les personnes concernées peuvent-elles le confirmer s'il vous plaît).
Je ne sais pas pour les autres, mais le mien a DOM

  • Ce problème se produit avec un ordre synchrone, l'ordre asynchrone n'a pas été utilisé (veuillez confirmer).
J'utilise les paramètres par défaut de cTrade.

  • Le problème se produit de manière aléatoire.
oui, aléatoirement

Raison: