English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
MQL5 Cookbook : Gestion des événements du graphique typiques

MQL5 Cookbook : Gestion des événements du graphique typiques

MetaTrader 5Exemples | 13 janvier 2022, 10:54
108 0
Denis Kirichenko
Denis Kirichenko

Introduction

Dans mon article, je voudrais décrire les capacités et la pratique de l'utilisation d'OnChartEvent() avec des événements (standard) typiques prédéfinis par les développeurs MQL5. Les articles MQL5 et Code Base contiennent déjà des exemples d'utilisation de ce gestionnaire.

Cependant, mon but est d'analyser cet instrument dans le contexte de la programmation orientée événement (EOP). Je pense que ce gestionnaire peut être utilisé avec succès pour les systèmes de trading entièrement automatiques et semi-automatiques.


1. Événement "ChartEvent"

Voyons donc d'abord ce qu'est ce type d'événement.

Selon la Documentation, l'événement ChartEvent peut apparaître lors de l'utilisation d'un graphique, notamment lors de :

  • l’appui sur une touche du clavier lorsqu'une fenêtre graphique est active.
  • la création d’un objet graphique.
  • la suppression un objet graphique.
  • le clic sur un objet graphique.
  • le glissement d’un objet graphique avec une souris.
  • la finition pour l'édition de texte dans un champ de texte d'un objet graphique LabelEdit.

Ainsi, cet événement apporte de l'interactivité et permet d'interagir avec un graphique. De plus, une telle interaction peut être le résultat d'un trading manuel, ainsi que de certaines opérations algorithmiques (trading automatisé).

Les développeurs MQL5 classent l'événement ChartEvent par types spécifiés dans l'énumération ENUM_CHART_EVENT.

Il est important de noter que cette liste contient une gamme d'événements définis par l'utilisateur, qui agissent comme une réserve cachée pour servir le programmeur. Les développeurs MQL5 fournissent 65535 ID pour les événements personnalisés.

Pour travailler avec des événements personnalisés, une fonction de générateur spéciale EventChartCustom() est disponible pour les besoins du programmeur. Cependant, cet article ne prend pas en compte les événements personnalisés.


2. Gestionnaire et générateur de ChartEvent

Tout le traitement de l'événement ChartEvent est effectué par une fonction de gestion spéciale OnChartEvent(). Ceci est cohérent avec le concept du langage MQL5, où par exemple l'événement Trade est géré par la fonction OnTrade(), l'événement Init est géré par la fonction OnInit(), etc.

La fonction OnChartEvent() a la signature suivante :

void OnChartEvent(const int id,         // event identifier  
                  const long& lparam,   // parameter of the event of type long
                  const double& dparam, // parameter of the event of type double
                  const string& sparam  // parameter of the event of type string
                  )

Tous les paramètres d'entrée sont constants et lorsque le gestionnaire est appelé, ils transmettent des informations utiles.

Ainsi, la valeur du paramètre id peut révéler quel événement particulier a appelé le gestionnaire. D'autres peuvent avoir des valeurs de types long, double et string. De cette façon, des informations supplémentaires sur un événement peuvent être obtenues.

Plus tard, nous créerons un exemple où les valeurs des paramètres spécifiés seront utilisées pour analyser ce qui se passe.

La partie personnalisée de l'événement ChartEvent, qui doit être implémentée par un programmeur, est connectée à la fonction EventChartCustom(). Cette fonction même peut générer l'événement. La signature de la fonction est la suivante :

bool  EventChartCustom(long    chart_id,        // receiving chart identifier
                       ushort  custom_event_id, // event identifier
                       long    lparam,          // the long parameter
                       double  dparam,          // the double parameter
                       string  sparam           // the string parameter
                       )

En fait, la fonction génératrice peut créer un événement et l'envoyer à n'importe quel graphique, y compris le graphique actuel avec toutes les valeurs des paramètres d'entrée. Ces derniers sont les types : ushort, long, double, string.

Les fonctions OnChartEvent() et EventChartCustom() forment ensemble un outil puissant qui est un bon exemple des avantages de la programmation orientée événement.


3. Modèle de traitement d'événement standard

Maintenant, je vais considérer les types des événements du graphique et donner un exemple pour chacun d'eux. Chaque événement aura sa propre version dédiée de EventProcessor.mq5 et son code contiendra la gestion d'un événement du graphique. Il y a 10 événements typiques dans MQL5.

Pour trois d'entre eux (événement de souris, événement de création d'objet graphique, événement de suppression d'objet graphique), nous devons préparer un graphique. Cela peut être fait en utilisant la fonction ChartSetInteger(). Il permet à un graphique de répondre à des événements spécifiés.

Un bloc typique pour le traitement des événements du graphique pourrait ressembler à :

void OnChartEvent(const int id, 
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   string comment="Last event: ";

//--- select event on chart
   switch(id)
     {
      //--- 1
      case CHARTEVENT_KEYDOWN:
        {
         comment+="1) keystroke";
         break;
        }
      //--- 2
      case CHARTEVENT_MOUSE_MOVE:
        {
         comment+="2) mouse";
         break;
        }
      //--- 3
      case CHARTEVENT_OBJECT_CREATE:
        {
         comment+="3) create graphical object";
         break;
        }
      //--- 4
      case CHARTEVENT_OBJECT_CHANGE:
        {
         comment+="4) change object properties via properties dialog";
         break;
        }
      //--- 5
      case CHARTEVENT_OBJECT_DELETE:
        {
         comment+="5) delete graphical object";
         break;
        }
      //--- 6
      case CHARTEVENT_CLICK:
        {
         comment+="6) mouse click on chart";
         break;
        }
      //--- 7
      case CHARTEVENT_OBJECT_CLICK:
        {
         comment+="7) mouse click on graphical object";
         break;
        }
      //--- 8
      case CHARTEVENT_OBJECT_DRAG:
        {
         comment+="8) move graphical object with mouse";
         break;
        }
      //--- 9
      case CHARTEVENT_OBJECT_ENDEDIT:
        {
         comment+="9) finish editing text";
         break;
        }
      //--- 10
      case CHARTEVENT_CHART_CHANGE:
        {
         comment+="10) modify chart";
         break;
        }
     }
//---
   Comment(comment);
  }

Dans chaque cas, j'ai ajouté la chaîne décrivant un événement sélectionné. En conséquence, dans la ligne de commentaire, nous pouvons voir le dernier événement survenu sur le graphique. Si vous exécutez le modèle et effectuez diverses manipulations avec le graphique, vous remarquerez que la ligne de commentaire peut avoir des enregistrements différents.

Évidemment, il y a peu d'utilité d'un tel Expert Advisor qui ne détermine que le type d'événement. Nous devons étendre ses capacités.


4. Exemples de traitement d'événement standard


4.1. Événement de frappe de clavier

Prenons le premier cas et travaillons avec les boutons du clavier, afin que notre EA réponde aux frappes au clavier. Laissez-le acheter en appuyant sur la "flèche vers le haut" et vendre en appuyant sur la "flèche vers le bas". Alors ce cas ressemblera à ceci :

//--- 1
      case CHARTEVENT_KEYDOWN:
        {
         //--- "up" arrow
         if(lparam==38)
            TryToBuy();

         //--- "down" arrow
         else if(lparam==40)
            TryToSell();

         comment+="1) keystroke";
         //---         
         break;
        }

Voir le code source EA ci-joint pour plus de détails sur l'implémentation TryToBuy() et TryToSell(). Les paramètres de trading (taille du lot, Stop Loss, Take Profit, etc.) sont spécifiés en tant que variables d'entrée (InpLot, InpStopLoss, InpTakeProfit, etc.). Il convient également de mentionner que le paramètre lparam obtient le code de la touche enfoncée.

La version mise à jour de l'EA s'appelle EventProcessor1.mq5.


4.2. Événement de souris

Ce type d'événement ne sera géré que si la propriété CHART_EVENT_MOUSE_MOVE a été spécifiée pour le graphe. Pour cette raison, le bloc d'initialisation de l'EA contient de telles chaînes de caractères :

//--- mouse move
bool is_mouse=false;
if(InpIsEventMouseMove)
   is_mouse=true;
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,is_mouse);

Il convient de noter que si vous utilisez une souris, alors, naturellement, un événement souris aura souvent lieu. Pour cette raison, une opportunité de désactiver le traitement de cet événement peut être utile. Les paramètres lparam et dparam du gestionnaire rapportent les coordonnées X et Y en conséquence.

Nous allons discuter d'un exemple inventé. Supposons qu'il y ait un décalage de zéro barre à partir du bord droit. En passant le curseur sur la partie de l'écran située à droite du décalage, vous ferez apparaître une fenêtre vous proposant d'acheter ou de vendre.

Pour ce faire, nous devons d'abord déterminer le décalage. Nous allons introduire une variable d'entrée pour déterminer la taille d'un décalage de la barre zéro à partir de la bordure droite en pourcentages (InpChartShiftSize).

Fig.1 Fenêtre d'une opération de trade

Fig.1 Fenêtre d'une opération de trade

Nous allons utiliser les fonctions qui activent le décalage et déterminent sa taille ChartShiftSet() et ChartShiftSizeSet(). Ensuite, nous identifierons si l'abscisse du curseur était auparavant à gauche de la bordure et si elle s'est déplacée vers la droite. Si c'est le cas, une fenêtre suggérant d'acheter/vendre apparaîtra (Fig.1).

Le code implémentant la cible définie ressemble à :

//--- 2
      case CHARTEVENT_MOUSE_MOVE:
        {
         comment+="2) mouse";
         //--- if a mouse event is processed
         if(InpIsEventMouseMove)
           {
            long static last_mouse_x;

            //--- enable shift
            if(ChartShiftSet(true))
               //--- set shift size 
               if(ChartShiftSizeSet(InpChartShiftSize))
                 {
                  //--- chart width
                  int chart_width=ChartWidthInPixels();

                  //--- calculate X coordinate of shift border
                  int chart_shift_x=(int)(chart_width-chart_width*InpChartShiftSize/100.);

                  //--- border crossing condition
                  if(lparam>chart_shift_x && last_mouse_x<chart_shift_x)
                    {
                     int res=MessageBox("Yes: buy / No: sell","Trade operation",MB_YESNO);
                     //--- buy
                     if(res==IDYES)
                        TryToBuy();
                     //--- sell
                     else if(res==IDNO)
                        TryToSell();
                    }

                  //--- store mouse X coordinate
                  last_mouse_x=lparam;
                 }
           }

         //---
         break;
        }

L'achat et la vente se font par les fonctions de trade précédemment créées. La version mise à jour de l'EA sera nommée EventProcessor2.mq5.


4.3. Événement de création d'objet graphique

Ce type d'événement est généré lorsqu'un objet est créé sur un graphique. Semblable à un événement de souris, ce type doit recevoir une autorisation de gestion avec la propriété CHART_EVENT_OBJECT_CREATE. Il n'a besoin d'être spécifié qu'une seule fois dans le bloc d'initialisation si l'on va répondre à l'apparition d'un nouvel objet graphique.

//--- object create
bool is_obj_create=false;
if(InpIsEventObjectCreate)
   is_obj_create=true;
ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,is_obj_create);

Un seul paramètre du gestionnaire va contenir des informations. C'est un paramètre de chaîne sparam qui contient le nom de l'objet graphique créé. Nous pouvons trouver cet objet par son nom, le traiter et ensuite décider quoi faire ensuite.

Voici un exemple simple. Nous allons tracer une ligne horizontale sur le graphique et laisser le robot la placer au prix maximum de toutes les barres reflétées sur le graphique et tracer deux autres lignes. La ligne inférieure sera placée au prix minimum et la troisième ligne sera entre les deux premières à égale distance des deux.

Le code pour la mise en œuvre de la tâche :

//--- 3
      case CHARTEVENT_OBJECT_CREATE:
        {
         comment+="3) create graphical object";
         //--- if graphical object creation event is processed
         if(InpIsEventObjectCreate)
           {
            //--- capture creation of horizontal line
            int all_hor_lines=ObjectsTotal(0,0,OBJ_HLINE);

            //--- if this is the only line
            if(all_hor_lines==1)
              {
               string hor_line_name1=sparam;

               //--- calculate levels
               int visible_bars_num=ChartVisibleBars();

               //--- arrays for high and low prices
               double highs[],lows[];
               //---
               int copied=CopyHigh(_Symbol,_Period,0,visible_bars_num-1,highs);
               if(copied!=visible_bars_num-1)
                 {
                  Print("Failed to copy highs!");
                  return;
                 }
               copied=CopyLow(_Symbol,_Period,0,visible_bars_num-1,lows);
               if(copied!=visible_bars_num-1)
                 {
                  Print("Failed to copy lows!");
                  return;
                 }
               //--- high and low prices
               double ch_high_pr,ch_low_pr,ch_mid_pr;
               //---
               ch_high_pr=NormalizeDouble(highs[ArrayMaximum(highs)],_Digits);
               ch_low_pr=NormalizeDouble(lows[ArrayMinimum(lows)],_Digits);
               ch_mid_pr=NormalizeDouble((ch_high_pr+ch_low_pr)/2.,_Digits);

               //--- place created line on high
               if(ObjectFind(0,hor_line_name1)>-1)
                  if(!ObjectMove(0,hor_line_name1,0,0,ch_high_pr))
                    {
                     Print("Failed to move!");
                     return;
                    }
               //--- create line on low
               string hor_line_name2="Hor_line_min";
               //---
               if(!ObjectCreate(0,hor_line_name2,OBJ_HLINE,0,0,ch_low_pr))
                 {
                  Print("Failed to create the 2nd horizontal line!");
                  return;
                 }
               //--- create line between high and low 
               string hor_line_name3="Hor_line_mid";
               //---
               if(!ObjectCreate(0,hor_line_name3,OBJ_HLINE,0,0,ch_mid_pr))
                 {
                  Print("Failed to create the 3rd horizontal line!");
                  return;
                 }
              }
           }
         break;
        }

Le nom de la version mise à jour de l'EA est EventProcessor3.mq5.

Fig. 2. Résultat de la gestion de l'événement de création d'objet graphique

Fig. 2. Résultat de la gestion de l'événement de création d'objet graphique

Après avoir terminé la procédure, j'ai reçu l'image suivante (Fig. 2). Ainsi, les fonctions intégrées donnent à un EA la capacité de réagir à la création d'un objet graphique et d'agir ensuite dessus.


4.4. Événement de modification des propriétés d'un objet graphique via une boîte de dialogue Propriétés

Ce type d'événement est partiellement similaire au précédent. Il se déclenche lorsque l'une des propriétés d'un objet graphique est modifiée via une boîte de dialogue de propriétés. Cet outil peut être utile, par exemple, pour synchroniser les propriétés graphiques d'objets du même type.

Imaginez un certain nombre d'objets sur un graphique. Un trader a généralement beaucoup de lignes différentes sur un graphique. Ces lignes doivent être rendues invisibles pendant un certain temps sans être supprimées. Nous allons trouver une solution à cette tâche. La ligne modifiée peut être décolorée et la même chose peut être faite pour d'autres objets graphiques. Le code pourrait alors être le suivant :

//--- 4
      case CHARTEVENT_OBJECT_CHANGE:
        {
         comment+="4) change object properties via properties dialog";
         //---
         string curr_obj_name=sparam;
         //--- find the changed object
         if(ObjectFind(0,curr_obj_name)>-1)
           {
            //--- get object color
            color curr_obj_color=(color)ObjectGetInteger(0,curr_obj_name,OBJPROP_COLOR);
            //--- total number of objects on chart
            int all_other_objects=ObjectsTotal(0);
            //--- find other objects
            for(int obj_idx=0;obj_idx<all_other_objects;obj_idx++)
              {
               string other_obj_name=ObjectName(0,obj_idx);
               if(StringCompare(curr_obj_name,other_obj_name)!=0)
                  if(!ObjectSetInteger(0,other_obj_name,OBJPROP_COLOR,curr_obj_color))
                    {
                     Print("Failed to change the object color!");
                     return;
                    }
              }
            //--- redraw chart
            ChartRedraw();
           }
         //---
         break;

Supposons qu'il y ait un ensemble de lignes sur le graphique (Fig.3).

Fig.3. Lignes dynamiques multicolores

Fig.3. Lignes dynamiques multicolores

Si nous essayons de changer la couleur de l'une des lignes, ou pour être précis, la décolorer (Fig.4) dans la boîte de dialogue des propriétés, alors il n'y aura aucune ligne visible sur le graphique. En même temps, les objets graphiques y seront toujours présents.

Fig.4. Changement d’une couleur de ligne

Fig.4. Changement d’une couleur de ligne

La version mise à jour de l'EA s'appelle EventProcessor4.mq5.


4.5. Événement de suppression d'objet graphique

Comme le nom de ce type d'événement l'indique, il apparaît lors de la suppression d'un objet d'un graphique. C'est le dernier événement d'un groupe, qui nécessite une autorisation préalable directe pour la manipulation. Cela peut être fait via la propriété CHART_EVENT_OBJECT_DELETE.

//--- object delete
   bool is_obj_delete=false;
   if(InpIsEventObjectDelete)
      is_obj_delete=true;
   ChartSetInteger(0,CHART_EVENT_OBJECT_DELETE,is_obj_delete);

Voici un autre exemple hypothétique. Sur le graphique où votre EA est attaché, il y a un ensemble d'objets graphiques de différents types. Supposons que nous ayons besoin de supprimer des objets d'un seul type particulier. Par exemple, les lignes verticales (Fig.5).

Fig.5. Cinq verticales et autres lignes

Fig.5. Cinq verticales et autres lignes

Nous n'avons besoin de supprimer qu'une seule verticale et l'expert supprimera les autres (Fig.6).

Fig.6. Lignes restantes

Fig.6. Lignes restantes

Les entrées suivantes apparaîtront dans le registre "Experts" :

NS      0       10:31:17.937    EventProcessor5 (EURUSD.e,W1)   Vertical lines before removing: 4
MD      0       10:31:17.937    EventProcessor5 (EURUSD.e,W1)   Vertical lines removed from the chart: 4
QJ      0       10:31:18.078    EventProcessor5 (EURUSD.e,W1)   Vertical lines after removing: 0

Un aspect important doit être mentionné. Une fois qu'un objet est supprimé, il n'y a plus d'accès à ses propriétés. Cela signifie que si nous ne récupérons pas les données requises sur l'objet au préalable, il ne sera pas accessible après sa suppression. Par conséquent, si nous avons besoin de connaître le type d'un objet supprimé, nous devons le stocker avant que l'objet lui-même ne soit supprimé. J'ai une suggestion pour les développeurs MQL5 de créer un historique d'un graphique disponible dans le terminal. Cela nous permettra de nous référer aux propriétés des objets supprimés.

Nous appellerons la dernière version de l'Expert EventProcessor5.mq5.


4.6. Événement de clic de souris sur le graphique

Cet événement sera généré si le graphique est cliqué avec le bouton gauche de la souris. Un clic droit sur le graphique ouvrira un menu contextuel et un clic avec le bouton du milieu fera apparaître un réticule. Les paramètres lparam et dparam du gestionnaire rapportent les coordonnées X et Y en conséquence.

La tâche simple suivante servira d'exemple. Nous devons faire en sorte qu'une flèche « acheter » soit dessinée à l'endroit où le clic de souris a lieu. L'objet 'flèche' n'a qu'un seul point d'ancrage. Par conséquent, une seule transformation des coordonnées X et Y en valeurs du temps et du prix du point d'ancrage est nécessaire.

Le code de l'exemple ci-dessus :

//--- 6
      case CHARTEVENT_CLICK:
        {
         comment+="6) mouse click on chart";
         //--- object counter 
         static uint sign_obj_cnt;
         string buy_sign_name="buy_sign_"+IntegerToString(sign_obj_cnt+1);
         //--- coordinates 
         int mouse_x=(int)lparam;
         int mouse_y=(int)dparam;
         //--- time and price
         datetime obj_time;
         double obj_price;
         int sub_window;
         //--- convert the X and Y coordinates to the time and price values
         if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price))
           {
            //--- create object
            if(!ObjectCreate(0,buy_sign_name,OBJ_ARROW_BUY,0,obj_time,obj_price))
              {
               Print("Failed to create buy sign!");
               return;
              }
            //--- redraw chart
            ChartRedraw();
            //--- increase object counter
            sign_obj_cnt++;
           }
         //---
         break;
        }

La version actuelle de l'expert s'appelle EventProcessor6.mq5.


4.7. Événement de clic de souris sur un objet graphique

Ce type d'événements du graphique ne diffère du précédent que par le fait qu'un clic de souris se produit sur un objet graphique. Le paramètre de chaîne sparam contiendra le nom de l'objet sur lequel vous avez cliqué. Dans l'exemple précédent, nous avons créé des flèches 'acheter'. Faisons en sorte qu'un clic sur l'objet de ce type le transforme en flèche 'vendre'.

Le code de ce bloc du gestionnaire peut ressembler à :

//--- 7
      case CHARTEVENT_OBJECT_CLICK:
        {
         comment+="7) mouse click on graphical object";
         //---
         string sign_name=sparam;

         //--- delete buy arrow
         if(ObjectDelete(0,sign_name))
           {
            //--- redraw chart
            ChartRedraw();
            //---
            static uint sign_obj_cnt;
            string sell_sign_name="sell_sign_"+IntegerToString(sign_obj_cnt+1);

            //--- coordinates 
            int mouse_x=(int)lparam;
            int mouse_y=(int)dparam;
            //--- time and price
            datetime obj_time;
            double obj_price;
            int sub_window;
            //--- convert the X and Y coordinates to the time and price values
            if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price))
              {
               //--- create object
               if(!ObjectCreate(0,sell_sign_name,OBJ_ARROW_SELL,0,obj_time,obj_price))
                 {
                  Print("Failed to create sell sign!");
                  return;
                 }
               //--- redraw chart
               ChartRedraw();
               //--- increase object counter
               sign_obj_cnt++;
              }
           }
         //---
         break;
        }

Pour les besoins de cet exemple, j'ai gardé le cas d'un clic de souris inchangé. En lançant l'EA, j'ai cliqué trois fois avec le bouton gauche de la souris et j'ai obtenu trois flèches à acheter (Fig.7). J'ai surligné leur emplacement en jaune.

Fig.7. Flèches "Acheter"

Fig.7. Flèches "Acheter"

Si maintenant nous cliquons sur chaque flèche 'acheter', nous recevrons l'image suivante (Fig.8).

Fig.8. Flèches 'Acheter' et 'Vendre'

Fig.8. Flèches 'Acheter' et 'Vendre'

Les flèches 'Vendre' sont apparues comme prévu, mais les flèches 'Acheter' n'étaient pas conçues pour apparaître. Il y a une raison pour laquelle j'apporte une liste d'objets sur le graphique où j'ai surligné en jaune les noms des flèches 'Acheter'.

Il est facile de remarquer que l'EA a créé les 4e, 5e et 6e flèches 'Acheter'. Pourquoi cela s'est-il produit ? C'est arrivé parce que le premier clic sur l'objet a déclenché deux événements : le premier était le clic réel sur l'objet et le second - un clic sur le graphique. Le dernier événement génère la création d'une flèche 'Acheter'. Ici se pose la nécessité d'ajouter un mécanisme qui empêchera la gestion du deuxième événement, qui est un clic sur le graphique. Il me semble que le contrôle du temps peut être un tel mécanisme.

Ajoutons une variable globale gLastTime. Cela facilitera un contrôle sur le temps de création d'une flèche 'acheter'. Si un simple gestionnaire de clics est appelé pendant moins de 250 ms après la création d'une flèche 'vente', alors cet appel doit être transmis.

Avant que le graphe ne soit redessiné, la chaîne ci-dessous est à ajouter au bloc de traitement d'un clic sur l'objet :

//--- store the moment of creation
gLastTime=GetTickCount();

La vérification de l'heure doit être ajoutée au bloc de manipulation d'un clic sur le graphique.

uint lastTime=GetTickCount();
if((lastTime-gLastTime)>250)
  {
   //--- click handling
  }

Créons à nouveau trois flèches sur le graphique de type 'acheter' (Fig.9).

Fig.9. Flèches 'Acheter'

Fig.9. Flèches 'Acheter'

Nous essaierons de cliquer dessus malgré leur petite taille. Les flèches se sont transformées en type "vente" au clic (Fig.10).

10. Flèches 'Vendre'

Fig.10. Flèches 'Vendre'

Semblable aux précédents, nous allons nommer la nouvelle version EventProcessor7.mq5.


4.8. Événement de déplacement d'un objet graphique avec la souris

Cet événement se produit lorsqu'un objet est déplacé dans une zone de graphique. Le gestionnaire reçoit le nom de l'objet déplacé sous la forme d'un paramètre de chaîne sparam.

Voici un autre exemple. Les traders intra-journaliers tradent très souvent dans un certain intervalle de temps. Les lignes verticales seront les limites d'un intervalle de temps. L'image ressemblera approximativement à la Fig.11. L'intervalle d'intérêt est mis en évidence.

Fig.11. Limites d'un intervalle de temps

Fig.11. Limites d'un intervalle de temps

L'intervalle de temps peut être modifié manuellement. Ensuite, notre semi-automate devra réagir à un tel changement.

Au niveau global, nous allons créer des variables décrivant les noms des deux verticales - gTimeLimit1_name et gTimeLimit2_name. Nous devons également créer quelques variables pour les noms des rectangles, qui assombrissent le temps de non-échange sur le graphique. Des variables globales pour les points d'ancrage devront également être créées. Puisque nous avons deux rectangles, nous aurons quatre points.

Le code du cas du gestionnaire CHARTEVENT_OBJECT_DRAG :

//--- 8
      case CHARTEVENT_OBJECT_DRAG:
        {
         comment+="8) move graphical object with mouse";
         string curr_obj_name=sparam;
         //--- if one of the vertical lines is moved
         if(!StringCompare(curr_obj_name,gTimeLimit1_name) || 
            !StringCompare(curr_obj_name,gTimeLimit2_name))
           {
            //--- the time coordinate of vertical lines
            datetime time_limit1=0;
            datetime time_limit2=0;
            //--- find the first vertical line
            if(ObjectFind(0,gTimeLimit1_name)>-1)
               time_limit1=(datetime)ObjectGetInteger(0,gTimeLimit1_name,OBJPROP_TIME);
            //--- find the second vertical line
            if(ObjectFind(0,gTimeLimit2_name)>-1)
               time_limit2=(datetime)ObjectGetInteger(0,gTimeLimit2_name,OBJPROP_TIME);

            //--- if vertical lines are found
            if(time_limit1>0 && time_limit2>0)
               if(time_limit1<time_limit2)
                 {
                  //--- update properties of rectangles
                  datetime start_time=time_limit1;
                  datetime finish_time=time_limit2;
                  //---
                  if(RefreshRecPoints(start_time,finish_time))
                    {
                     //---
                     if(!ObjectMove(0,gRectLimit1_name,0,gRec1_time1,gRec1_pr1))
                       {
                        Print("Failed to move the 1st point!");
                        return;
                       }
                     if(!ObjectMove(0,gRectLimit1_name,1,gRec1_time2,gRec1_pr2))
                       {
                        Print("Failed to move the 2nd point!");
                        return;
                       }
                     //---
                     if(!ObjectMove(0,gRectLimit2_name,0,gRec2_time1,gRec2_pr1))
                       {
                        Print("Failed to move the 1st point!");
                        return;
                       }
                     if(!ObjectMove(0,gRectLimit2_name,1,gRec2_time2,gRec2_pr2))
                       {
                        Print("Failed to move the 2nd point!");
                        return;
                       }
                    }
                 }
           }
         //---
         break;
        }

Ce code contient une fonction personnalisée RefreshRecPoints(). Il s'agit de mettre à jour les valeurs des points d'ancrage pour deux rectangles. Le bloc d'initialisation EA peut fournir des informations sur la création d'objets graphiques. La version mise à jour s'appellera EventProcessor8.mq5.


4.9. Fin de l'événement d'édition d'un texte dans le champ de texte

Ce type d'événement a une nature hautement spécialisée et apparaît lorsque le texte dans le champ de saisie de données est en cours d'édition. Le paramètre sparam contient le nom de l'objet sur lequel on travaille.

Voici un exemple à considérer. Dans le champ de saisie des données, nous saisirons l'opération de trade que nous sommes sur le point d'exécuter. Qu'il n'y ait que deux opérations - acheter et vendre. Si nous entrons le mot « Acheter » dans le champ de saisie, l'EA achètera un actif et si nous entrons « Vendre », l'actif sera vendu. Nous allons faire en sorte que ce champ ne soit pas sensible à la casse, c'est-à-dire que nous pouvons taper « acheter » et « vendre ». Le texte et le champ de saisie seront de couleur rouge à la vente et bleu à l'achat (Fig.12).

Fig.12. Acheter via le champ de texte

Fig.12. Acheter via le champ de texte

Le code dans le cas CHARTEVENT_OBJECT_ENDEDIT :

//--- 9
      case CHARTEVENT_OBJECT_ENDEDIT:
        {
         comment+="9) end of editing a text in the data entry field";
         //---
         string curr_obj_name=sparam;
         //--- if specified text field is being edited
         if(!StringCompare(curr_obj_name,gEdit_name))
           {
            //--- get object description
            string obj_text=NULL;
            if(ObjectGetString(0,curr_obj_name,OBJPROP_TEXT,0,obj_text))
              {
               //--- check value
               if(!StringCompare(obj_text,"Buy",false))
                 {
                  if(TryToBuy())
                     //--- set text color
                     ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrBlue);
                 }
               else if(!StringCompare(obj_text,"Sell",false))
                 {
                  if(TryToSell())
                     //--- set text color
                     ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrRed);
                 }
               else
                 {
                  //--- set text color
                  ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrGray);
                 }
               //--- redraw chart
               ChartRedraw();
              }
           }
         //---
         break;
        }

La version mise à jour de l'EA s'appelle EventProcessor9.mq5. Vous pouvez trouver le bloc de création du champ de texte dans le fichier source.


4.10. Événement de modification de graphique

Le dernier événement que nous allons considérer dans cet article est lié à la modification des paramètres du graphique. Il s'agit d'un événement particulier car à ce stade, nous nous occupons du graphique lui-même, et non des objets du graphique. Les développeurs disent que cet événement est généré lorsque la taille d'un graphique est modifiée ou qu'un nouveau paramètre est introduit.

Voici un autre exemple. Supposons qu'il existe une interdiction de modifier certains paramètres du graphique. Ensuite, toutes les tentatives de modification des paramètres sous restriction seront ignorées. En fait, l'EA renverra simplement les valeurs précédentes. Fixons les paramètres suivants du graphique :

  • grille d'affichage ;
  • type d'affichage graphique ;
  • Couleur de fond.

Code pour ce cas :

//--- 10
      case CHARTEVENT_CHART_CHANGE:
        {
         //--- current height and width of the chart         
         int curr_ch_height=ChartHeightInPixelsGet();
         int curr_ch_width=ChartWidthInPixels();
         //--- if chart height and width have not changed
         if(gChartHeight==curr_ch_height && gChartWidth==curr_ch_width)
           {
            //--- fix the properties:
            //--- display grid
            if(!ChartShowGridSet(InpToShowGrid))
              {
               Print("Failed to show grid!");
               return;
              }
            //--- type of chart display
            if(!ChartModeSet(InpMode))
              {
               Print("Failed to set mode!");
               return;
              }
            //--- background color
            if(!ChartBackColorSet(InpBackColor))
              {
               Print("Failed to set background сolor!");
               return;
              }
           }
         //--- store window dimensions
         else
           {
            gChartHeight=curr_ch_height;
            gChartWidth=curr_ch_width;
           }
         //---
         comment+="10) modify chart";
         //---
         break;
        }

La dernière version s'appellera EventProcessor10.mq5.


Conclusion

Dans cet article, j'ai essayé d'illustrer la diversité des événements du graphique typiques dans MetaTrader 5. J'espère que ces exemples de gestion d'événements seront utiles aux programmeurs qui commencent à coder en MQL5.

Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/689

Fichiers joints |
code_en.zip (19.59 KB)
Comment installer et utiliser OpenCL pour les calculs Comment installer et utiliser OpenCL pour les calculs
Cela fait plus d'un an que MQL5 a commencé à fournir un support natif pour OpenCL. Cependant, peu d'utilisateurs ont vu la vraie valeur de l'utilisation du calcul parallèle dans leurs Expert Advisors, indicateurs ou scripts. Cet article sert à vous aider à installer et à configurer OpenCL sur votre ordinateur afin que vous puissiez essayer d'utiliser cette technologie dans le terminal de trading MetaTrader 5.
Le réseau MQL5 Cloud Network : Calculez-vous toujours ? Le réseau MQL5 Cloud Network : Calculez-vous toujours ?
Cela fera bientôt un an et demi que le réseau MQL5 Cloud Network a été lancé. Cet événement de pointe a inauguré une nouvelle ère de trading algorithmique - désormais, en quelques clics, les traders peuvent disposer de centaines et de milliers de cœurs de calcul pour l'optimisation de leurs stratégies de trading.
Une autre classe MQL5 OOP Une autre classe MQL5 OOP
Cet article vous montre comment créer un Expert Advisor orienté objet à partir de zéro, de la conception d'une idée de trading théorique à la programmation d'un EA MQL5 qui rend cette idée réelle dans le monde empirique. Apprendre par la pratique est à mon humble avis une approche solide pour réussir, je vous montre donc un exemple pratique afin que vous voyiez comment vous pouvez ordonner vos idées pour enfin coder vos robots Forex. Mon objectif est également de vous inviter à adhérer aux principes de l’OO.
Indicateur pour le graphique en Points et Figures Indicateur pour le graphique en Points et Figures
hIl existe de nombreux types de graphiques qui fournissent des informations sur la situation actuelle du marché. Beaucoup d’entre eux, tels que le graphique en Points et Figures, sont l’héritage du passé lointain. L’article décrit un exemple de graphique en Points et Figures à l’aide d’un indicateur en temps réel.