English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Développer un Expert Advisor de trading à partir de zéro

Développer un Expert Advisor de trading à partir de zéro

MetaTrader 5Trading | 4 mai 2022, 12:25
1 594 5
Daniel Jose
Daniel Jose

Introduction

Le nombre de nouveaux utilisateurs sur le marché financier augmente. Peut-être que beaucoup d'entre eux ne savent même pas comment fonctionne le système d'ordres. Cependant, il y a aussi les utilisateurs qui veulent vraiment savoir ce qui se passe. Ils essaient de comprendre comment tout cela fonctionne afin de contrôler la situation.

Bien sûr, MetaTrader 5 offre un haut niveau de contrôle sur les positions de trading. Cependant, utiliser uniquement la capacité manuelle pour passer des ordres peut être assez difficile et risqué pour les utilisateurs moins expérimentés. De plus, si quelqu'un veut négocier des contrats à terme, alors qu'il y a très peu de temps pour passer un ordre, un tel trading peut se transformer en cauchemar, car vous devez remplir correctement tous les champs en temps opportun, mais cela prend encore du temps et donc vous pouvez manquer de bonnes opportunités ou même perdre de l'argent si quelque chose n'est pas rempli correctement.

Maintenant, et si nous faisions appel à un Expert Advisor (EA) pour faciliter les choses ? Dans ce cas, vous pouvez spécifier certains détails, par exemple l'effet de levier ou combien vous pouvez vous permettre de perdre et combien vous voulez gagner (en termes monétaires, plutôt qu'en "points" ou "pips" pas tout à fait clairs). Ensuite, utilisez le pointeur de la souris sur le graphique pour montrer où entrer sur le marché et indiquer s'il s'agira d'acheter ou de vendre...


Planning

La partie la plus difficile dans la création de quelque chose est de comprendre comment les choses devraient fonctionner. L'idée doit être formulée très clairement afin que nous devions créer le code minimum requis, car plus le code à créer est complexe, plus la possibilité d'erreurs d'exécution est grande. Avec ceci en tête, j'ai essayé de rendre le code assez simple mais en utilisant toujours le maximum des possibilités offertes par MetaTrader 5. La plateforme est très fiable, elle est constamment testée et il ne peut donc pas y avoir d'erreurs côté plateforme.

Le code utilisera la POO (programmation orientée objet). Cette approche permet d'isoler le code et facilite sa maintenance et son développement futur, au cas où nous voudrions ajouter de nouvelles fonctionnalités et apporter des améliorations.

Bien que l'EA dont il est question dans cet article soit conçu pour le trading sur B3 (Brazilian Exchange) et spécifiquement pour le trading de contrats à terme (Mini Index et Mini Dollar), il peut être étendu à tous les marchés avec un minimum de modifications. Pour faciliter les choses et non pour lister ou vérifier les actifs de trading, nous utiliserons l'énumération suivante :

enum eTypeSymbolFast {WIN, WDO, OTHER};


Si vous souhaitez trader un autre actif, qui utilise une fonctionnalité spéciale, ajoutez-le à l'énumération. Cela nécessitera également de petits changements dans le code, mais avec l'énumération, cela sera beaucoup plus facile car cela réduit également la possibilité d'erreurs. Une partie intéressante du code est la fonction AdjustPrice :

   double AdjustPrice(const double arg)
     {
      double v0, v1;
      if(m_Infos.TypeSymbol == OTHER)
         return arg;
      v0 = (m_Infos.TypeSymbol == WDO ? round(arg * 10.0) : round(arg));
      v1 = fmod(round(v0), 5.0);
      v0 -= ((v1 != 0) || (v1 != 5) ? v1 : 0);
      return (m_Infos.TypeSymbol == WDO ? v0 / 10.0 : v0);
     };

Cette fonction ajustera la valeur à utiliser dans le prix, afin de positionner les lignes à des points précis du graphique. Pourquoi ne pouvons-nous pas simplement mettre une ligne sur le graphique ? En effet, certains actifs ont certains pas entre les prix. Pour WDO (Mini Dollar), ce pas n'est que de 0,5 point. Pour WIN (Mini Index), ce pas est de 5 points et pour les actions, il est de 0,01 point. En d'autres termes, les valeurs en points diffèrent pour différents actifs. Cela ajuste le prix à la valeur correcte du tick afin qu'une valeur appropriée soit utilisée dans l'ordre, sinon un ordre mal exécuté peut être rejeté par le serveur.

Sans cette fonction, il peut être difficile de connaître les valeurs correctes à utiliser dans l'ordre. Et ainsi, il y a une chance pour le serveur de notifier que l'ordre est rempli de manière incorrecte et d'empêcher son exécution. Passons maintenant à la fonction qui est au cœur de l'Expert Advisor : CreateOrderPendent. La fonction est la suivante :

   ulong CreateOrderPendent(const bool IsBuy, const double Volume, const double Price, const double Take, const double Stop, const bool DayTrade = true)
     {
      double last = SymbolInfoDouble(m_szSymbol, SYMBOL_LAST);
      ZeroMemory(TradeRequest);
      ZeroMemory(TradeResult);
      TradeRequest.action        = TRADE_ACTION_PENDING;
      TradeRequest.symbol        = m_szSymbol;
      TradeRequest.volume        = Volume;
      TradeRequest.type          = (IsBuy ? (last >= Price ? ORDER_TYPE_BUY_LIMIT : ORDER_TYPE_BUY_STOP) : (last < Price ? ORDER_TYPE_SELL_LIMIT : ORDER_TYPE_SELL_STOP));
      TradeRequest.price         = NormalizeDouble(Price, m_Infos.nDigits);
      TradeRequest.sl            = NormalizeDouble(Stop, m_Infos.nDigits);
      TradeRequest.tp            = NormalizeDouble(Take, m_Infos.nDigits);
      TradeRequest.type_time     = (DayTrade ? ORDER_TIME_DAY : ORDER_TIME_GTC);
      TradeRequest.stoplimit     = 0;
      TradeRequest.expiration    = 0;
      TradeRequest.type_filling  = ORDER_FILLING_RETURN;
      TradeRequest.deviation     = 1000;
      TradeRequest.comment       = "Order Generated by Experts Advisor.";
      if(!OrderSend(TradeRequest, TradeResult))
        {
         MessageBox(StringFormat("Error Number: %d", TradeResult.retcode), "Nano EA");
         return 0;
        };
      return TradeResult.order;
     };

Cette fonction est très simple et est conçue pour être sûre. Nous allons créer ici un ordre OCO (One Cancels the Other), qui sera envoyé au serveur de trading. Veuillez noter que nous utilisons des ordres LIMIT ou STOP. En effet, ce type d'ordres est plus simple et son exécution est garantie même en cas de mouvements brusques des cours.

Le type d'ordre à utiliser dépend du prix d'exécution et du prix actuel de l'instrument de trading, ainsi que du fait que vous entrez une position d'achat ou de vente. Ceci est implémenté dans la ligne suivante :

TradeRequest.type = (IsBuy ? (last >= Price ? ORDER_TYPE_BUY_LIMIT : ORDER_TYPE_BUY_STOP) : (last < Price ? ORDER_TYPE_SELL_LIMIT : ORDER_TYPE_SELL_STOP));

Il est également possible de créer un CROSS ORDER, en spécifiant un instrument de trading dans la ligne suivante :

TradeRequest.symbol = m_szSymbol;

Mais ce faisant, vous devrez également ajouter du code afin de gérer les ordres ouverts ou en attente via le système CROSS ORDER, car vous aurez un "mauvais" graphique. Voyons un exemple. Vous pouvez être sur le graphique de l'indice complet (IND) et trader le Mini Index (WIN), mais MetaTrader 5 n'affichera pas l'ordre WIN ouvert ou en attente lorsque vous l'utilisez sur le graphique IND. Il est donc nécessaire d'ajouter un code afin de rendre les commandes visibles. Cela peut être fait en lisant les valeurs de position et en les présentant sous forme de lignes sur le graphique. Ceci est très utile lorsque vous tradez et suivez l'historique de trading des symboles. Lorsque vous utilisez, par exemple, CROSS ORDER, vous pouvez trader WIN (Mini Index) en utilisant le graphique WIN$ (le graphique de l'historique du Mini Index).

Ensuite, veuillez prêter attention aux lignes de code suivantes :

      TradeRequest.price         = NormalizeDouble(Price, m_Infos.nDigits);
      TradeRequest.sl            = NormalizeDouble(Stop, m_Infos.nDigits);
      TradeRequest.tp            = NormalizeDouble(Take, m_Infos.nDigits);

Ces 3 lignes créeront les niveaux d'arrêt d'ordre OCO et le prix d'ouverture de la position. Si vous tradez des ordres à court terme, qui peuvent ne durer que quelques secondes, il n'est pas conseillé d'entrer dans le trade sans utiliser les ordres OCO, car la volatilité peut faire passer le prix d'un point à un autre sans direction claire. Lorsque vous utilisez OCO, le serveur de trading lui-même s'occupera de notre position. L'ordre OCO apparaîtra comme suit.

Dans la fenêtre d'édition, le même ordre se présentera comme suit :

Une fois que vous aurez rempli tous les champs obligatoires, le serveur gérera l'ordre. Dès qu'il atteint soit Max Profit ou Max Loss, le système fermera l'ordre. Mais si vous ne spécifiez pas Max Profit ou Max Loss, l'ordre peut rester ouvert jusqu'à ce qu'un autre événement se produise. Si le type d'ordre est défini sur Day Trade, le système le clôturera à la fin de la journée de trading. Sinon, la position restera ouverte jusqu'à ce que vous la fermiez manuellement ou jusqu'à ce qu'il n'y ait plus de fonds pour maintenir la position ouverte.

Certains systèmes Expert Advisor utilisent des ordres pour fermer des positions : une fois qu'une position est ouverte, un ordre opposé pour fermer la position au point spécifié, avec le même volume, est envoyé. Mais cela peut ne pas fonctionner dans certains scénarios, car si l'actif est mis aux enchères pendant la session pour une raison quelconque, l'ordre en attente peut être annulé et doit être remplacé. Cela compliquerait l'opération de l'EA, car vous auriez besoin d'ajouter des vérifications pour quels ordres sont actifs et lesquels ne le sont pas, et si quelque chose ne va pas, l'EA enverrait des ordres les uns après les autres, sans aucun critère.

   void Initilize(int nContracts, int FinanceTake, int FinanceStop, color cp, color ct, color cs, bool b1)
     {
      string sz0 = StringSubstr(m_szSymbol = _Symbol, 0, 3);
      double v1 = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE) / SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
      m_Infos.Id = ChartID();
      m_Infos.TypeSymbol = ((sz0 == "WDO") || (sz0 == "DOL") ? WDO : ((sz0 == "WIN") || (sz0 == "IND") ? WIN : OTHER));
      m_Infos.nDigits = (int) SymbolInfoInteger(m_szSymbol, SYMBOL_DIGITS);
      m_Infos.Volume = nContracts * (m_VolMinimal = SymbolInfoDouble(m_szSymbol, SYMBOL_VOLUME_MIN));
      m_Infos.TakeProfit = AdjustPrice(FinanceTake * v1 / m_Infos.Volume);
      m_Infos.StopLoss = AdjustPrice(FinanceStop * v1 / m_Infos.Volume);
      m_Infos.IsDayTrade = b1;
      CreateHLine(m_Infos.szHLinePrice, m_Infos.cPrice = cp);
      CreateHLine(m_Infos.szHLineTake, m_Infos.cTake = ct);
      CreateHLine(m_Infos.szHLineStop, m_Infos.cStop = cs);
      ChartSetInteger(m_Infos.Id, CHART_COLOR_VOLUME, m_Infos.cPrice);
      ChartSetInteger(m_Infos.Id, CHART_COLOR_STOP_LEVEL, m_Infos.cStop);
     };

La routine ci-dessus est responsable de l'initiation des données de l'EA comme indiqué par l'utilisateur - elle crée un ordre OCO. Nous avons seulement besoin de faire le changement suivant dans cette routine.

m_Infos.TypeSymbol = ((sz0 == "WDO") || (sz0 == "DOL") ? WDO : ((sz0 == "WIN") || (sz0 == "IND") ? WIN : OTHER));

Ici, nous ajoutons le type de symbole de trading en plus des symboles actuels, si vous avez besoin de quelque chose de spécifique.

      m_Infos.Volume = nContracts * (m_VolMinimal = SymbolInfoDouble(m_szSymbol, SYMBOL_VOLUME_MIN));
      m_Infos.TakeProfit = AdjustPrice(FinanceTake * v1 / m_Infos.Volume);
      m_Infos.StopLoss = AdjustPrice(FinanceStop * v1 / m_Infos.Volume);

Les trois lignes ci-dessus effectuent les ajustements nécessaires pour la création correcte de l'ordre. nContracts est un facteur de levier, utilisez des valeurs comme 1, 2, 3 etc. En d'autres termes, vous n'avez pas besoin de connaître le volume minimum de symboles à trader. Tout ce dont vous avez vraiment besoin est d'indiquer le facteur de levier de ce volume minimum. Par exemple, si le volume minimum requis est de 5 contrats et que vous spécifiez un facteur de levier de 3, le système ouvrira un ordre de 15 contrats. Les deux autres lignes définissent en conséquence le Take Profit et le Stop Loss, en fonction des paramètres spécifiés par l'utilisateur. Les niveaux sont ajustés avec le volume de l'ordre : si l'ordre augmente, le niveau diminue et vice versa. Avec ce code, vous n'aurez pas à faire de calculs pour créer une position - l'EA calculera tout lui-même : vous indiquerez à l'EA quel instrument financier négocier avec quel facteur de levier, combien d'argent vous voulez gagner et êtes prêt à perdre, et l'EA passera un ordre approprié pour vous.

   inline void MoveTo(int X, int Y, uint Key)
     {
      int w = 0;
      datetime dt;
      bool bEClick, bKeyBuy, bKeySell;
      double take = 0, stop = 0, price;
      bEClick  = (Key & 0x01) == 0x01;    //Left mouse button click
      bKeyBuy  = (Key & 0x04) == 0x04;    //Pressed SHIFT
      bKeySell = (Key & 0x08) == 0x08;    //Pressed CTRL
      ChartXYToTimePrice(m_Infos.Id, X, Y, w, dt, price);
      ObjectMove(m_Infos.Id, m_Infos.szHLinePrice, 0, 0, price = (bKeyBuy != bKeySell ? AdjustPrice(price) : 0));
      ObjectMove(m_Infos.Id, m_Infos.szHLineTake, 0, 0, take = price + (m_Infos.TakeProfit * (bKeyBuy ? 1 : -1)));
      ObjectMove(m_Infos.Id, m_Infos.szHLineStop, 0, 0, stop = price + (m_Infos.StopLoss * (bKeyBuy ? -1 : 1)));
      if((bEClick) && (bKeyBuy != bKeySell))
         CreateOrderPendent(bKeyBuy, m_Infos.Volume, price, take, stop, m_Infos.IsDayTrade);
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLinePrice, OBJPROP_COLOR, (bKeyBuy != bKeySell ? m_Infos.cPrice : clrNONE));
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLineTake, OBJPROP_COLOR, (take > 0 ? m_Infos.cTake : clrNONE));
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLineStop, OBJPROP_COLOR, (stop > 0 ? m_Infos.cStop : clrNONE));
     };

Le code ci-dessus présentera l'ordre à créer. Il utilise le mouvement de la souris pour montrer où l'ordre sera passé. Mais vous souhaitez informer l'EA si vous souhaitez acheter (maintenez la touche MAJ enfoncée) ou vendre (maintenez la touche CTRL enfoncée). Une fois que vous avez cliqué sur le bouton gauche de la souris, un ordre en attente sera créé à ce stade.

Si vous avez besoin de plus de données à afficher, par exemple le seuil de rentabilité, ajoutez l'objet correspondant au code.

Maintenant, nous avons tout un EA qui fonctionne et peut créer des ordres OCO. Mais tout n'est pas parfait ici...


Problème avec les ordres OCO

Les ordres OCO ont un problème, qui n'est pas de la faute du système MetaTrader 5 ou du serveur de trading. Il est lié à la volatilité elle-même qui est constamment présente sur le marché. Théoriquement, le prix devrait évoluer de manière linéaire, sans recul, mais nous avons parfois une forte volatilité, ce qui crée des écarts à l'intérieur d'un chandelier. Lorsque ces écarts se produisent au point où se situe le prix de l'ordre Stop Loss ou Take Profit, ces points ne se déclencheront pas et, par conséquent, la position ne sera pas fermée. Il peut également arriver que lorsque l'utilisateur déplace ces points, le prix puisse être au-delà du corridor formé par le stop loss et le take profit. Dans ce cas, l'ordre ne sera pas fermé non plus. C'est une situation très dangereuse qui est impossible à prévoir. En tant que programmeur, vous devez fournir un mécanisme pertinent pour minimiser les dommages possibles.

Pour rafraîchir le prix et essayer de le maintenir dans le corridor, nous utiliserons deux sous-programmes. Le premier est le suivant :

   void UpdatePosition(void)
     {
      for(int i0 = PositionsTotal() - 1; i0 >= 0; i0--)
         if(PositionGetSymbol(i0) == m_szSymbol)
           {
            m_Take      = PositionGetDouble(POSITION_TP);
            m_Stop      = PositionGetDouble(POSITION_SL);
            m_IsBuy     = PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY;
            m_Volume    = PositionGetDouble(POSITION_VOLUME);
            m_Ticket    = PositionGetInteger(POSITION_TICKET);
           }
     };

Il sera appelé dans la fonction OnTrade - la fonction appelée par MetaTrader 5 à chaque changement de position. Le sous-programme suivant à utiliser est appelé par OnTick. Il vérifie et s'assure que le prix est dans le corridor ou dans les limites de l'ordre OCO. C'est comme suit :

   inline bool CheckPosition(const double price = 0, const int factor = 0)
     {
      double last;
      if(m_Ticket == 0)
         return false;
      last = SymbolInfoDouble(m_szSymbol, SYMBOL_LAST);
      if(m_IsBuy)
        {
         if((last > m_Take) || (last < m_Stop))
            return ClosePosition();
         if((price > 0) && (price >= last))
            return ClosePosition(factor);
        }
      else
        {
         if((last < m_Take) || (last > m_Stop))
            return ClosePosition();
         if((price > 0) && (price <= last))
            return ClosePosition(factor);
        }
      return false;
     };

Ce fragment de code est essentiel car il sera exécuté à chaque changement de tick et il doit donc être aussi simple que possible afin que les calculs et les tests soient effectués le plus efficacement possible. Veuillez noter que pendant que nous maintenons le prix à l'intérieur du couloir, nous vérifions également quelque chose d'intéressant, qui peut être supprimé si vous le souhaitez. J'expliquerai ce test supplémentaire dans la section suivante. À l'intérieur de ce sous-programme, nous avons l'appel de fonction suivant :

   bool ClosePosition(const int arg = 0)
     {
      double v1 = arg * m_VolMinimal;
      if(!PositionSelectByTicket(m_Ticket))
         return false;
      ZeroMemory(TradeRequest);
      ZeroMemory(TradeResult);
      TradeRequest.action     = TRADE_ACTION_DEAL;
      TradeRequest.type       = (m_IsBuy ? ORDER_TYPE_SELL : ORDER_TYPE_BUY);
      TradeRequest.price      = SymbolInfoDouble(m_szSymbol, (m_IsBuy ? SYMBOL_BID : SYMBOL_ASK));
      TradeRequest.position   = m_Ticket;
      TradeRequest.symbol     = m_szSymbol;
      TradeRequest.volume     = ((v1 == 0) || (v1 > m_Volume) ? m_Volume : v1);
      TradeRequest.deviation  = 1000;
      if(!OrderSend(TradeRequest, TradeResult))
        {
         MessageBox(StringFormat("Error Number: %d", TradeResult.retcode), "Nano EA");
         return false;
        }
      else
         m_Ticket = 0;
      return true;
     };

La fonction fermera le volume spécifié et fonctionnera comme une protection. Cependant, n'oubliez pas que vous devez être connecté, car la fonction s'exécute dans le terminal client MetaTrader 5 - si la connexion au serveur échoue, cette fonction sera complètement inutile.

En regardant ces deux derniers codes, nous pouvons voir que nous pouvons terminer le volume donné à un certain point. En faisant cela, soit nous procédons à une fermeture partielle, soit nous réduisons notre exposition. Voyons comment utiliser cette fonction.


Travailler avec des ordres partiels


Les ordres partiels sont quelque chose que de nombreux traders aiment et utilisent. L'Expert Advisor permet de travailler avec une fermeture partielle, mais je ne montrerai pas comment implémenter un tel code, car les ordres partiels devraient faire l'objet d'un problème séparé. Cependant, si vous souhaitez mettre en œuvre un travail avec des fermetures partielles, appelez simplement la routine CheckPosition et spécifiez le prix auquel l'ordre sera exécuté et le volume, tandis que l'EA fais le reste.

Je dis que les ordres partiels sont un cas particulier car ils sont très individuels et il est difficile de créer une solution généralisée pour satisfaire tout le monde. L'utilisation d'un tableau dynamique ne conviendrait pas ici, car vous pourriez vous balancer - cela ne fonctionnera pour le day trading que si vous ne fermez pas l'EA. Si vous devez fermer l'EA pour une raison quelconque, la solution du tableau ne fonctionnera pas. Vous aurez besoin d'utiliser un support de stockage, dans lequel le formatage des données dépendra de ce que vous allez faire avec ces données.

Quoi qu'il en soit, vous devez éviter autant que possible les fermetures partielles en utilisant l'ordre d'ouverture de position, car le risque d'avoir mal à la tête est énorme. Laissez-moi vous expliquer : supposons que vous ayez une position d'achat à effet de levier de 3x et que vous souhaitiez réaliser un profit avec 2x tout en conservant une position à effet de levier de 1x. Cela peut être fait en vendant un effet de levier 2x. Cependant, si votre EA envoie un ordre de vente au marché, il peut arriver que la volatilité fasse monter le prix et atteigne votre Take Profit avant que l'ordre de vente ne soit réellement exécuté. Dans ce cas, l'EA ouvrira une nouvelle position courte dans la direction défavorable. Optionnellement, vous pouvez envoyer un Sell Limit ou Sell Stop pour réduire la position du levier 2x. Cela peut sembler une solution adéquate. Mais que se passe-t-il si un autre ordre est envoyé avant que le prix n'atteigne le point partiel - vous pouvez avoir une très mauvaise surprise : la position ouverte sera arrêtée et un peu plus tard, l'ordre redeviendra ouvert et augmentera les pertes. Si la volatilité devient plus forte, la situation deviendra la même que celle mentionnée ci-dessus.

Donc, à mon avis, en tant que programmeur, la meilleure option pour passer des ordres partiels est d'émuler l'envoi des ordres au prix du marché. Mais vous devez faire très attention à ne pas dépasser le volume ouvert. Dans cet EA, je l'ai fait exactement de cette façon. Si vous le souhaitez, vous pouvez implémenter d'autres méthodes de fermeture partielle.


Conclusion

Créer un Expert Advisor pour le trading n'est pas aussi simple que certains le pensent ; c'est assez simple par rapport à certains des autres problèmes auxquels nous sommes souvent confrontés lors de la programmation, mais construire quelque chose de suffisamment stable et fiable pour risquer votre argent est une tâche souvent difficile. Dans cet article, j'ai suggéré quelque chose qui peut faciliter la vie de ceux qui commencent à utiliser MetaTrader 5 et qui n'ont pas les connaissances nécessaires pour programmer un EA. C'est un bon début, car cet EA n'ouvre pas les ordres mais aide seulement à ouvrir les ordres de manière plus fiable. Une fois l'ordre passé, l'EA n'a plus rien à faire et MetaTrader 5 commence à fonctionner, à l'exception des fragments de code mentionnés ci-dessus.

L'Expert Advisor présenté dans cet article peut être amélioré de diverses manières pour travailler avec des ensembles de paramètres, mais cela nécessiterait plus de code qui le rendra plus indépendant de MetaTrader 5.

Le grand succès de cet EA est qu'il utilise MetaTrader 5 lui-même pour effectuer des actions qui ne sont pas dans son code, et donc il est extrêmement stable et fiable.





Traduit du portugais par MetaQuotes Ltd.
Article original : https://www.mql5.com/pt/articles/10085

Fichiers joints |
EA_Nano_rvl_1.1.mq5 (23.44 KB)
Derniers commentaires | Aller à la discussion (5)
Feresther
Feresther | 18 déc. 2021 à 16:35

Bonjour,

Très bien, mais je n'ai pas compris une chose. Lorsque je place l'ordre dans WIN et WDO l'EA ouvre 6 ordres avec le nombre de contrats que j'ai inséré dans "leverage". Donc même si je veux fonctionner avec 1 contrat, je ne peux pas, il en ouvre 6.

Est-ce un concept qui est passé inaperçu pour moi ? Je suis un débutant, donc je pars de cette prémisse.

Merci beaucoup pour ce partage.

joecafrois
joecafrois | 21 déc. 2021 à 17:50
Si je comprends bien, il faut avoir des connaissances en "Algo Trading" pour travailler avec lui...
[Supprimé] | 21 déc. 2021 à 21:35
Très bien !
Daniel Jose
Daniel Jose | 25 déc. 2021 à 11:04
joecafrois #:
Je comprends que vous devez avoir des connaissances en Algo Trading pour travailler avec lui...

Vous n'avez pas besoin d'avoir des connaissances en AlgoTrading ... mais il doit être activé chaque fois que vous allez utiliser un EA (Expert Advisor), sinon l'EA voit son fonctionnement limité.

Daniel Jose
Daniel Jose | 25 déc. 2021 à 11:28
Feresther nombre de contrats que j'ai inséré dans "leverage". Donc même si je veux négocier avec 1 contrat, je ne peux pas, il en ouvre 6.

Est-ce un concept qui est passé inaperçu pour moi ? Je suis un débutant, donc je pars de cette prémisse.

Merci beaucoup pour ce partage.

Il se peut que le système envoie plus d'une commande lorsque vous cliquez sur la souris, les raisons peuvent être multiples, mais merci de l'avoir signalé 😁👍, pour résoudre ce malheur, il faut ajouter un test supplémentaire sur le clic de la souris, les points à modifier ou à ajouter sont marqués en VERT ..... faites attention à le taper tel quel, sinon vous risquez de ne pas envoyer la commande, ou elle risque de ne pas être acceptée par le serveur ... mais l'ajout de ce test supplémentaire devrait résoudre votre problème. La logique est la suivante : lorsque la souris est cliquée, la variable STATIC sera définie, et elle ne sera réinitialisée permettant d'envoyer un nouvel ordre que lorsque la souris n'est plus pressée.

inline void MoveTo(int X, int Y, uint Key)
{
        static double d_block = 0; 
        int w = 0;
        datetime dt;
        bool bEClick, bKeyBuy, bKeySell;
        double take = 0, stop = 0, price;
        bEClick  = (Key & 0x01) == 0x01;                //Clique esquerdo
        bKeyBuy  = (Key & 0x04) == 0x04;                //SHIFT Pressionada
        bKeySell = (Key & 0x08) == 0x08;                //CTRL Pressionada
        ChartXYToTimePrice(Infos.Id, X, Y, w, dt, price);
        ObjectMove(Infos.Id, Infos.szHLinePrice, 0, 0, price = (bKeyBuy != bKeySell ? AdjustPrice(price) : 0));
        ObjectMove(Infos.Id, Infos.szHLineTake, 0, 0, take = price + (Infos.TakeProfit * (bKeyBuy ? 1 : -1)));
        ObjectMove(Infos.Id, Infos.szHLineStop, 0, 0, stop = price + (Infos.StopLoss * (bKeyBuy ? -1 : 1)));
        if ((bEClick) && (bKeyBuy != bKeySell) && (d_block == 0)) CreateOrderPendent(bKeyBuy, Infos.Volume, (d_block = price), take, stop, Infos.IsDayTrade); else d_block = 0;
        ObjectSetInteger(Infos.Id, Infos.szHLinePrice, OBJPROP_COLOR, (bKeyBuy != bKeySell ? Infos.cPrice : clrNONE));
        ObjectSetInteger(Infos.Id, Infos.szHLineTake, OBJPROP_COLOR, (take > 0 ? Infos.cTake : clrNONE));
        ObjectSetInteger(Infos.Id, Infos.szHLineStop, OBJPROP_COLOR, (stop > 0 ? Infos.cStop : clrNONE));
};
Apprenez à concevoir différents systèmes de Moyenne Mobile Apprenez à concevoir différents systèmes de Moyenne Mobile
Il existe de nombreuses stratégies qui peuvent être utilisées pour filtrer les signaux générés en fonction de n'importe quelle stratégie, même en utilisant la moyenne mobile elle-même qui fait l'objet de cet article. Ainsi, l'objectif de cet article est de partager avec vous certaines des stratégies de moyenne mobile et comment concevoir un système de trading algorithmique.
Apprenez Pourquoi et Comment Concevoir Votre Système de Trading Algorithmique Apprenez Pourquoi et Comment Concevoir Votre Système de Trading Algorithmique
Cet article montre les bases de MQL pour les débutants afin de concevoir leur système de trading algorithmique (Expert Advisor) en concevant un système de trading algorithmique simple après avoir mentionné quelques bases de MQL5
PriceAction Stoploss fixe ou RSI fixe (Smart StopLoss) PriceAction Stoploss fixe ou RSI fixe (Smart StopLoss)
Le stop-loss est un outil majeur en matière de gestion de l'argent dans le trading. L'utilisation efficace du stop-loss, du take profit et de la taille du lot peut rendre un trader plus cohérent dans le trading et globalement plus rentable. Bien que le stop-loss soit un excellent outil, certains défis sont rencontrés lors de son utilisation. Le principal étant la chasse au stop-loss. Cet article examine comment réduire la chasse au stop-loss dans le trading et compare avec l'utilisation classique du stop-loss pour déterminer sa rentabilité.
Programmation d'un Réseau de Neurones Profond à partir de zéro à l'aide du langage MQL Programmation d'un Réseau de Neurones Profond à partir de zéro à l'aide du langage MQL
Cet article vise à apprendre au lecteur comment créer un Réseau de Neurones Profond à partir de zéro en utilisant le langage MQL4/5.