Boucles et fermeture ou suppression d'ordres - page 5

 
Eleni Anna Branou:

Veuillez utiliser le bouton </> pour insérer votre code.


Mes excuses... Voici le format correct...

OrdersTotal() pas correct...

J'ai été surpris par une séquence de code en boucle qui utilise OrdersTotal() ne donnant pas des résultats corrects (observé avec deux brokers différents).

J'utilise MT4 version 1090 sur un ordinateur de bureau Linux Ubuntu-MATE 16.04, avec WINE 3.0.

Voici ce que j'ai utilisé...

Voici la situation :

for(int cc = 0; cc < OrdersTotal(); cc++)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);

J'ai remarqué avec deux courtiers différents que la valeur OrdersTotal() ne correspond pas toujours à ce qui est affiché dans l'onglet 'Trade' du courtier MT4. Au départ, j'ai pensé que c'était le courtier qui empêchait OrdersTotal() de fonctionner correctement. Lorsque j'ai remarqué sur le deuxième courtier, j'ai commencé à me demander si MT4 avait un 'problème' interne, ou si mon code était erroné OU si c'était un problème de synchronisation de MT4 avec le serveur.... ?

Après avoir lu ce fil de discussion du forum, je me demande si j'obtiendrais de meilleurs résultats en modifiant la boucle for..loop pour lire :

for(int cc = OrdersTotal() - 1; cc >= 0; cc--)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);
OU, existe-t-il un drapeau ou une ligne de code permettant de s'assurer que la fonction OrdersTotal() est correctement synchronisée pendant un événement OnTick() ?

Toute clarification à ce sujet serait très utile et serait grandement appréciée !

 
Simon Gniadkowski:

C'est l'une des erreurs les plus courantes que je vois, probablement due en partie à des déchets tels que Expert Advisor Builder. J'ai donc pensé qu'il était temps de consacrer un fil de discussion à ce sujet afin de pouvoir y faire référence à l'avenir.

Le problème

Prenons un exemple simple ; nous voulons une fonction pour fermer tous les ordres ouverts pour notre EA, il y a beaucoup d'exemples mais créons-en un à partir de zéro.

Nous avons besoin d'une boucle parce que nous voulons fermer tous nos ordres pour un EA spécifique, dans cette boucle nous aurons du code pour sélectionner l'ordre, du code pour vérifier que le symbole et le numéro magique sont corrects et enfin du code pour fermer l'ordre :

Ce code est mauvais. . . NE L'UTILISEZ PAS. . . Je vais vous expliquer pourquoi dans la section suivante...

L'explication

Travaillons à travers le code ci-dessus... ligne par ligne, ordre par ordre....

Supposons que nous avons les ordres suivants que nous voulons clôturer, ils ont tous le même numéro magique et le même symbole que notre EA, donc nous voulons que notre code les clôture tous :

Position Numéro de ticket
0111
1222
2 333
3444
4555

1er passage dans la boucle :

la valeur initiale de PositionIndex est 0 donc l'ordre en position 0 est sélectionné, le ticket numéro 111, cet ordre est supprimé avec succès et les ordres restants changent de position comme suit :

Position Numéro de ticket
0222
1 333
2444
3555

2ème passage dans la boucle :

maintenant la valeur de PositionIndex est 1 donc l'ordre en position 1 est sélectionné, le ticket numéro 333, cet ordre est supprimé avec succès et les ordres restants changent de position comme suit:

Position Numéro de ticket
0222
1 444
2555

3ème passage dans la boucle :

maintenant la valeur de PositionIndex est 2 donc l'ordre en position 2 est sélectionné, le ticket numéro 555, cet ordre est supprimé avec succès et les ordres restants changent de position comme suit:

Position Numéro de ticket
0222
1 444

4ème exécution de la boucle :

maintenant la valeur de PositionIndex est 3 OrderSelect() essaie de sélectionner l'ordre à la position 3 et échoue, le continue prend l'exécution du code à la valeur suivante dans la boucle ...


5e et dernière exécution de la boucle :

maintenant la valeur de PositionIndex est 4 OrderSelect() essaie de sélectionner l'Ordre à la position 4 et échoue, le continue prend l'exécution du code à la valeur suivante dans la boucle ... la boucle est terminée.


Nous nous retrouvons avec deux commandes, les tickets 222 et 444, qui auraient dû être fermés mais ne l'ont pas été... Comment résoudre ce problème ?

La solution

Le code suivant est l'approche correcte pour fermer des ordres ouverts ou supprimer des ordres en attente...

La différence essentielle est que la boucle décrémente de ( TotalNumberOfOrders - 1 ) à 0

.

Reprenons le code ci-dessus... ligne par ligne, ordre par ordre...

Nous avons les mêmes ordres que précédemment :

Position Numéro de ticket
0111
1222
2333
3444
4555

1er passage dans la boucle :

la valeur initiale de PositionIndex est TotalNumberOfOrders - 1 qui est égal à 5 - 1 = 4, donc l'ordre en position 4 est sélectionné, ticket numéro 555, cet ordre est supprimé avec succès et les ordres restants changent de position comme suit :

Position Numéro de ticket
0111
1222
2333
3444

2ème passage dans la boucle :

maintenant la valeur de PositionIndex est 3 donc l'ordre en position 3 est sélectionné, le ticket numéro 444, cet ordre est supprimé avec succès et les ordres restants changent de position comme suit:

Position Numéro de ticket
0111
1222
2333

3ème passage dans la boucle :

maintenant la valeur de PositionIndex est 2 donc l'ordre en position 2 est sélectionné, le ticket numéro 333, cet ordre est supprimé avec succès et les ordres restants changent de position comme suit:

Position Numéro de ticket
0111
1222

4ème passage dans la boucle :

maintenant la valeur de PositionIndex est 1 donc l'ordre en position 1 est sélectionné, le ticket numéro 222, cet ordre est supprimé avec succès et les ordres restants changent de position comme suit:

Position Numéro de ticket
0111

5ème et dernière exécution de la boucle :

maintenant la valeur de PositionIndex est 0 donc l'ordre en position 0 est sélectionné, ticket numéro 111, cet ordre est supprimé avec succès, la valeur 0 est la dernière valeur valide pour la boucle ... la boucle est terminée.

Nous avons supprimé avec succès tous nos ordres correspondants....

Lien vers cette discussion : Boucles et fermeture ou suppression d'ordres

Merci beaucoup ! C'est une explication très claire.
 
Bonjour aux codeurs,
J'ai parcouru ce fil de discussion en lisant sur la sélection des ordres. En effet, j'ai un code où je pense avoir fait les choses correctement mais la sélection ne fonctionne pas pour moi car je ne peux pas lire le OpenPrice de l'ordre sélectionné. Tout le reste fonctionne bien, juste cette partie du code fournie. Je ne sais pas pourquoi.
L'ensemble du code comporte 4 sections où je dois appeler le OrderOpenPrice juste après l'envoi de l'ordre... OrderSend fonctionne bien, OrderSelect ne me donne pas les résultats dont j'ai besoin. Référez-vous à une section du code si vous pouvez m'aider.
Merci.
 if(Protection_Step_One==1)
        {
        while(Protective_Order<0)
          {
          RefreshRates();
          Protective_Order=OrderSend(Symbol(),OP_SELL,Protective_Lots,NormalizeDouble(MarketInfo(Symbol(),MODE_BID),MarketInfo(Symbol(),MODE_DIGITS)),3,0,0,"Intermediary",MN_Sell_Intermediary_Protection,0,Cyan);
          }
  //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Addition for Clamp       
          for (int i=OrdersTotal()-1; i>=0; i--)
            {if(OrderSelect(i,SELECT_BY_POS, MODE_TRADES)==true)
               {if (OrderMagicNumber()==MN_Sell_Intermediary_Protection)
                  { RefreshRates();
                  Intermediary_OpenPrice_Sell= OrderOpenPrice();
                  }
                }
             }   
               //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..
        if(Protective_Order!=-1)
          { 
          Protection_Step_One=0;
          RealTime_Drawing=2;
          Protective_Mode_Activated=1;
          Protective_Order=-2;
          Defcon=2;

 

Merci, cherSimon Gniadkowski,

Votre article m'a vraiment fait gagner du temps.

 
Gelson Kasonia:
void OnStart()
{
     int Protective_Order=OrderSend(_Symbol,ORDER_TYPE_BUY,0.01,Ask,3,0,0,"Intermediary");
     if(Protective_Order<0)
          return;
     if(!OrderSelect(Protective_Order,SELECT_BY_TICKET, MODE_TRADES))
          return;
     Print(Protective_Order, " OrderOpenPrice: ", OrderOpenPrice());
}
 

Voici le code que je propose pour la fermeture des ordres de marché.

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersBackward()
  {
   for(int i=OrdersTotal()-1; i>=0 && !IsStopped(); i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(!OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))

            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
        }
     }
  }

Et je suggère que c'est la manière correcte d'utiliser une boucle forward for (pour se conformer aux règles FIFO des courtiers américains).

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersForward()
  {
   for(int i=0; i<OrdersTotal() && !IsStopped(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))
           {
            i--;
           }
         else
           {
            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
           }
        }
     }
  }

Dans la boucle avant,

  1. La fonction OrderTotal() est utilisée à l'intérieur de la boucle for pour mettre à jour le nombre restant d'ordres ouverts à chaque itération de la boucle, pour éviter que l'index ne sorte de la plage du tableau.
  2. L'indice i est décrémenté à chaque ordre fermé, pour éviter de sauter certains ordres.
 
amrali: L'indice i est décrémenté à chaque ordre fermé, pour éviter de sauter certains ordres.
En présence d'ordres multiples (un EA, plusieurs graphiques, plusieurs EA, trading manuel), pendant que vous attendez la fin de l'opération en cours (fermeture, suppression, modification), un certain nombre d'autres opérations sur d'autres ordres peuvent se produire simultanément et modifier l'indexation de la position :
  1. Pour les courtiers non FIFO (courtiers américains)(ou l'EA n'ouvre qu'un seul ordre par symbole), vous pouvez simplement compter à rebours dans une boucle de position, et vous ne manquerez pas d'ordres. Prenez l'habitude de toujours compter à rebours.
    Boucles et fermeture ou suppression d'ordres - Forum de programmation MQL4
    Pour le FIFO ( courtiers américains,)et que vous traitez (potentiellement) plusieurs ordres par symbole, vous devez Trouver l'ordre le plus ancien, le fermer, et sur une opération réussie, retraiter toutes les positions restantes.
    CloseOrders by FIFO Rules - Strategy Tester - MQL4 programming forum - Page 2 #16

  2. et vérifiez OrderSelect au cas où des positions antérieures auraient été supprimées.
    Quelles sont les valeurs de retour des fonctions ? Comment les utiliser ? - Forum de programmation MQL4
    Erreurs courantes dans les programmes MQL4 et comment les éviter - MQL4 Articles
  3. et si vous traitez (potentiellement) plusieurs ordres, vous devez appelerRefreshRates() après les appels du serveur si vous voulez utiliser, sur le prochain ordre / appel du serveur, les variables prédéfinies(Bid/Ask) ou (être indépendant de la direction et utiliser) OrderClosePrice().
 

Vous savez à quel point cela m'a aidé. Pas seulement avec le code sur lequel je travaillais, mais avec ma compréhension totale. Il fonctionne parfaitement maintenant et j'ai la possibilité de le mettre en œuvre de différentes manières.

J'apprécie vraiment cette information.