Créateur de grilles 1.1 - page 4

 
Désolé Cori, je n'ai qu'un seul ordre pour une position de grille donnée et j'ai testé à peu près toutes les variations - sur plusieurs semaines maintenant.

Je supprime de temps en temps tous les ordres ouverts pour que nos amis de MT4 ne soient pas contrariés.

Vous aurez ce problème dans le backtesting mais ce n'est pas un problème de script... mais un problème de backtesting MT4.

Si cela continue, faites-le moi savoir ou envoyez-moi des rapports montrant le problème...

merci et reagrds,

hugues
 
Je l'ai trouvé. Et cela ne m'amuse pas.

Le conseiller crée la grille avec mon commentaire "GridEURUSD". Ce commentaire reste dans le champ Commentaire tant que l'ordre est en attente. Si l'ordre est activé, le commentaire devient "activate/auto". Après tout, il est clair que ce comportement conduit au problème décrit.

Je travaille avec Alpari. Ils supportent MT4 dans les comptes de démonstration.

Je vais vérifier, si je peux contourner ce comportement, c'est-à-dire utiliser la magie de l'ordre comme identifiant pour la grille et vous faire part des résultats.

Tout en testant cela, j'ai également apporté des modifications au script de nettoyage de la grille. J'ai également ajouté une fonctionnalité permettant de fermer les ordres ouverts. Malheureusement, j'obtiens l'erreur 129, qui signifie "Ordre verrouillé", si j'essaie de fermer un ordre ouvert. Mais il supprime tous les ordres en attente pour la grille donnée.

//+------------------------------------------------------------------+ //| RemoveGrid.mq4 | //| Copyright © 2005, hdb | //| http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, hdb" #property link "http://www.dubois1.net/hdb" extern string GridName = "Grid" ; extern bool closeOpen = false ; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { #property show_inputs // montre les paramètres - merci Slawa... 

//---- int total = OrdersTotal() ; int i ; for(i=total-1 ; i>=0;i--) { OrderSelect(i, SELECT_BY_POS) ; int type = OrderType() ; if ( OrderSymbol()==Symbol() && OrderComment() == GridName ) { bool result = false ; switch(type) { case OP_BUY : if ( closeOpen ) { result = OrderClose( OrderTicket(), OrderLots(), Ask, 0, Blue ) ; } break ; case OP_SELL : if ( closeOpen ) { result = OrderClose( OrderTicket(), OrderLots(), Bid, 0, Blue ) ; } break ; //Fermeture des ordres en attente case OP_BUYLIMIT : result = OrderDelete( OrderTicket() ) ; break ; case OP_BUYSTOP : result = OrderDelete( OrderTicket() ) ; break ; case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ) ; break ; case OP_SELLSTOP : result = OrderDelete( OrderTicket() ) ; break ; } if(result == false) { Print("Order " , OrderTicket() , " failed to close. Erreur :" , GetLastError() ) ; // Sleep(3000) ; } }  
        } } //---- return(0) ; } //+------------------------------------------------------------------+




cori

 
ok cori, merci...

faites-moi savoir si cela fonctionne et j'utiliserai la magie... car je ne savais pas que le courtier faisait des choses aussi étranges !

merci et salutations,

hugues
 
Voilà, c'est fait.

J'ai changé le gridMaker pour utiliser le OrderMagicNumber au lieu du commentaire. J'ai aussi fait quelques petites modifications sur la construction du commentaire.

Voici le résultat.

//+------------------------------------------------------------------+ //| MakeGrid.mq4 | //| Copyright © 2005, hdb | //| http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, hdb" #property link "http://www.dubois1.net/hdb" //#property version "1.4beta" // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille extern int uniqueGridMagic = 11111 ; // Numéro magique des trades. doit être unique pour identifier // les trades d'une grille extern double Lots = 0.1 ; // extern double GridSize = 6 ; // pips entre les ordres - grille ou taille de la maille extern double GridSteps = 12 ; // nombre total d'ordres à placer extern double TakeProfit = 6 ; // nombre de ticks pour prendre le profit. normalement c'est = taille de la grille mais vous pouvez le remplacer extern double StopLoss = 0 ; // si vous voulez ajouter un stop loss. Les grilles normales n'utilisent pas de stop loss. extern double UpdateInterval = 1 ; // Mise à jour des ordres toutes les x minutes extern bool wantLongs = true ; // Nous voulons des positions longues extern bool wantShorts = true ; // Nous voulons des positions courtes extern bool wantBreakout = true ;       // on veut des positions longues au-dessus du prix, des positions courtes en dessous du prix extern bool wantCounter = true ; // on veut des positions longues en dessous du prix, des positions courtes au-dessus du prix extern bool limitEMA34 = false ; // on veut des positions longues au-dessus de l'ema seulement, des positions courtes en dessous de l'ema seulement // modifié par cori. variables internes uniquement double LastUpdate = 0 ; // compteur utilisé pour noter l'heure de la dernière mise à jour double GridMaxOpen = 0 ; // nombre maximum de positions ouvertes string GridName = "Grid" ; // identifie la grille. permet de faire coexister plusieurs grilles //+------------------------------------------------------------------+ //| fonction d'initialisation de l'expert | //+------------------------------------------------------------------+ int init() { //---- #property show_inputs // affiche les paramètres - merci Slawa...    
 if ( TakeProfit <= 0 ) // { TakeProfit = GridSize ; } //---- GridName = StringConcatenate( "Grid", Symbol() ) ; return(0) ;
  } //+------------------------------------------------------------------------+ //| teste s'il y a une position ouverte ou un ordre dans la région de atRate | //| vérifiera les longs si checkLongs est vrai, sinon vérifiera | //| les shorts | //+------------------------------------------------------------------------+ bool IsPosition(double atRate, double inRange, bool checkLongs ) { int totalorders = OrdersTotal() ; for(int j=0;j<totalorders;j++) // analyse tous les ordres et positions... { OrderSelect(j, SELECT_BY_POS) ; // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille if ( OrderSymbol()==Symbol() && OrderMagicNumber() == uniqueGridMagic )  // ne regarde que si mygrid et le symbole... { int type = OrderType() ; if (MathAbs( OrderOpenPrice() - atRate ) < inRange) // ne cherche pas le prix exact mais la proximité du prix (moins que gridsize) { if ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT || type == OP_SELLSTOP ) ) ) { return(true) ; } } } } } 

   return(false) ; } //+------------------------------------------------------------------+ //| fonction de démarrage du programme de script | //+------------------------------------------------------------------+ int start() { //---- int i, j,k, ticket, entermode, totalorders ; bool doit ; double point, startrate, traderate ; //---- if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60) // nous mettons à jour la première fois qu'elle est appelée et toutes les minutes UpdateInterval { LastUpdate = CurTime() ;
   Print("Updating") ; point = MarketInfo(Symbol(),MODE_POINT) ; startrate = ( Ask + point*GridSize/2 ) / point / GridSize ; // arrondir à un nombre de ticks divisible par GridSize k = startrate ; k = k * GridSize ; startrate = k * point - GridSize*GridSteps/2*point ;          // calculer le point d'entrée le plus bas double EMA34=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE,0) ; for( i=0;i<GridSteps;i++) {traderate = startrate + i*point*GridSize ; if ( wantLongs && ( !limitEMA34 || traderate > EMA34)) { if ( IsPosition(traderate,point*GridSize,true) == false )           // test si je n'ai pas d'ordres ouverts proches de mon prix : si oui, en mettre un { double myStopLoss = 0 ; if ( StopLoss > 0 ) { myStopLoss = traderate-point*StopLoss ; } if ( traderate > Ask ) { entermode = OP_BUYSTOP ; } 
              else { entermode = OP_BUYLIMIT ; } 
              
              si ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter))) 

              { // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green) ; } } } if ( wantShorts && (!limitEMA34 || traderate < EMA34)) { if (IsPosition(traderate,point*GridSize,false)== false )           // tester si je n'ai pas d'ordres ouverts proches de mon prix : si oui, en mettre un { myStopLoss = 0 ; if ( StopLoss > 0 ) { myStopLoss = traderate+point*StopLoss ; } if ( traderate > Bid ) { entermode = OP_SELLLIMIT ; } 
              else { entermode = OP_SELLSTOP ; } 
              
              si ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter))) 
               { // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red) ; } } } return(0) ; } //------------------------------------------------------------------+



avec mes respects, cori

 
merci cori...

comme j'avais déjà fait quelques changements moi-même, j'ai intégré tes changements dans la nouvelle version.

J'ai fait une petite variation : afin de garder mes grilles actuelles actives, j'ai mis un test sur magic OR gridname...

pouvez-vous vérifier si je l'ai fait correctement ?



//+------------------------------------------------------------------+ //| MakeGrid.mq4 | //| Copyright © 2005, hdb | //| http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, hdb" #property link "http://www.dubois1.net/hdb" //#property version "1.6beta" // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille extern int uniqueGridMagic = 11111 ; // Numéro magique des trades. doit être unique pour identifier // les trades d'une grille extern double Lots = 0.1 ; // extern double GridSize = 6 ; // pips entre les ordres - grille ou taille de la maille extern double GridSteps = 12 ; // nombre total d'ordres à placer extern double TakeProfit = 12 ; // nombre de ticks pour prendre le profit. normalement c'est = taille de la grille mais vous pouvez le remplacer extern double StopLoss = 0 ; // si vous voulez ajouter un stop loss. Les grilles normales n'utilisent pas de stop loss. extern double UpdateInterval = 1 ; // Mise à jour des ordres toutes les x minutes extern bool wantLongs = true ; // Nous voulons des positions longues extern bool wantShorts = false ; // Nous voulons des positions courtes extern bool wantBreakout = true ;     // nous voulons des positions longues au-dessus du prix, des positions courtes en dessous du prix extern bool wantCounter = true ; // nous voulons des positions longues en dessous du prix, des positions courtes au-dessus du prix extern bool limitEMA34 = true ; // nous voulons des positions longues au-dessus de l'ema uniquement, des positions courtes en dessous de l'ema uniquement extern double GridMaxOpen = 0 ; // nombre maximum de positions ouvertes : pas encore implémenté.. extern bool UseMACD = true ; // si true, utilisera macd >0 pour les longs uniquement, macd >0 pour les shorts uniquement // au croisement, annulera tous les ordres en attente. Ceci annulera tous les paramètres // wantLongs et wantShort - au moins pour le moment. extern bool CloseOpenPositions = false;// si UseMACD, est-ce que nous fermons aussi les positions ouvertes avec une perte ? // modifié par cori. variables internes seulement string GridName = "Grid" ; // identifie la grille. permet plusieurs grilles coexistantes double LastUpdate = 0 ; // compteur utilisé pour noter l'heure de la dernière mise à jour //+------------------------------------------------------------------+ //| fonction d'initialisation de l'expert | //+------------------------------------------------------------------+ int init() { //---- #property show_inputs // montre les paramètres - merci Slawa...    
 if ( TakeProfit <= 0 ) // { TakeProfit = GridSize ; } //---- // ajouté par mon corri et supprimé par hdb !! lol... juste pour rester compatible avec les grilles ouvertes...
// GridName = StringConcatenate( "Grid", Symbol() ) ; return(0) ; } //+------------------------------------------------------------------------+ //| teste s'il y a une position ouverte ou un ordre dans la région de atRate | //| vérifiera les longs si checkLongs est vrai, sinon vérifiera | //| les shorts | //+------------------------------------------------------------------------+ bool IsPosition(double atRate, double inRange, bool checkLongs ) { int totalorders = OrdersTotal() ;
     for(int j=0;j<totalorders;j++) // analyse tous les ordres et positions... { OrderSelect(j, SELECT_BY_POS) ; // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille // hdb ajouté ou gridname pour compatibilité if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // ne regarde que si mygrid et le symbole... { int type = OrderType() ; if (MathAbs( OrderOpenPrice() - atRate ) < inRange) // ne cherche pas le prix exact mais la proximité du prix (moins que gridsize) { if ( ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT || type == OP_SELLSTOP ) ) ) { return(true) ; } } } } } 
   return(false) ; } //+------------------------------------------------------------------------+ //| annule tous les ordres en attente | //+------------------------------------------------------------------------+ void CloseAllPendingOrders( ) { int totalorders = OrdersTotal() ; for(int j=totalorders-1;j>=0;j--) // analyse tous les ordres et positions... { OrderSelect(j, SELECT_BY_POS) ; // modifié selon cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille // hdb ajouté ou gridname pour compatibilité if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // ne regarde que si mygrid et symbol...
         { int type = OrderType() ; bool result = false ; switch(type) { case OP_BUY : result = true ; case OP_SELL : result = true ; //Fermeture des ordres en attente case OP_BUYLIMIT : result = OrderDelete( OrderTicket() ) ; case OP_BUYSTOP : result = OrderDelete( OrderTicket() ) ; case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ) ; case OP_SELLSTOP : result = OrderDelete( OrderTicket() ) ; } } } 
   return ; } //+------------------------------------------------------------------------+ //| annule tous les ordres en attente et ferme les positions ouvertes | //+------------------------------------------------------------------------+ void CloseOpenOrders() { int total = OrdersTotal() ; for(int i=total-1;i>=0;i--) { OrderSelect(i, SELECT_BY_POS) ; int type = OrderType() ; bool result = false ; // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille // hdb ajouté ou gridname pour compatibilité if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // ne regarde que si mygrid et symbol...
     { // Print("Closing 2 ",type) ; switch(type) { //Clôture des positions longues ouvertes case OP_BUY : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 5, Red ) ; break ; //Clôture des positions courtes ouvertes case OP_SELL : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 5, Red ) ; break ; //Fermeture des ordres en attente case OP_BUYLIMIT : case OP_BUYSTOP :
           case OP_SELLLIMIT : case OP_SELLSTOP : result = OrderDelete( OrderTicket() ) ; } } if(result == false) { // Alert("Order " , OrderTicket() , " failed to close. Erreur :" , GetLastError() ) ; // Sleep(3000) ; } }  
  } return ; } //+------------------------------------------------------------------+ //| fonction de démarrage du programme de script | //+------------------------------------------------------------------+ int start() { //---- int i, j,k, ticket, entermode, totalorders ; bool doit ; double point, startrate, traderate ; //---- if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60) // nous mettons à jour la première fois qu'il est appelé et toutes les minutes UpdateInterval { LastUpdate = CurTime() ;
   point = MarketInfo(Symbol(),MODE_POINT) ; startrate = ( Ask + point*GridSize/2 ) / point / GridSize ; // arrondir à un nombre de ticks divisible par GridSize k = startrate ; k = k * GridSize ;
   startrate = k * point - GridSize*GridSteps/2*point ; // calculer le point d'entrée le plus bas double EMA34=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE,0) ; if ( UseMACD ) { double Macd0=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0) ;
      double Macd1=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1) ; double Macd2=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,2) ; if( Macd0>0 && Macd1>0 && Macd2<0) // cross up { CloseAllPendingOrders() ;
         if ( CloseOpenPositions == true ) { CloseOpenOrders() ; } } if( Macd0<0 && Macd1<0 && Macd2>0) // cross down { CloseAllPendingOrders() ; if ( CloseOpenPositions == true ) { CloseOpenOrders() ; } } wantLongs = false ; wantShorts = false ; if( Macd0>0 && Macd1>0 && Macd2>0) // est bien au-dessus de zéro { wantLongs = true ; } if( Macd0<0 && Macd1<0 && Macd2<0) // est bien inférieur à zéro { wantShorts = true ; } } for( i=0;i<GridSteps;i++) { traderate = startrate + i*point*GridSize ; if ( wantLongs && ( !limitEMA34 || traderate > EMA34)) { if ( IsPosition(traderate,point*GridSize,true) == false )           // test si je n'ai pas d'ordres ouverts proches de mon prix : si oui, en mettre un { double myStopLoss = 0 ; if ( StopLoss > 0 ) { myStopLoss = traderate-point*StopLoss ; } if ( traderate > Ask ) { entermode = OP_BUYSTOP ; } 
              else { entermode = OP_BUYLIMIT ; } 
              si ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter))) 
              { // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green) ; } } } if ( wantShorts && (!limitEMA34 || traderate < EMA34)) { if (IsPosition(traderate,point*GridSize,false)== false )           // tester si je n'ai pas d'ordres ouverts proches de mon prix : si oui, en mettre un { myStopLoss = 0 ; if ( StopLoss > 0 ) { myStopLoss = traderate+point*StopLoss ; } if ( traderate > Bid ) { entermode = OP_SELLLIMIT ; } 
              else { entermode = OP_SELLSTOP ; } 
              
              si ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter))) 
                { // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red) ; } } } return(0) ; } //------------------------------------------------------------------+
 
Bonjour hdb,

semble correct. Mais vous devriez définir le GridName comme extern, ce que j'ai changé, car je n'en avais pas besoin comme paramètre.

salutations, cori
 
ATTENTION à tous les utilisateurs de GridMaker - il y a un bug dans la fonction IsPosition - le résultat est que tous les emplacements de la grille ne sont pas remplis.

Vous pouvez modifier la ligne :

if (MathAbs( OrderOpenPrice() - atRate ) < inRange) // ne pas chercher le prix exact mais la proximité du prix (moins que la taille de la grille)

to

if (MathAbs( OrderOpenPrice() - atRate ) < (inRange*0.9)) // ne pas chercher le prix exact mais la proximité du prix (moins que la taille de la grille) - ajouter 0.9 à cause des erreurs de pont flottant


et ceci corrige le problème.

Désolé pour tout inconvénient...

hugues
 
Salut hugues,

Ce problème existe-t-il déjà ?

J'ai trouvé quelque chose de similaire dans l'ancien MQL2.

La façon vraiment sûre de contourner ce problème est de faire quelque chose comme :

int intOOP = MathRound( OrdeOpenPrice() / Point ) ;

pour toutes vos variables doubles. Vous avez alors toutes les variables int droites qui sont comparables sans fautes.

C'est un peu plus à écrire pour que ce soit clair et compréhensible mais c'est moins défectueux.

Avec mes salutations,

cori
 
Tu as raison Cori, c'est beaucoup plus élégant ! C'est juste moi qui suis paresseux !

salutations,
hugues
 
Voici une mise à jour de l'EA GridMaker. Dans cette version, j'ai :

1) modifié la logique pour UseMACD, wantLongs, wantShorts. Auparavant, si useMACD était activé, l'EA prenait les positions longues et courtes, sans tenir compte des drapeaux wantLongs et wantShorts. Maintenant, useMACD ne remplacera pas ces drapeaux, donc vous pouvez être long uniquement avec useMACD ou short uniquement.

2) J'ai ajouté une vérification supplémentaire pour m'assurer qu'il n'y avait pas d'ordres ouverts du mauvais côté de l'EMA si le limitEMA34 était activé. Ce qui se passait, c'est que les ordres étaient bien placés au-dessus ou au-dessous de l'EMA, mais après quelques heures, l'EMA se déplaçait... donc il y avait des ordres des deux côtés de l'EMA.

3) Il semble y avoir un bug dans l'instruction switch sur OrderType(). Je ne suis pas sûr de ce que c'est mais il se comporte vraiment bizarrement. J'ai simplement éliminé les instructions switch et les ai remplacées par "if"... je n'aime pas ça mais ça marche !

4) J'ai rendu la période de l'EMA variable... c'est bien pour le backtesting...

J'ai aussi quelques scripts complémentaires si quelqu'un le souhaite :

1) pour supprimer les ordres ouverts non remplis pour une paire
2) pour supprimer tous les ordres ouverts pour toutes les paires en une seule fois
3) pour clôturer toutes les positions et supprimer les ordres ouverts.
4) pour obtenir quelques statistiques simples sur le comportement de la grille à partir des positions ouvertes et de l'historique.

Voici le code de la V1.08 :


//+------------------------------------------------------------------+ //| MakeGrid.mq4 | //| Copyright © 2005, hdb | //|
http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, hdb" #property link "http://www.dubois1.net/hdb" //#property version "1.8" // DISCLAIMER ***** IMPORTANT NOTE ***** LIRE AVANT D'UTILISER ***** // Ce conseiller expert peut ouvrir et fermer des positions réelles et donc faire des transactions réelles et perdre de l'argent réel.
// L'auteur n'a aucune prétention quant à la rentabilité de ce système et ne suggère pas l'utilisation de cet EA autrement qu'à des fins de test dans des comptes de démonstration. // L'utilisation de ce système est gratuite - mais vous n'êtes pas autorisé à le revendre - et sans aucune garantie quant à son // adéquation à un quelconque objectif.
// En utilisant ce programme, vous reconnaissez implicitement que vous comprenez ce qu'il fait et acceptez que // l'auteur ne porte aucune responsabilité pour les pertes éventuelles. // Avant de l'utiliser, veuillez également vérifier auprès de votre courtier que ses systèmes sont adaptés aux transactions les plus fréquentes // associées à cet expert. // Les modifications de la version 1.8 // ont fait de wantLongs et wantShorts des variables locales. Auparavant, si vous définissiez UseMACD à true, // il faisait des longs et des shorts et ignorait simplement les drapeaux wantLongs et wantShorts. 
// Maintenant, ces drapeaux ne sont pas ignorés. // Ajout d'une boucle pour vérifier s'il y a des ordres ouverts "illicites" au-dessus ou en dessous de l'EMA lorsque le drapeau limitEMA34 // est utilisé. Ceux-ci s'accumulent au fil du temps et ne sont jamais supprimés, ce qui est dû au déplacement de l'EMA. // Suppression des instructions de commutation car elles ne semblent pas fonctionner - remplacées par des instructions if // Modification de la variable de période de l'EMA // // par Cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille extern int uniqueGridMagic = 11111 ; // Numéro magique des trades. doit être unique pour identifier // les trades d'une grille extern double Lots = 0.1 ; // extern double GridSize = 6 ; // pips entre les ordres - grille ou taille de la maille extern double GridSteps = 12 ; // nombre total d'ordres à placer extern double TakeProfit = 12 ; // nombre de ticks pour prendre le profit. normalement c'est = taille de la grille mais vous pouvez le remplacer extern double StopLoss = 0 ; // si vous voulez ajouter un stop loss. Les grilles normales n'utilisent pas de stop loss. extern double UpdateInterval = 1 ; // Mise à jour des ordres toutes les x minutes extern bool wantLongs = true ; // Nous voulons des positions longues extern bool wantShorts = true ; // Nous voulons des positions courtes extern bool wantBreakout = true ;     // nous voulons des positions longues au-dessus du prix, des positions courtes en dessous du prix extern bool wantCounter = true ; // nous voulons des positions longues en dessous du prix, des positions courtes au-dessus du prix extern bool limitEMA = true ; // nous voulons des positions longues au-dessus de l'ema uniquement, des positions courtes en dessous de l'ema uniquement extern int EMAperiod = 34 ; // la longueur de l'EMA.. était précédemment fixée à 34 extern double GridMaxOpen = 0 ; // nombre maximum de positions ouvertes : pas encore implémenté... extern bool UseMACD = true ; // si true, utilisera macd >0 pour les longs uniquement, macd >0 pour les shorts uniquement // lors du croisement, annulera tous les ordres en attente. Ceci annulera tous les paramètres // wantLongs et wantShort - au moins pour le moment. extern bool CloseOpenPositions = false ; // si UseMACD, est-ce que nous fermons aussi les positions ouvertes avec une perte ? extern bool doHouseKeeping = true ; // juste un test // modifié par cori. variables internes seulement string GridName = "Grid" ; // identifie la grille. permet de faire coexister plusieurs grilles double LastUpdate = 0 ; // compteur utilisé pour noter l'heure de la dernière mise à jour //+------------------------------------------------------------------+ //| fonction d'initialisation de l'expert | //+------------------------------------------------------------------+ int init() { //---- #property show_inputs // montre les paramètres - merci Slawa...    
//---- // ajouté par mon corri et supprimé par hdb !! lol... juste pour rester compatible avec les grilles ouvertes...
// GridName = StringConcatenate( "Grid", Symbol() ) ; return(0) ; } //+------------------------------------------------------------------------+ //| teste s'il y a une position ouverte ou un ordre dans la région de atRate | //| vérifiera les longs si checkLongs est vrai, sinon vérifiera | //| les shorts | //+------------------------------------------------------------------------+ bool IsPosition(double atRate, double inRange, bool checkLongs ) { int totalorders = OrdersTotal() ;
     for(int j=0;j<totalorders;j++) // analyse tous les ordres et positions... { OrderSelect(j, SELECT_BY_POS) ; // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille // hdb ajouté ou gridname pour compatibilité if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // ne cherche que si mygrid et symbol... { int type = OrderType() ; if (MathAbs( OrderOpenPrice() - atRate ) < (inRange*0.9)) // ne pas chercher le prix exact mais la proximité du prix (moins que gridsize) - ajouté 0.9 à cause des erreurs de virgule flottante { if ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT || type == OP_SELLSTOP ) ) ) { return(true) ; } } } } } 
   return(false) ; } //+------------------------------------------------------------------------+ //| annule tous les ordres en attente | //+------------------------------------------------------------------------+ void CloseAllPendingOrders( ) { int totalorders = OrdersTotal() ; for(int j=totalorders-1;j>=0;j--) // analyse tous les ordres et positions... { OrderSelect(j, SELECT_BY_POS) ; // modifié selon cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille // hdb ajouté ou gridname pour compatibilité if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // ne regarde que si mygrid et symbol... { int type = OrderType() ; if ( type > 1 ) bool result = OrderDelete( OrderTicket() ) ; } } 
   return ; } //+------------------------------------------------------------------------+ //| annule tous les ordres en attente et ferme les positions ouvertes | //+------------------------------------------------------------------------+ void CloseOpenOrders() { int total = OrdersTotal() ; for(int i=total-1;i>=0;i--) { OrderSelect(i, SELECT_BY_POS) ; int type = OrderType() ; bool result = false ; // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille // hdb ajouté ou gridname pour compatibilité if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // Ne regarde que si mygrid et symbol...
     { //Fermeture des positions longues ouvertes si ( type == OP_BUY ) result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 5, Red ) ;
           //Clore les positions courtes ouvertes si ( type == OP_SELL ) result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 5, Red ) ; //Clore les ordres en attente si ( type > 1 ) result = OrderDelete( OrderTicket() ) ; } } return ;
} //+------------------------------------------------------------------------+ //| annule tous les ordres ouverts qui tombent du mauvais côté de l'EMA | //+------------------------------------------------------------------------+ void CloseOrdersfromEMA( double theEMAValue ) { int totalorders = OrdersTotal() ; for(int j=totalorders-1;j>=0;j--) // analyse tous les ordres et positions... { OrderSelect(j, SELECT_BY_POS) ; if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // ne regarde que si mygrid et symbol...
         { int type = OrderType() ; bool result = false ; //si (type > 1) Print(type," ",theEMAValue," ",OrderOpenPrice()) ; if ( type == OP_BUYLIMIT && OrderOpenPrice() <= theEMAValue ) result = OrderDelete( OrderTicket() ) ; if ( type == OP_BUYSTOP && orderOpenPrice() <= theEMAValue ) result = OrderDelete( OrderTicket() ) ; if ( type == OP_SELLLIMIT && orderOpenPrice() >= theEMAValue ) result = OrderDelete( OrderTicket() ) ; if ( type == OP_SELLSTOP && orderOpenPrice() >= theEMAValue ) result = OrderDelete( OrderTicket() ) ; } } 
   return ; } //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { //---- int i, j,k, ticket, entermode, totalorders ; bool doit ; double point, startrate, traderate ; //---- setup parameters if ( TakeProfit <= 0 ) // { TakeProfit = GridSize ; } bool myWantLongs = wantLongs ;
 bool myWantShorts = wantShorts ; //---- if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60) // nous mettons à jour la première fois qu'il est appelé et toutes les minutes UpdateInterval { LastUpdate = CurTime() ;
   point = MarketInfo(Symbol(),MODE_POINT) ; startrate = ( Ask + point*GridSize/2 ) / point / GridSize ; // arrondir à un nombre de ticks divisible par GridSize k = startrate ; k = k * GridSize ; startrate = k * point - GridSize*GridSteps/2*point ;          // calculer le point d'entrée le plus bas double myEMA=iMA(NULL,0,EMAperiod,0,MODE_EMA,PRICE_CLOSE,0) ; if (limitEMA) { if (doHouseKeeping) CloseOrdersfromEMA(myEMA) ; } if ( UseMACD ) { double Macd0=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0) ;
      double Macd1=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1) ; double Macd2=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,2) ; if( Macd0>0 && Macd1>0 && Macd2<0) // cross up { CloseAllPendingOrders() ; if ( CloseOpenPositions == true ) { CloseOpenOrders() ; } } if( Macd0<0 && Macd1<0 && Macd2>0) // cross down { CloseAllPendingOrders() ;
         if ( CloseOpenPositions == true ) { CloseOpenOrders() ; } } myWantLongs = false ; myWantShorts = false ; if( Macd0>0 && Macd1>0 && Macd2>0 && wantLongs )     // est bien au-dessus de zéro { myWantLongs = true ; } if( Macd0<0 && Macd1<0 && Macd2<0 && wantShorts )     // est bien inférieur à zéro { myWantShorts = true ; } } for( i=0;i<GridSteps;i++) { traderate = startrate + i*point*GridSize ; if ( myWantLongs && (!limitEMA || traderate > myEMA)) { if ( IsPosition(traderate,point*GridSize,true) == false )           // test si je n'ai pas d'ordres ouverts proches de mon prix : si oui, en mettre un { double myStopLoss = 0 ; if ( StopLoss > 0 ) { myStopLoss = traderate-point*StopLoss ; } if ( traderate > Ask ) { entermode = OP_BUYSTOP ; } 
              else { entermode = OP_BUYLIMIT ; } 
              si ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter))) 
              { // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green) ; } } } if ( myWantShorts && (!limitEMA || traderate < myEMA)) { if (IsPosition(traderate,point*GridSize,false)== false )           // tester si je n'ai pas d'ordres ouverts proches de mon prix : si oui, en mettre un { myStopLoss = 0 ; if ( StopLoss > 0 ) { myStopLoss = traderate+point*StopLoss ; } if ( traderate > Bid ) { entermode = OP_SELLLIMIT ; } 
              else { entermode = OP_SELLSTOP ; } 
              
              si ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter))) 
                { // modifié par cori. Utilisation de OrderMagicNumber pour identifier les trades de la grille ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red) ; } } } return(0) ; } //------------------------------------------------------------------+