MQL5 Cookbook : Propriétés de position dans le panneau d'informations personnalisé
Introduction
Cette fois, nous allons créer un simple Expert Advisor qui obtiendra les propriétés de position sur le symbole actuel et les affichera sur le panneau d'informations personnalisé pendant le trading manuel. Le panneau d'informations sera créé à l'aide d'objets graphiques et les informations affichées seront actualisées à chaque tick. Cela va être beaucoup plus pratique que d'avoir tout le temps à exécuter manuellement le script décrit dans l'article précédent de la série intitulé "MQL5 Cookbook : Getting Position Properties".
Développer un Expert Advisor
Commençons par les objets graphiques. Pour créer le panneau d'informations, nous avons besoin d'objets pour l'arrière-plan, l'en-tête, les noms et les valeurs des propriétés de position. L'arrière-plan et l'en-tête nécessiteront un rectangle qui ne bouge pas avec le prix. Le rectangle peut être créé à l'aide d'objets graphiques tels que Rectangle Label ou Edit, tandis que les noms et les valeurs des propriétés de l'objet seront créés à l'aide de Text Labels.
Avant de passer au code, nous allons d'abord préparer une mise en page pour le panneau d'informations. Sa commodité réside dans le fait que nous pouvons modifier rapidement n'importe quelle propriété dans la fenêtre des paramètres et personnaliser l'apparence du panneau d'informations.
Chaque objet a une fenêtre de paramètres qui peut être ouverte à partir du menu contextuel d'un objet sélectionné. La fenêtre des paramètres peut également être ouverte à partir de la liste d'objets (Ctrl+B) en sélectionnant l'objet requis et en cliquant sur Propriétés. La disposition du panneau d'informations est illustrée ci-dessous. Il peut également être utilisé pour estimer les tailles et les coordonnées lors de l'écriture d'un code. Lorsque le code du panneau d'informations sera prêt, vous devrez supprimer les objets de mise en page manuellement car l'Expert Advisor ne pourra pas les 'voir' et ne les supprimera donc pas du graphique.
Fig. 1. Préparation de la mise en page pour le panneau d'information.
Nous devons maintenant créer un modèle pour l'Expert Advisor. Cela peut être fait aussi rapidement que pour le script. Dans l'assistant MQL5, l'option Expert Advisor (modèle) est sélectionnée par défaut. Nous passons aux étapes suivantes sans apporter de modifications aux options car elles ne sont pas nécessaires cette fois. Cliquez ensuite sur Terminer et vous verrez un modèle comme ci-dessous :
//+------------------------------------------------------------------+ //| PositionPropertiesPanel.mq5 | //| Copyright 2012, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2012, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+
On remarque tout de suite que le modèle Expert Advisor est différent du modèle de script. Outre les propriétés du programme (#property), il existe trois fonctions principales : OnInit(), OnDeinit() et OnTick().
La fonction OnInit () est appelée lors du chargement du programme, de la modification des paramètres externes, de la compilation du programme, à condition que le programme soit à ce moment-là ajouté au graphique, et lors du changement de symbole ou de période. Si nécessaire, vous pouvez initialiser certaines variables ou tableaux dans cette fonction pour pouvoir les utiliser ultérieurement.
La fonction OnDeinit() est appelée lorsque vous supprimez le programme du graphique, modifiez le compte, le symbole ou la période. Toutes les raisons de désinitialisation possibles sont fournies dans MQL5 Reference. Cet Expert Advisor emploiera une fonction définie par l'utilisateur, GetDeinitReasonText(), qui convertit l'identifiant de motif de désinitialisation (le paramètre de fonction OnDeinit()) en texte.
Et enfin, la fonction OnTick(). Il est appelé à chaque fois qu'il y a une nouvelle coche sur le symbole sur le graphique duquel l'Expert Advisor opère actuellement.
Préparons maintenant toutes les constantes, variables et tableaux que nous allons utiliser dans l'Expert Advisor. Nous les placerons au tout début du programme. Tout d'abord, définissez les variables dont les valeurs restent inchangées tout au long du programme :
//--- #define INFOPANEL_SIZE 14 // Size of the array for info panel objects #define EXPERT_NAME MQL5InfoString(MQL5_PROGRAM_NAME) // Name of the Expert Advisor //---
Ceci est suivi par des variables globales pour les propriétés de position :
//--- GLOBAL VARIABLES bool pos_open=false; // Flag of presence/absence of an open position string pos_symbol=""; // Symbol long pos_magic=0; // Magic number string pos_comment=""; // Comment double pos_swap=0.0; // Swap double pos_commission=0.0; // Commission double pos_price=0.0; // Position price double pos_cprice=0.0; // Current price of the position double pos_profit=0.0; // Profit/Loss of the position double pos_volume=0.0; // Position volume double pos_sl=0.0; // Stop Loss of the position double pos_tp=0.0; // Take Profit of the position datetime pos_time=NULL; // Position opening time long pos_id=0; // Position identifier ENUM_POSITION_TYPE pos_type=WRONG_VALUE; // Position type
Après les variables, nous allons déclarer des tableaux de noms d'objets graphiques. Ces objets afficheront les propriétés de position et leurs valeurs dans le graphique. À cette fin, nous allons créer deux tableaux de chaînes et initialiser immédiatement leurs éléments en valeurs. Entre crochets, nous utilisons la valeur de la constante INFOPANEL_SIZE déclarée au tout début du programme. C'est-à-dire qu'il y aura 14 éléments dans chaque tableau.
// Array of names of objects that display names of position properties string positionPropertyNames[INFOPANEL_SIZE]= { "name_pos_symbol", "name_pos_magic", "name_pos_comment", "name_pos_swap", "name_pos_commission", "name_pos_price", "name_pos_cprice", "name_pos_profit", "name_pos_volume", "name_pos_sl", "name_pos_tp", "name_pos_time", "name_pos_id", "name_pos_type" }; //--- // Array of names of objects that display values of position properties string positionPropertyValues[INFOPANEL_SIZE]= { "value_pos_symbol", "value_pos_magic", "value_pos_comment", "value_pos_swap", "value_pos_commission", "value_pos_price", "value_pos_cprice", "value_pos_profit", "value_pos_volume", "value_pos_sl", "value_pos_tp", "value_pos_time", "value_pos_id", "value_pos_type" }; //---
En utilisant ces noms, vous pouvez rechercher par programme l'objet nécessaire dans le graphique et définir ou modifier ses propriétés telles que le texte affiché, la couleur, la taille, etc. De plus, ces noms seront affichés dans la fenêtre Liste d'objets (Ctrl+B) après avoir été créés dans le graphique. Mais vous ne pourrez pas les voir là car les objets créés par le programme MQL5 sont masqués par défaut. Pour les rendre visibles, vous devez cliquer sur List All dans la fenêtre Object List. Cette fonctionnalité permet de séparer les objets créés manuellement de ceux créés par programmation, ce qui est certes très pratique.
De plus, nous aurons besoin de fonctions définies par l'utilisateur qui seront utilisées par l'Expert Advisor pour créer des objets graphiques. La fonction offerte par MQL5 pour la création d'objets graphiques est ObjectCreate(). Mais puisque nous devons également définir les propriétés des objets, alors que les objets eux-mêmes peuvent avoir besoin d'être créés plus d'une fois, il serait préférable de penser à une méthode plus pratique et compacte qui pourrait être implémentée en une seule ligne de code.
Pour créer l'arrière-plan et l'en-tête du panneau d'informations, nous allons utiliser l'objet graphique Edit. Écrivons la fonction CreateEdit() :
//+------------------------------------------------------------------+ //| CREATING THE EDIT OBJECT | //+------------------------------------------------------------------+ void CreateEdit(long chart_id, // chart id int sub_window, // (sub)window number string name, // object name string text, // displayed text ENUM_BASE_CORNER corner, // chart corner string font_name, // font int font_size, // font size color font_color, // font color int x_size, // width int y_size, // height int x_distance, // X-coordinate int y_distance, // Y-coordinate long z_order, // Z-order color background_color, // background color bool read_only) // Read Only flag { // If the object has been created successfully,... if(ObjectCreate(chart_id,name,OBJ_EDIT,sub_window,0,0)) { // ...set its properties ObjectSetString(chart_id,name,OBJPROP_TEXT,text); // displayed text ObjectSetInteger(chart_id,name,OBJPROP_CORNER,corner); // set the chart corner ObjectSetString(chart_id,name,OBJPROP_FONT,font_name); // set the font ObjectSetInteger(chart_id,name,OBJPROP_FONTSIZE,font_size); // set the font size ObjectSetInteger(chart_id,name,OBJPROP_COLOR,font_color); // font color ObjectSetInteger(chart_id,name,OBJPROP_BGCOLOR,background_color); // background color ObjectSetInteger(chart_id,name,OBJPROP_XSIZE,x_size); // width ObjectSetInteger(chart_id,name,OBJPROP_YSIZE,y_size); // height ObjectSetInteger(chart_id,name,OBJPROP_XDISTANCE,x_distance); // set the X coordinate ObjectSetInteger(chart_id,name,OBJPROP_YDISTANCE,y_distance); // set the Y coordinate ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false); // cannot select the object if FALSE ObjectSetInteger(chart_id,name,OBJPROP_ZORDER,z_order); // Z-order of the object ObjectSetInteger(chart_id,name,OBJPROP_READONLY,read_only); // Read Only ObjectSetInteger(chart_id,name,OBJPROP_ALIGN,ALIGN_LEFT); // align left ObjectSetString(chart_id,name,OBJPROP_TOOLTIP,"\n"); // no tooltip if "\n" } }
Maintenant, l'objet graphique Edit (OBJ_EDIT) peut être créé en utilisant une seule ligne de code. Nous allons l'illustrer avec un exemple lors de la création d'une fonction qui définira le panneau d'informations sur le graphique.
Passons maintenant aux objets Text Label qui vont être utilisés pour afficher la liste des propriétés de position et leurs valeurs, et créons la fonction CreateLabel() de la même manière :
//+------------------------------------------------------------------+ //| CREATING THE LABEL OBJECT | //+------------------------------------------------------------------+ void CreateLabel(long chart_id, // chart id int sub_window, // (sub)window number string name, // object name string text, // displayed text ENUM_ANCHOR_POINT anchor, // anchor point ENUM_BASE_CORNER corner, // chart corner string font_name, // font int font_size, // font size color font_color, // font color int x_distance, // X-coordinate int y_distance, // Y-coordinate long z_order) // Z-order { // If the object has been created successfully,... if(ObjectCreate(chart_id,name,OBJ_LABEL,sub_window,0,0)) { // ...set its properties ObjectSetString(chart_id,name,OBJPROP_TEXT,text); // displayed text ObjectSetString(chart_id,name,OBJPROP_FONT,font_name); // set the font ObjectSetInteger(chart_id,name,OBJPROP_COLOR,font_color); // set the font color ObjectSetInteger(chart_id,name,OBJPROP_ANCHOR,anchor); // set the anchor point ObjectSetInteger(chart_id,name,OBJPROP_CORNER,corner); // set the chart corner ObjectSetInteger(chart_id,name,OBJPROP_FONTSIZE,font_size); // set the font size ObjectSetInteger(chart_id,name,OBJPROP_XDISTANCE,x_distance); // set the X-coordinate ObjectSetInteger(chart_id,name,OBJPROP_YDISTANCE,y_distance); // set the Y-coordinate ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false); // cannot select the object if FALSE ObjectSetInteger(chart_id,name,OBJPROP_ZORDER,z_order); // Z-order of the object ObjectSetString(chart_id,name,OBJPROP_TOOLTIP,"\n"); // no tooltip if "\n" } }
Il est également conseillé de consulter les descriptions des fonctions dans MQL5 Reference.
Lorsqu'il est supprimé du graphique, l'Expert Advisor doit à son tour supprimer tous les objets qu'il a précédemment ajoutés au graphique. Pour ce faire, vous pouvez simplement passer le nom de l'objet à la fonction DeleteObjectByName(). Il recherchera ensuite l'objet par le nom spécifié et le supprimera, s'il est trouvé, à l'aide de la fonction intégrée ObjectFind() qui recherche l'objet et de la fonction ObjectDelete() qui supprime l'objet.
//+------------------------------------------------------------------+ //| DELETING THE OBJECT BY NAME | //+------------------------------------------------------------------+ void DeleteObjectByname(string name) { int sub_window=0; // Returns the number of the subwindow where the object is located bool res =false; // Result following an attempt to delete the object //--- Find the object by name sub_window=ObjectFind(ChartID(),name); //--- if(sub_window>=0) // If it has been found,.. { res=ObjectDelete(ChartID(),name); // ...delete it //--- // If an error occurred when deleting the object,.. if(!res) // ...print the relevant message { Print("Error deleting the object: ("+IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError())); } } }
De plus, dans la fonction DeleteObjectByName(), nous implémentons également une vérification des erreurs lors de la suppression d'un objet. Si une erreur se produit, un message pertinent apparaîtra contenant le code et la description de l'erreur. Comme vous pouvez le voir dans le code ci-dessus, nous utilisons une fonction supplémentaire définie par l'utilisateur qui convertit le code d'erreur en description textuelle - la fonction ErrorDescription(). Comme il y a beaucoup de codes d'erreur, je vais illustrer ce qui précède en n'utilisant qu'une partie de cette fonction (voir le code ci-dessous). La version complète du code se trouve dans le fichier de code source joint à cet article.
//+------------------------------------------------------------------+ //| RETURNING THE ERROR DESCRIPTION | //+------------------------------------------------------------------+ string ErrorDescription(int error_code) { string error_string=""; //--- switch(error_code) { //--- Trade server return codes case 10004: error_string="Requote"; break; case 10006: error_string="Request rejected"; break; case 10007: error_string="Request canceled by trader"; break; case 10008: error_string="Order placed"; break; case 10009: error_string="Request executed"; break; case 10010: error_string="Request executed partially"; break; case 10011: error_string="Request processing error"; break; case 10012: error_string="Request timed out"; break; case 10013: error_string="Invalid request"; break; case 10014: error_string="Invalid request volume"; break; case 10015: error_string="Invalid request price"; break; case 10016: error_string="Invalid Stop orders in the request"; break; case 10017: error_string="Trading forbidden"; break; case 10018: error_string="Market is closed"; break; case 10019: error_string="Insufficient funds"; break; case 10020: error_string="Prices changed"; break; case 10021: error_string="No quotes to process the request"; break; case 10022: error_string="Invalid order expiration in the request"; break; case 10023: error_string="Order status changed"; break; case 10024: error_string="Too many requests"; break; case 10025: error_string="No changes in the request"; break; case 10026: error_string="Automated trading is disabled by trader"; break; case 10027: error_string="Automated trading is disabled by the client terminal"; break; case 10028: error_string="Request blocked for processing"; break; case 10029: error_string="Order or position frozen"; break; case 10030: error_string="The specified type of order execution by balance is not supported"; break; case 10031: error_string="No connection with trade server"; break; case 10032: error_string="Transaction is allowed for live accounts only"; break; case 10033: error_string="You have reached the maximum number of pending orders"; break; case 10034: error_string="You have reached the maximum order and position volume for this symbol"; break; ... } //--- return(error_string); }
Dans l'article précédent, nous avons traité de la fonction GetPositionProperties() qui obtient les propriétés de position. Cette fois, la structure de la fonction va être un peu plus complexe. Nous allons vérifier une position actuellement ouverte, le drapeau de présence/absence d'une position ouverte étant stocké dans la variable globale pos_open. Ces informations peuvent être requises dans d'autres fonctions, sans avoir à appeler la fonction PositionSelect() à chaque fois.
Ensuite, si une position ouverte existe, nous obtiendrons ses propriétés, sinon toutes les variables seront mises à zéro. Écrivons maintenant une simple fonction ZeroPositionProperties() :
//+------------------------------------------------------------------+ //| ZEROING OUT VARIABLES FOR POSITION PROPERTIES | //+------------------------------------------------------------------+ void ZeroPositionProperties() { pos_symbol =""; pos_comment =""; pos_magic =0; pos_price =0.0; pos_cprice =0.0; pos_sl =0.0; pos_tp =0.0; pos_type =WRONG_VALUE; pos_volume =0.0; pos_commission =0.0; pos_swap =0.0; pos_profit =0.0; pos_time =NULL; pos_id =0; }
De plus, à la fin de la fonction GetPositionProperties(), nous appellerons une fonction SetInfoPanel() définie par l'utilisateur qui dessine/met à jour le panneau d'informations dans le graphique.
//+------------------------------------------------------------------+ //| GETTING POSITION PROPERTIES | //+------------------------------------------------------------------+ void GetPositionProperties() { // Check if there is an open position pos_open=PositionSelect(_Symbol); //--- if(pos_open) // If an open position exists, get its properties { pos_symbol =PositionGetString(POSITION_SYMBOL); pos_comment =PositionGetString(POSITION_COMMENT); pos_magic =PositionGetInteger(POSITION_MAGIC); pos_price =PositionGetDouble(POSITION_PRICE_OPEN); pos_cprice =PositionGetDouble(POSITION_PRICE_CURRENT); pos_sl =PositionGetDouble(POSITION_SL); pos_tp =PositionGetDouble(POSITION_TP); pos_type =(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); pos_volume =PositionGetDouble(POSITION_VOLUME); pos_commission =PositionGetDouble(POSITION_COMMISSION); pos_swap =PositionGetDouble(POSITION_SWAP); pos_profit =PositionGetDouble(POSITION_PROFIT); pos_time =(datetime)PositionGetInteger(POSITION_TIME); pos_id =PositionGetInteger(POSITION_IDENTIFIER); } else // If there is no open position, zero out variables for position properties ZeroPositionProperties(); //--- SetInfoPanel(); // Set/update the info panel }
Écrivons maintenant la fonction SetInfoPanel(). Ci-dessous le code de la fonction avec des commentaires détaillés :
//+------------------------------------------------------------------+ //| SETTING THE INFO PANEL | //|------------------------------------------------------------------+ void SetInfoPanel() { int y_bg=18; // Y-coordinate for the background and header int y_property=32; // Y-coordinate for the list of properties and their values int line_height=12; // Line height //--- int font_size=8; // Font size string font_name="Calibri"; // Font color font_color=clrWhite; // Font color //--- ENUM_ANCHOR_POINT anchor=ANCHOR_RIGHT_UPPER; // Anchor point in the top right corner ENUM_BASE_CORNER corner=CORNER_RIGHT_UPPER; // Origin of coordinates in the top right corner of the chart //--- X-coordinates int x_first_column=120; // First column (names of properties) int x_second_column=10; // Second column (values of properties) //--- Array of Y-coordinates for the names of position properties and their values int y_prop_array[INFOPANEL_SIZE]={0}; //--- Fill the array with coordinates for each line on the info panel y_prop_array[0]=y_property; y_prop_array[1]=y_property+line_height; y_prop_array[2]=y_property+line_height*2; y_prop_array[3]=y_property+line_height*3; y_prop_array[4]=y_property+line_height*4; y_prop_array[5]=y_property+line_height*5; y_prop_array[6]=y_property+line_height*6; y_prop_array[7]=y_property+line_height*7; y_prop_array[8]=y_property+line_height*8; y_prop_array[9]=y_property+line_height*9; y_prop_array[10]=y_property+line_height*10; y_prop_array[11]=y_property+line_height*11; y_prop_array[12]=y_property+line_height*12; y_prop_array[13]=y_property+line_height*13; //--- Background of the info panel CreateEdit(0,0,"InfoPanelBackground","",corner,font_name,8,clrWhite,230,190,231,y_bg,0,C'15,15,15',true); //--- Header of the info panel CreateEdit(0,0,"InfoPanelHeader","POSITION PROPERTIES",corner,font_name,8,clrWhite,230,14,231,y_bg,1,clrFireBrick,true); //--- List of the names of position properties and their values // Property name CreateLabel(0,0,pos_prop_names[0],"Symbol :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[0],2); // Property value CreateLabel(0,0,pos_prop_values[0],GetValInfoPanel(0),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[0],2); //--- CreateLabel(0,0,pos_prop_names[1],"Magic Number :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[1],2); CreateLabel(0,0,pos_prop_values[1],GetValInfoPanel(1),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[1],2); //--- CreateLabel(0,0,pos_prop_names[2],"Comment :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[2],2); CreateLabel(0,0,pos_prop_values[2],GetValInfoPanel(2),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[2],2); //--- CreateLabel(0,0,pos_prop_names[3],"Swap :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[3],2); CreateLabel(0,0,pos_prop_values[3],GetValInfoPanel(3),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[3],2); //--- CreateLabel(0,0,pos_prop_names[4],"Commission :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[4],2); CreateLabel(0,0,pos_prop_values[4],GetValInfoPanel(4),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[4],2); //--- CreateLabel(0,0,pos_prop_names[5],"Open Price :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[5],2); CreateLabel(0,0,pos_prop_values[5],GetValInfoPanel(5),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[5],2); //--- CreateLabel(0,0,pos_prop_names[6],"Current Price :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[6],2); CreateLabel(0,0,pos_prop_values[6],GetValInfoPanel(6),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[6],2); //--- CreateLabel(0,0,pos_prop_names[7],"Profit :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[7],2); CreateLabel(0,0,pos_prop_values[7],GetValInfoPanel(7),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[7],2); //--- CreateLabel(0,0,pos_prop_names[8],"Volume :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[8],2); CreateLabel(0,0,pos_prop_values[8],GetValInfoPanel(8),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[8],2); //--- CreateLabel(0,0,pos_prop_names[9],"Stop Loss :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[9],2); CreateLabel(0,0,pos_prop_values[9],GetValInfoPanel(9),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[9],2); //--- CreateLabel(0,0,pos_prop_names[10],"Take Profit :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[10],2); CreateLabel(0,0,pos_prop_values[10],GetValInfoPanel(10),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[10],2); //--- CreateLabel(0,0,pos_prop_names[11],"Time :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[11],2); CreateLabel(0,0,pos_prop_values[11],GetValInfoPanel(11),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[11],2); //--- CreateLabel(0,0,pos_prop_names[12],"Identifier :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[12],2); CreateLabel(0,0,pos_prop_values[12],GetValInfoPanel(12),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[12],2); //--- CreateLabel(0,0,pos_prop_names[13],"Type :",anchor,corner,font_name,font_size,font_color,x_first_column,y_prop_array[13],2); CreateLabel(0,0,pos_prop_values[13],GetValInfoPanel(13),anchor,corner,font_name,font_size,font_color,x_second_column,y_prop_array[13],2); //--- ChartRedraw(); // Redraw the chart }
Examinons de plus près la fonction SetInfoPanel(). Les variables qui ont à voir avec les propriétés des objets graphiques (coordonnées, couleur, police, texte affiché, etc.) sont déclarées au début de la fonction. Faites attention au processus de remplissage du tableau de coordonnées Y pour la liste des propriétés de position sur le panneau d'informations. Il est mis en œuvre d'une manière qui est claire pour les débutants. Mais cela peut être réduit à quelques lignes de code lors de l'utilisation d'une boucle. Vous pouvez l'écrire comme suit :
//--- Fill the array with coordinates for each line on the info panel for(int i=0; i<INFOPANEL_SIZE; i++) { if(i==0) y_prop_array[i]=y_property; else y_prop_array[i]=y_property+line_height*i; }
Ensuite, toutes les propriétés des objets qui doivent être affichés sur le panneau doivent être spécifiées dans les paramètres des fonctions CreateLabel() et CreateEdit() créées précédemment, en prenant un objet à la fois. La liste entière peut également être implémentée en quelques lignes de code à l'aide d'une boucle. Pour ce faire, nous devons créer un autre tableau pour les objets qui affichent le texte des noms des propriétés de position dans le graphique. Que ce soit votre devoir.
La fonction GetPropertyValue() qui reçoit le numéro d'objet renvoie la valeur qui est ensuite transmise à la fonction CreateLabel() comme quatrième paramètre (texte affiché). Cela concerne tous les objets qui afficheront des valeurs de propriétés de position. La valeur renvoyée par la fonction est une valeur de chaîne ajustée qui sera finalement affichée sur le panneau. Ci-dessous le code de la fonction avec des commentaires détaillés :
//+------------------------------------------------------------------+ //| RETURNING THE STRING WITH POSITION PROPERTY VALUE | //+------------------------------------------------------------------+ string GetPropertyValue(int number) { //--- Sign indicating the lack of an open position or a certain property // E.g. the lack of a comment, Stop Loss or Take Profit string empty="-"; //--- If an open position exists, return the value of the requested property if(pos_open) { switch(number) { case 0 : return(pos_symbol); break; case 1 : return(IntegerToString((int)pos_magic)); break; //--- return the value of the comment, if any, otherwise return the sign indicating the lack of comment case 2 : return(pos_comment!="" ? pos_comment : empty); break; case 3 : return(DoubleToString(pos_swap,2)); break; case 4 : return(DoubleToString(pos_commission,2)); break; case 5 : return(DoubleToString(pos_price,_Digits)); break; case 6 : return(DoubleToString(pos_cprice,_Digits)); break; case 7 : return(DoubleToString(pos_profit,2)); break; case 8 : return(DoubleToString(pos_volume,2)); break; case 9 : return(pos_sl!=0.0 ? DoubleToString(pos_sl,_Digits) : empty); break; case 10 : return(pos_tp!=0.0 ? DoubleToString(pos_tp,_Digits) : empty); break; case 11 : return(TimeToString(pos_time,TIME_DATE|TIME_MINUTES)); break; case 12 : return(IntegerToString((int)pos_id)); break; case 13 : return(PositionTypeToString(pos_type)); break; default : return(empty); } } //--- // If there is no open position, return the sign indicating the lack of the open position "-" return(empty); }
Le code ci-dessus suggère qu'une certaine valeur est préparée pour chaque nombre passé à la fonction, à condition qu'il y ait une position ouverte. S'il n'y a actuellement aucune position ouverte, la fonction renverra un tiret (-) affiché pour tous les objets qui ont à voir avec les valeurs de propriété de position.
À la fin de la fonction SetInfoPanel(), nous appelons la fonction ChartRedraw() conçue pour un rafraîchissement forcé du graphique. À moins qu'il ne soit appelé, vous ne pourrez pas voir les modifications apportées.
Nous devons maintenant écrire une fonction qui supprimera tous les objets graphiques créés par l'Expert Advisor. Appelons-le DeleteInfoPanel() :
//+------------------------------------------------------------------+ //| DELETING THE INFO PANEL | //+------------------------------------------------------------------+ void DeleteInfoPanel() { DeleteObjectByName("InfoPanelBackground"); // Delete the panel background DeleteObjectByName("InfoPanelHeader"); // Delete the panel header //--- Delete position properties and their values for(int i=0; i<INFOPANEL_SIZE; i++) { DeleteObjectByName(pos_prop_names[i]); // Delete the property DeleteObjectByName(pos_prop_values[i]); // Delete the value } //--- ChartRedraw(); // Redraw the chart }
Il ne nous reste plus qu'à répartir les méthodes que nous avons créées parmi les fonctions principales de l'Expert Advisor qui étaient à l'origine présentes dans le modèle après l'avoir créé dans l’assistant MQL5 Wizard. C'est la partie la plus facile :
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Get the properties and set the panel GetPositionProperties(); //--- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Print the deinitialization reason to the journal Print(GetDeinitReasonText(reason)); //--- When deleting from the chart if(reason==REASON_REMOVE) //--- Delete all objects relating to the info panel from the chart DeleteInfoPanel(); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Get the properties and update the values on the panel GetPositionProperties(); } //+------------------------------------------------------------------+
La seule chose sur laquelle vous pourriez tomber est la fonction GetDeinitReasonText() qui renvoie une description textuelle du code de motif de désinitialisation :
//+---------------------------------------------------------------------+ //| RETURNING A TEXTUAL DESCRIPTION OF THE DEINITIALIZATION REASON CODE | //+---------------------------------------------------------------------+ string GetDeinitReasonText(int reason_code) { string text=""; //--- switch(reason_code) { case REASON_PROGRAM : // 0 text="The Expert Advisor has stopped working calling the ExpertRemove() function."; break; case REASON_REMOVE : // 1 text="The '"+EXPERT_NAME+"' program has been removed from the chart."; break; case REASON_RECOMPILE : // 2 text="The '"+EXPERT_NAME+"' program has been recompiled."; break; case REASON_CHARTCHANGE : // 3 text="Chart symbol or period has been changed."; break; case REASON_CHARTCLOSE : // 4 text="The chart is closed."; break; case REASON_PARAMETERS : // 5 text="Input parameters have been changed by the user."; break; case REASON_ACCOUNT : // 6 text="A different account has been activated."; break; case REASON_TEMPLATE : // 7 text="A different chart template has been applied."; break; case REASON_INITFAILED : // 8 text="A flag specifying that the OnInit() handler returned zero value."; break; case REASON_CLOSE : // 9 text="The terminal has been closed."; break; default : text="The reason is undefined."; } //--- return text; }
Si vous essayez d'utiliser l'Expert Advisor sur le symbole du graphique qui n'a actuellement aucune position ouverte, vous verrez des tirets au lieu des valeurs de propriété de position sur le panneau. Le panneau aura le même aspect après avoir fermé une certaine position.
Fig. 2. Panneau d'information en l'absence de position ouverte.
Si l'Expert Advisor est ajouté au graphique du symbole qui a une position ouverte ou si une position est ouverte après avoir ajouté l'Expert Advisor au graphique, tous les tirets seront remplacés par les valeurs de propriété de position appropriées :
Fig. 3. Panneau d'information affichant les propriétés de la position ouverte.
Il y a une petite particularité. Après avoir fermé la position, ce n'est qu'à la nouvelle coche que les valeurs sur le panneau sont mises à jour. Il existe un moyen de mettre les valeurs à jour immédiatement, mais ce qui doit être fait pour mettre en œuvre cela sera discuté dans le prochain article de la série.
Conclusion
Certaines des fonctions présentées dans cet article seront également utilisées dans les articles suivants de la série MQL5 Cookbook, tandis que d'autres seront modifiées et améliorées en fonction de la tâche à accomplir. Il est conseillé de lire les articles dans l'ordre, l'un après l'autre car chaque nouvel article est la suite logique du précédent. Cela dépend certainement aussi de votre niveau de compétence et de compétences, il peut donc être plus raisonnable et intéressant de commencer par des publications plus récentes.
Le fichier de code source est joint à l'article.
Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/641
- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation