English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Manuale MQL5: Proprietà di posizione nel pannello delle informazioni personalizzate

Manuale MQL5: Proprietà di posizione nel pannello delle informazioni personalizzate

MetaTrader 5Esempi | 11 gennaio 2022, 16:41
101 0
Anatoli Kazharski
Anatoli Kazharski

Introduzione

Questa volta creeremo un semplice Expert Advisor che otterrà le proprietà della posizione sul simbolo corrente e le visualizzerà sul pannello informativo personalizzato durante il trading manuale. Il pannello informativo verrà creato utilizzando oggetti grafici e le informazioni visualizzate verranno aggiornate ad ogni tick. Questo sarà molto più conveniente rispetto al dover eseguire manualmente lo script descritto nel precedente articolo della serie chiamata "Manuale MQL5: Ottenere le Proprietà di posizione.

 

Sviluppare un Expert Advisor

Cominciamo con gli oggetti grafici. Per creare il pannello delle informazioni, abbiamo bisogno di oggetti per lo sfondo, l'intestazione, i nomi e i valori delle proprietà di posizione. Lo sfondo e l'intestazione richiederanno un rettangolo che non si muove col prezzo. Il rettangolo può essere creato utilizzando oggetti grafici come Rectangle Label o Modifica, mentre i nomi ei valori delle proprietà dell'oggetto verranno creati utilizzando Etichette di testo.

Prima di procedere con il codice, prepariamo un layout per il pannello informativo. La sua comodità sta nel fatto che possiamo modificare rapidamente qualsiasi proprietà nella finestra delle impostazioni e personalizzare l'aspetto del pannello delle informazioni.

Ogni oggetto ha una finestra delle impostazioni che può essere aperta dal menu contestuale di un oggetto selezionato. La finestra delle impostazioni può essere aperta anche dall'Elenco oggetti (Ctrl+B) selezionando l'oggetto richiesto e facendo clic su Proprietà. Il layout del pannello delle informazioni è mostrato di seguito. Può anche essere utilizzato per stimare dimensioni e coordinate durante la scrittura di un codice. Quando il codice per il pannello informativo è pronto, dovrai eliminare manualmente gli oggetti del layout poiché l'Expert Advisor non sarà in grado di "vederli" e quindi non li rimuoverà dal grafico.

Fig. 1. Preparazione del layout per il pannello informativo.

Fig. 1. Preparazione del layout per il pannello informazioni.

Ora dobbiamo creare un modello per l'Expert Advisor. Questo può essere fatto velocemente come per lo script. Nella procedura guidata MQL5, l'opzione Expert Advisor (modello) è selezionata per impostazione predefinita. Eseguiamo i passaggi successivi senza apportare modifiche alle opzioni poiché questa volta non sono necessarie. Quindi fai clic su Fine e vedrai un modello come di seguito:

//+------------------------------------------------------------------+
//|                                      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()
  {
//---
   
  }
//+------------------------------------------------------------------+

Si può notare subito che il modello Expert Advisor è diverso dal modello di script. Oltre alle proprietà del programma (#property), ci sono tre funzioni principali: OnInit(), OnDeinit() e OnTick().

La funzione OnInit() viene chiamata durante il caricamento del programma, la modifica dei parametri esterni, la compilazione del programma, a condizione che il programma sia in quel momento aggiunto al grafico e quando si modifica il simbolo o il punto. Se necessario, puoi inizializzare determinate variabili o array in questa funzione per poterci lavorare in seguito.

La funzione OnDeinit() viene chiamata quando si elimina il programma dal grafico, si cambia conto, simbolo o periodo. Tutti i possibili motivi di deinizializzazione sono forniti nel riferimento MQL5. Questo Expert Advisor utilizzerà una funzione definita dall'utente, GetDeinitReasonText(), che converte in testo l'identificatore del motivo della deinizializzazione (il parametro della funzione OnDeinit()).

E infine, la funzione OnTick(). Viene chiamato ogni volta che c'è un nuovo segno di spunta sul simbolo sul cui grafico l'Expert Advisor sta attualmente operando.

Ora prepariamo tutte le costanti, le variabili e gli array che utilizzeremo nell'Expert Advisor. Li collocheremo all'inizio del programma. Innanzitutto, definisci le variabili i cui valori rimangono invariati per tutto il programma:

//---
#define INFOPANEL_SIZE 14 // Size of the array for info panel objects
#define EXPERT_NAME MQL5InfoString(MQL5_PROGRAM_NAME) // Name of the Expert Advisor
//---

Seguono le variabili globali per le proprietà di posizione:

//--- 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

Dopo le variabili, dichiareremo array di nomi di oggetti grafici. Questi oggetti visualizzeranno le proprietà di posizione ei loro valori nel grafico. A questo scopo, creeremo due array di stringhe e inizializzeremo immediatamente i loro elementi in valori. Tra parentesi quadre, utilizziamo il valore della costante INFOPANEL_SIZE dichiarata all'inizio del programma. Cioè, ci saranno 14 elementi in ogni array.

// 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"
  };
//---

Usando questi nomi, puoi trovare programmaticamente l'oggetto necessario nel grafico e impostare o modificare le sue proprietà come testo visualizzato, colore, dimensione, ecc. Inoltre, questi nomi verranno visualizzati nella finestra Elenco oggetti (Ctrl+B) dopo essere stati creati nel grafico. Ma non sarai in grado di vederli lì poiché gli oggetti creati dal programma MQL5 sono nascosti per impostazione predefinita. Per renderli visibili, dovresti fare clic su Elenca tutto nella finestra Elenco oggetti. Questa funzione aiuta a separare gli oggetti creati manualmente da quelli creati a livello di codice, il che è certamente molto conveniente.

Inoltre, avremo bisogno di funzioni definite dall'utente che verranno impiegate dall'Expert Advisor per creare oggetti grafici. La funzione offerta da MQL5 per la creazione di oggetti grafici è ObjectCreate(). Ma poiché occorre impostare anche le proprietà degli oggetti, mentre gli oggetti stessi potrebbero dover essere creati più di una volta, sarebbe meglio pensare a un metodo più comodo e compatto che possa essere implementato in una singola riga di codice.

Per creare lo sfondo e l'intestazione del pannello delle informazioni, utilizzeremo l'oggetto grafico Modifica. Scriviamo la funzione 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"
     }
  }

Ora l'oggetto grafico Edit (OBJ_EDIT) può essere creato utilizzando una singola riga di codice. Lo illustreremo con un esempio durante la creazione di una funzione che imposterà il pannello informativo sul grafico.

Passiamo ora agli oggetti Etichetta di testo che verranno utilizzati per visualizzare l'elenco delle proprietà di posizione e i loro valori e creiamo la funzione CreateLabel() in modo simile:

//+------------------------------------------------------------------+
//| 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"
     }
  }

Si consiglia inoltre di dare un'occhiata alle descrizioni delle funzioni in MQL5 Reference.

Quando viene eliminato dal grafico, Expert Advisor deve a sua volta eliminare tutti gli oggetti che ha precedentemente aggiunto al grafico. Per fare ciò, puoi semplicemente passare il nome dell'oggetto alla funzione DeleteObjectByName(). Quindi cercherà l'oggetto in base al nome specificato e lo eliminerà, se trovato, utilizzando la funzione ObjectFind() incorporata che cerca l'oggetto e la funzione ObjectDelete() che elimina l'oggetto.

//+------------------------------------------------------------------+
//| 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()));
        }
     }
  }

Inoltre, nella funzione DeleteObjectByName(), implementiamo anche un controllo degli errori durante l'eliminazione di un oggetto. Se si verifica un errore, apparirà un messaggio relativo contenente il codice di errore e la descrizione. Come puoi vedere nel codice sopra, utilizziamo una funzione aggiuntiva definita dall'utente che converte il codice di errore in una descrizione testuale: la funzione ErrorDescription(). Poiché ci sono molti codici di errore, esemplificherò quanto sopra utilizzando solo una parte di questa funzione (vedi il codice sotto). La versione completa del codice è disponibile nel file del codice sorgente allegato a questo articolo.

//+------------------------------------------------------------------+
//| 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);
  }

Nell'articolo precedente ci siamo occupati della funzione GetPositionProperties() che ottiene le proprietà di posizione. Questa volta la struttura della funzione sarà un po' più complessa. Verificheremo una posizione attualmente aperta, con il flag di presenza/assenza di una posizione aperta memorizzato nella variabile globale pos_open. Queste informazioni possono essere richieste in altre funzioni, senza dover chiamare ogni volta la funzione PositionSelect().

Quindi, se esiste una posizione aperta, otterremo le sue proprietà, altrimenti tutte le variabili verranno azzerate. Ora scriviamo una semplice funzione 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;
  }

Inoltre, alla fine della funzione GetPositionProperties(), chiameremo una funzione SetInfoPanel() definita dall'utente che disegna/aggiorna il pannello delle informazioni nel grafico.

//+------------------------------------------------------------------+
//| 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
  }

Scriviamo ora la funzione SetInfoPanel(). Di seguito il codice della funzione con commenti dettagliati:

//+------------------------------------------------------------------+
//| 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
  }

Diamo un'occhiata più da vicino alla funzione SetInfoPanel(). Le variabili che hanno a che fare con le proprietà degli oggetti grafici (coordinate, colore, font, testo visualizzato, ecc.) sono dichiarate all'inizio della funzione. Prestare attenzione al processo di riempimento dell'array di coordinate Y per l'elenco delle proprietà di posizione nel pannello delle informazioni. È implementato in modo chiaro ai principianti. Ma può essere ridotto a un paio di righe di codice quando si utilizza un ciclo. Puoi scriverlo come segue:

//--- 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;
     }

Quindi, tutte le proprietà degli oggetti che devono essere visualizzate sul pannello devono essere specificate nei parametri delle funzioni CreateLabel() e CreateEdit() create in precedenza, prendendo un oggetto alla volta. L'intero elenco può anche essere implementato in poche righe di codice utilizzando un ciclo. Per fare ciò, dobbiamo creare un altro array per gli oggetti che visualizzano il testo dei nomi delle proprietà di posizione nel grafico. Pensalo come un compito.

La funzione GetPropertyValue() che riceve il numero dell'oggetto restituisce il valore che viene quindi passato alla funzione CreateLabel() come quarto parametro (testo visualizzato). Ciò riguarda tutti gli oggetti che visualizzeranno i valori delle proprietà di posizione. Il valore restituito dalla funzione è un valore di stringa modificato che verrà infine visualizzato sul pannello. Di seguito il codice della funzione con commenti dettagliati:

//+------------------------------------------------------------------+
//| 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);
  }

Il codice sopra suggerisce che viene preparato un certo valore per ogni numero passato alla funzione, a condizione che ci sia una posizione aperta. Se al momento non è presente alcuna posizione aperta, la funzione restituirà un trattino (-) visualizzato per tutti gli oggetti che hanno a che fare con i valori della proprietà di posizione.

Alla fine della funzione SetInfoPanel(), chiamiamo la funzione ChartRedraw() progettata per un ridisegno forzato del grafico. A meno che non venga chiamato, non sarai in grado di vedere le modifiche apportate.

Ora dobbiamo scrivere una funzione che cancellerà tutti gli oggetti grafici creati dall'Expert Advisor. Chiamiamolo 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
  }

Ora non ci resta che distribuire i metodi che abbiamo creato tra le principali funzioni dell'Expert Advisor che erano originariamente presenti nel template dopo averlo creato in MQL5 Wizard. Questa è la parte più semplice:

//+------------------------------------------------------------------+
//| 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();

  }
//+------------------------------------------------------------------+

L'unica cosa in cui potresti imbatterti è la funzione GetDeinitReasonText() che restituisce una descrizione testuale del codice motivo della deinizializzazione:

//+---------------------------------------------------------------------+
//| 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;
  }

Se provi a utilizzare l'Expert Advisor sul simbolo del grafico che attualmente non ha una posizione aperta, vedrai dei trattini invece dei valori delle proprietà della posizione sul pannello. Il pannello avrà lo stesso aspetto dopo aver chiuso una determinata posizione.

Fig. 2. Pannello informativo in assenza di posizione aperta.

Fig. 2. Pannello informativo in assenza di posizione aperta.

Se l'Expert Advisor viene aggiunto al grafico del simbolo che ha una posizione aperta o se una posizione viene aperta dopo aver aggiunto l'Expert Advisor al grafico, tutti i trattini verranno sostituiti con i valori appropriati della proprietà di posizione:

Fig. 3. Pannello informativo che mostra le proprietà della posizione aperta.

Fig. 3. Pannello informativo che mostra le proprietà della posizione aperta.

C'è una piccola particolarità. Dopo aver chiuso la posizione, i valori sul pannello vengono aggiornati solo al nuovo tick. Esiste un modo per aggiornare immediatamente i valori, ma ciò che è necessario fare per implementarlo verrà discusso nel prossimo articolo della serie.

 

Conclusione

Alcune delle funzioni introdotte in questo articolo verranno utilizzate anche nei successivi articoli della serie Manuale MQL5, mentre altre verranno modificate e migliorate a seconda dell'attività da svolgere. Si consiglia di leggere gli articoli in ordine, uno dopo l'altro in quanto ogni nuovo articolo è una logica continuazione del precedente. Sicuramente dipende anche dal tuo livello di competenza e abilità, quindi potrebbe essere più ragionevole e interessante iniziare con pubblicazioni più recenti. 

Il file del codice sorgente è allegato all'articolo.

Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/641

File allegati |
Manuale MQL5: Analisi delle proprietà di posizione nel tester di strategia MetaTrader 5 Manuale MQL5: Analisi delle proprietà di posizione nel tester di strategia MetaTrader 5
Presenteremo una versione modificata dell'Expert Advisor dal precedente articolo "Manuale MQL5: Proprietà posizione nel pannello Informazioni personalizzate". Alcuni dei problemi che affronteremo includono l'ottenimento di dati dalle barre, il controllo di nuovi eventi di barra sul simbolo corrente, inclusa una classe commerciale della libreria standard in un file, la creazione di una funzione per la ricerca di segnali di trading e una funzione per l'esecuzione di operazioni di trading, nonché la determinazione degli eventi commerciali nella funzione OnTrade ().
Manuale MQL5: Ottenere Proprietà di Posizione Manuale MQL5: Ottenere Proprietà di Posizione
In questo articolo, creeremo uno script che ottiene tutte le proprietà di posizione e le mostra all'utente in una finestra di dialogo. Durante l'esecuzione dello script, sarà possibile selezionare tra due modalità disponibili nell'elenco a discesa nei parametri esterni: visualizzare le proprietà di posizione solo sul simbolo corrente o visualizzare le proprietà di posizione su tutti i simboli.
Manuale MQL5: Come evitare errori durante l'impostazione/modifica dei livelli di trading Manuale MQL5: Come evitare errori durante l'impostazione/modifica dei livelli di trading
In continuazione del nostro lavoro sull'Expert Advisor dal precedente articolo della serie chiamata "Manuale MQL5: Analizzando le proprietà della posizione nel tester di strategia MetaTrader 5", lo miglioreremo con un sacco di funzioni utili, oltre a migliorare e ottimizzare quelle esistenti. L'Expert Advisor questa volta avrà parametri esterni che possono essere ottimizzati nel MetaTrader 5 Strategy Tester e in qualche modo assomiglierà a un semplice sistema di trading.
Manuale MQL5: Utilizzo di diverse modalità di stampa Manuale MQL5: Utilizzo di diverse modalità di stampa
Questo è il primo articolo della serie Manuale MQL5. Inizierò con semplici esempi per permettere a chi sta muovendo i primi passi nella programmazione di familiarizzare gradualmente con il nuovo linguaggio. Ricordo i miei primi sforzi nel progettare e programmare sistemi di trading che posso dire sono stati piuttosto difficili, dato che è stato il primo linguaggio di programmazione della mia vita. Tuttavia, si è rivelato più semplice di quanto pensassi e mi ci sono voluti solo pochi mesi prima di poter sviluppare un programma abbastanza complesso.