English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Manuale MQL5: La cronologia delle offerte e la libreria di funzioni per ottenere proprietà di posizione

Manuale MQL5: La cronologia delle offerte e la libreria di funzioni per ottenere proprietà di posizione

MetaTrader 5Esempi | 11 gennaio 2022, 16:44
114 0
Anatoli Kazharski
Anatoli Kazharski

Introduzione

È il momento di riassumere brevemente le informazioni fornite nei precedenti articoli sulle proprietà della posizione. In questo articolo creeremo alcune funzioni aggiuntive per ottenere le proprietà che possono essere ottenute solo dopo aver effettuato l'accesso alla cronologia delle offerte. Acquisiremo anche familiarità con le strutture dati che ci consentiranno di accedere alle proprietà di posizione e simbolo in modo più comodo.

I sistemi di trading in cui i volumi delle posizioni rimangono gli stessi per tutta la loro esistenza non richiedono realmente l'uso delle funzioni che verranno fornite in questo articolo. Ma se hai intenzione di implementare un sistema di gestione del denaro e controllare la dimensione del lotto di una posizione nella tua strategia di trading in una fase successiva, queste funzioni saranno indispensabili.

Prima di iniziare, vorrei dare un suggerimento a quei lettori che hanno seguito un collegamento a questo articolo, mentre visitavano per la prima volta questo sito Web o hanno appena iniziato a imparare il linguaggio MQL5, per iniziare con i precedenti articoli del " Manuale MQL5".


Sviluppo di Expert Advisor

Per poter vedere il funzionamento delle nuove funzioni nell'Expert Advisor modificato nel precedente articolo chiamato "MQL5 Cookbook: Come evitare errori durante l'impostazione/modifica dei livelli commerciali", aggiungeremo la possibilità di aumentare il volume della posizione se si verifica nuovamente un segnale di apertura, mentre la posizione è già presente.

Potrebbero esserci diverse operazioni nella cronologia delle posizioni e, se si sono verificati cambiamenti nel volume della posizione nel corso del trading, devono esserci stati anche cambiamenti nel prezzo della posizione corrente. Per conoscere il prezzo del primo punto di ingresso, dobbiamo accedere allo storico delle trattative rispetto a quella specifica posizione. La figura seguente è una dimostrazione del caso in cui una posizione ha una sola operazione (punto di ingresso):

Fig. 1. Primo affare in posizione

Fig. 1. Primo deal nella posizione.

La figura successiva mostra una variazione del prezzo della posizione dopo la seconda operazione:

Fig. 2. Secondo affare in posizione

Fig. 2. Secondo affare nella posizione.

Come dimostrato negli articoli precedenti, gli identificatori standard consentono di ottenere solo il prezzo della posizione corrente (POSITION_PRICE_OPEN) e il prezzo corrente di un simbolo (proprietà della posizione: POSITION_PRICE_CURRENT) per cui viene aperta una posizione.

Tuttavia, in alcuni sistemi di negoziazione è necessario conoscere la distanza coperta dal prezzo dal primo punto di ingresso, nonché il prezzo dell'ultima transazione. Tutte queste informazioni sono disponibili nella cronologia delle trattative/ordini dell'account. Di seguito l'elenco delle offerte associate alla figura precedente:

Fig. 3. La cronologia delle trattative nel conto

Fig. 3. La cronologia delle trattative nel conto.

Credo che ora la situazione sia chiara e tutti gli obiettivi siano fissati. Continuiamo a modificare l'Expert Advisor presente negli articoli precedenti. Innanzitutto, aggiungeremo nuovi identificatori numerati 0, 6, 9, 12 e 16 all'enumerazione delle proprietà di posizione:

//--- Enumeration of position properties
enum ENUM_POSITION_PROPERTIES
  {
   P_TOTAL_DEALS     = 0,
   P_SYMBOL          = 1,
   P_MAGIC           = 2,
   P_COMMENT         = 3,
   P_SWAP            = 4,
   P_COMMISSION      = 5,
   P_PRICE_FIRST_DEAL= 6,
   P_PRICE_OPEN      = 7,
   P_PRICE_CURRENT   = 8,
   P_PRICE_LAST_DEAL = 9,
   P_PROFIT          = 10,
   P_VOLUME          = 11,
   P_INITIAL_VOLUME  = 12,
   P_SL              = 13,
   P_TP              = 14,
   P_TIME            = 15,
   P_DURATION        = 16,
   P_ID              = 17,
   P_TYPE            = 18,
   P_ALL             = 19
  };

I commenti per ciascuna delle proprietà verranno forniti in una struttura che verrà esaminata un po' più in basso.

Aumentiamo il numero dei parametri esterni. Ora, saremo in grado di specificare:

  • MagicNumber - un ID univoco dell'Expert Advisor (numero magico);
  • Deviazione - slittamento;
  • VolumeIncrease - un valore di cui verrà aumentato il volume della posizione;
  • InfoPanel - un parametro che permette di abilitare/disabilitare la visualizzazione del pannello info.

Ecco come viene implementato:

//--- External parameters of the Expert Advisor
sinput   long        MagicNumber=777;     // Magic number
sinput   int         Deviation=10;        // Slippage
input    int         NumberOfBars=2;      // Number of Bullish/Bearish bars for a Buy/Sell
input    double      Lot=0.1;             // Lot
input    double      VolumeIncrease=0.1;  // Position volume increase
input    double      StopLoss=50;         // Stop Loss
input    double      TakeProfit=100;      // Take Profit
input    double      TrailingStop=10;     // Trailing Stop
input    bool        Reverse=true;        // Position reversal
sinput   bool        ShowInfoPanel=true;  // Display of the info panel

Si prega di notare i parametri le cui sinput è impostato. Questo modificatore consente di disabilitare l'ottimizzazione in Strategy Tester. In effetti, quando si sviluppa un programma per uso personale, si ha una perfetta comprensione di quali parametri influenzeranno il risultato finale, quindi è sufficiente deselezionarli dall'ottimizzazione. Ma quando si tratta di un numero molto elevato di parametri, questo metodo consente di separarli visivamente dagli altri man mano che vengono visualizzati in grigio:

Fig. 4. I parametri disabilitati per l'ottimizzazione sono visualizzati in grigio

Fig. 4. I parametri disabilitati per l'ottimizzazione sono disattivati.

Sostituiamo ora le variabili globali che memorizzavano i valori delle proprietà di posizione e simbolo con strutture di dati (struct):

//--- Position properties
struct position_properties
  {
   uint              total_deals;      // Number of deals
   bool              exists;           // Flag of presence/absence of an open position
   string            symbol;           // Symbol
   long              magic;            // Magic number
   string            comment;          // Comment
   double            swap;             // Swap
   double            commission;       // Commission   
   double            first_deal_price; // Price of the first deal in the position
   double            price;            // Current position price
   double            current_price;    // Current price of the position symbol      
   double            last_deal_price;  // Price of the last deal in the position
   double            profit;           // Profit/Loss of the position
   double            volume;           // Current position volume
   double            initial_volume;   // Initial position volume
   double            sl;               // Stop Loss of the position
   double            tp;               // Take Profit of the position
   datetime          time;             // Position opening time
   ulong             duration;         // Position duration in seconds
   long              id;               // Position identifier
   ENUM_POSITION_TYPE type;            // Position type
  };
//--- Symbol properties
struct symbol_properties
  {
   int               digits;        // Number of decimal places in the price
   int               spread;        // Spread in points
   int               stops_level;   // Stops level
   double            point;         // Point value
   double            ask;           // Ask price
   double            bid;           // Bid price
   double            volume_min;    // Minimum volume for a deal
   double            volume_max;    // Maximum volume for a deal
   double            volume_limit;  // Maximum permissible volume for a position and orders in one direction
   double            volume_step;   // Minimum volume change step for a deal
   double            offset;        // Offset from the maximum possible price for a transaction
   double            up_level;      // Upper Stop level price
   double            down_level;    // Lower Stop level price
  }

Ora, per accedere a un determinato elemento della struttura, dobbiamo creare una variabile di questo tipo di struttura. La procedura è simile alla creazione di un oggetto per una classe commerciale che è stata considerata nell'articolo chiamato "Manuale MQL5: Analisi delle proprietà di posizione nel tester di strategia MetaTrader 5".

//--- variables for position and symbol properties
position_properties  pos;
symbol_properties    symb;

È possibile accedere agli elementi nello stesso modo in cui si ha a che fare con i metodi di classe. In altre parole, è sufficiente mettere un punto dopo il nome di una variabile di struttura per visualizzare l'elenco degli elementi contenuti in quella specifica struttura. Questo è molto conveniente. Nel caso in cui vengano forniti commenti a riga singola per i campi della struttura (come nel nostro esempio), verranno visualizzati in un tooltip sulla destra.

Figura 5a. Elenco dei campi struttura per le proprietà di posizione  Fig. 5b. Elenco dei campi struttura per le proprietà dei simboli

Fig. 5. Elenco dei campi della struttura.

Un altro punto importante. Nel modificare l'Expert Advisor, abbiamo cambiato praticamente tutte le sue variabili globali utilizzate in molte funzioni, quindi ora dobbiamo sostituirle con i campi della struttura corrispondenti per le proprietà di simboli e posizioni. Ad esempio, la variabile globale pos_open che era utilizzata per memorizzare il flag di presenza/assenza di una posizione aperta è stata sostituita con il campo exists del tipo di struttura position_properties. Pertanto, ovunque sia stata utilizzata la variabile pos_open, deve essere sostituita con pos.exists.

Sarà un processo lungo ed estenuante se riesci a farlo manualmente. Quindi sarebbe meglio automatizzare la soluzione a questa attività utilizzando le funzionalità di MetaEditor: Trova e sostituisci -> Sostituisci nel menu Modifica o nella combinazione di tasti Ctrl+H:


Fig. 6. Trovare e sostituire il testo

Fig. 6. Trovare e sostituire il testo.

Abbiamo bisogno di trovare e sostituire tutte le variabili globali per le proprietà di posizione e simbolo per eseguire ulteriormente un test, dopo aver compilato il file. Se non vengono rilevati errori, vorrà dire che abbiamo fatto tutto bene. Non fornirò qui il codice per non rendere l'articolo inutilmente lungo. Inoltre, un codice sorgente pronto per l'uso è disponibile alla fine dell'articolo per il download.

Ora che abbiamo risolto il problema con le variabili, procediamo con la modifica delle funzioni esistenti e la creazione di quelle nuove.

Nei parametri esterni, ora puoi impostare il numero magico e lo slippage in punti. Dobbiamo quindi apportare le modifiche rilevanti anche al codice dell'Expert Advisor. Creeremo una funzione ausiliaria definita dall'utente OpenPosition(), dove queste proprietà verranno impostate utilizzando le funzioni della classe CTrade prima di inviare un ordine per l'apertura della posizione.

//+------------------------------------------------------------------+
//| Opening a position                                               |
//+------------------------------------------------------------------+
void OpenPosition(double lot,
                  ENUM_ORDER_TYPE order_type,
                  double price,
                  double sl,
                  double tp,
                  string comment)
  {
   trade.SetExpertMagicNumber(MagicNumber); // Set the magic number in the trading structure
   trade.SetDeviationInPoints(CorrectValueBySymbolDigits(Deviation)); // Set the slippage in points
//--- If the position failed to open, print the relevant message
   if(!trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,comment))
     { Print("Error opening the position: ",GetLastError()," - ",ErrorDescription(GetLastError())); }
  }

Abbiamo solo bisogno di apportare alcune piccole modifiche al codice della principale funzione di trading dell'Expert Advisor - TradingBlock(). Di seguito è riportata la parte del codice funzione che ha subito modifiche:

//--- If there is no position
   if(!pos.exists)
     {
      //--- Adjust the volume
      lot=CalculateLot(Lot);
      //--- Open a position
      OpenPosition(lot,order_type,position_open_price,sl,tp,comment);
     }
//--- If there is a position
   else
     {
      //--- Get the position type
      GetPositionProperties(P_TYPE);
      //--- If the position is opposite to the signal and the position reversal is enabled
      if(pos.type==opposite_position_type && Reverse)
        {
         //--- Get the position volume
         GetPositionProperties(P_VOLUME);
         //--- Adjust the volume
         lot=pos.volume+CalculateLot(Lot);
         //--- Reverse the position
         OpenPosition(lot,order_type,position_open_price,sl,tp,comment);
         return;
        }
      //--- If the signal is in the direction of the position and the volume increase is enabled, increase the position volume
      if(!(pos.type==opposite_position_type) && VolumeIncrease>0)
        {
         //--- Get the Stop Loss of the current position
         GetPositionProperties(P_SL);
         //--- Get the Take Profit of the current position
         GetPositionProperties(P_TP);
         //--- Adjust the volume
         lot=CalculateLot(Increase);
         //--- Increase the position volume
         OpenPosition(lot,order_type,position_open_price,pos.sl,pos.tp,comment);
         return;
        }

Il codice sopra è stato migliorato con il blocco in cui la direzione della posizione corrente viene verificata rispetto alla direzione del segnale. Se le loro direzioni coincidono e nei parametri esterni è abilitato l'aumento del volume di posizione (il valore del parametro VolumeIncrease è maggiore di zero), controlliamo/rettifichiamo un determinato lotto e inviamo il relativo ordine. Ora, tutto ciò che devi fare per inviare un ordine per aprire o invertire una posizione o per aumentare il volume della posizione è scrivere una riga di codice.

Creiamo funzioni per ottenere le proprietà di posizione dalla cronologia delle trattative. Inizieremo con una funzione CurrentPositionTotalDeals() che restituisce il numero di operazioni nella posizione corrente:

//+------------------------------------------------------------------+
//| Returning the number of deals in the current position            |
//+------------------------------------------------------------------+
uint CurrentPositionTotalDeals()
  {
   int    total       =0;  // Total deals in the selected history list
   int    count       =0;  // Counter of deals by the position symbol
   string deal_symbol =""; // symbol of the deal
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list
      for(int i=0; i<total; i++)
        {
            //--- Get the symbol of the deal
            deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL);
            //--- If the symbol of the deal and the current symbol are the same, increase the counter
            if(deal_symbol==_Symbol)
               count++;
        }
     }
//---
   return(count);
  }

Il codice sopra è fornito con commenti abbastanza dettagliati. Ma dovremmo dire alcune parole su come viene selezionata la cronologia. Nel nostro caso, abbiamo ottenuto l'elenco dal punto di apertura della posizione corrente determinata dal tempo di apertura al momento corrente utilizzando la funzione HistorySelect(). Dopo aver selezionato la cronologia, possiamo scoprire il numero di offerte nell'elenco utilizzando la funzione HistoryDealsTotal(). Il resto dovrebbe essere chiaro dai commenti.

La cronologia di una particolare posizione può essere selezionata anche tramite il suo identificatore utilizzando la funzione HistorySelectByPosition(). Qui, devi considerare che l'identificatore di posizione rimane lo stesso quando la posizione viene invertita, come a volte accade nel nostro Expert Advisor. Tuttavia, il tempo di apertura della posizione cambia all'inversione, quindi questa variante è più facile da implementare. Ma se hai a che fare con la cronologia delle operazioni che non si applica solo alla posizione attualmente aperta, devi utilizzare gli identificatori. Torneremo alla cronologia delle operazioni nei prossimi articoli.

Continuiamo creando una funzione CurrentPositionFirstDealPrice() che restituisce il prezzo della prima operazione nella posizione, ovvero il prezzo dell'operazione a cui è stata aperta la posizione.

//+------------------------------------------------------------------+
//| Returning the price of the first deal in the current position    |
//+------------------------------------------------------------------+
double CurrentPositionFirstDealPrice()
  {
   int      total       =0;    // Total deals in the selected history list
   string   deal_symbol ="";   // symbol of the deal
   double   deal_price  =0.0;  // Price of the deal
   datetime deal_time   =NULL; // Time of the deal
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list
      for(int i=0; i<total; i++)
        {
         //--- Get the price of the deal
         deal_price=HistoryDealGetDouble(HistoryDealGetTicket(i),DEAL_PRICE);
         //--- Get the symbol of the deal
         deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL);
         //--- Get the time of the deal
         deal_time=(datetime)HistoryDealGetInteger(HistoryDealGetTicket(i),DEAL_TIME);
         //--- If the time of the deal equals the position opening time, 
         //    and if the symbol of the deal and the current symbol are the same, exit the loop
         if(deal_time==pos.time && deal_symbol==_Symbol)
            break;
        }
     }
//---
   return(deal_price);
  }

Il principio qui è lo stesso della funzione precedente. Otteniamo la cronologia dal punto di apertura della posizione e quindi controlliamo l'ora dell'operazione e l'ora di apertura della posizione ad ogni iterazione. Insieme al prezzo dell'affare, otteniamo il nome del simbolo e l'ora dell'affare. La primissima operazione viene individuata quando l'orario dell'operazione coincide con l'orario di apertura della posizione. Poiché il suo prezzo è già stato assegnato alla relativa variabile, dobbiamo solo restituire il valore.

Andiamo avanti. A volte, potrebbe essere necessario ottenere il prezzo dell'ultima operazione nella posizione corrente. A questo scopo, creeremo una funzione CurrentPositionLastDealPrice():

//+------------------------------------------------------------------+
//| Returning the price of the last deal in the current position     |
//+------------------------------------------------------------------+
double CurrentPositionLastDealPrice()
  {
   int    total       =0;   // Total deals in the selected history list
   string deal_symbol ="";  // Symbol of the deal 
   double deal_price  =0.0; // Price
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list from the last deal in the list to the first deal
      for(int i=total-1; i>=0; i--)
        {
         //--- Get the price of the deal
         deal_price=HistoryDealGetDouble(HistoryDealGetTicket(i),DEAL_PRICE);
         //--- Get the symbol of the deal
         deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL);
         //--- If the symbol of the deal and the current symbol are the same, exit the loop
         if(deal_symbol==_Symbol)
            break;
        }
     }
//---
   return(deal_price);
  }

Questa volta il ciclo è iniziato con l'ultimo affare nell'elenco e spesso l'accordo richiesto viene identificato alla prima iterazione del ciclo. Ma se scambi su più simboli, il ciclo continuerà fino a quando il simbolo dell'operazione non corrisponderà al simbolo corrente.

Il volume della posizione corrente può essere ottenuto utilizzando le POSITION_VOLUME. Per scoprire il volume della posizione iniziale (il volume della prima transazione), creeremo una funzione CurrentPositionInitialVolume():

//+------------------------------------------------------------------+
//| Returning the initial volume of the current position             |
//+------------------------------------------------------------------+
double CurrentPositionInitialVolume()
  {
   int             total       =0;           // Total deals in the selected history list
   ulong           ticket      =0;           // Ticket of the deal
   ENUM_DEAL_ENTRY deal_entry  =WRONG_VALUE; // Position modification method
   bool            inout       =false;       // Flag of position reversal
   double          sum_volume  =0.0;         // Counter of the aggregate volume of all deals, except for the first one
   double          deal_volume =0.0;         // Volume of the deal
   string          deal_symbol ="";          // Symbol of the deal 
   datetime        deal_time   =NULL;        // Deal execution time
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list from the last deal in the list to the first deal
      for(int i=total-1; i>=0; i--)
        {
         //--- If the order ticket by its position is obtained, then...
         if((ticket=HistoryDealGetTicket(i))>0)
           {
            //--- Get the volume of the deal
            deal_volume=HistoryDealGetDouble(ticket,DEAL_VOLUME);
            //--- Get the position modification method
            deal_entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket,DEAL_ENTRY);
            //--- Get the deal execution time
            deal_time=(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
            //--- Get the symbol of the deal
            deal_symbol=HistoryDealGetString(ticket,DEAL_SYMBOL);
            //--- When the deal execution time is less than or equal to the position opening time, exit the loop
            if(deal_time<=pos.time)
               break;
            //--- otherwise calculate the aggregate volume of deals by the position symbol, except for the first one
            if(deal_symbol==_Symbol)
               sum_volume+=deal_volume;
           }
        }
     }
//--- If the position modification method is a reversal
   if(deal_entry==DEAL_ENTRY_INOUT)
     {
      //--- If the position volume has been increased/decreased
      //    I.e. the number of deals is more than one
      if(fabs(sum_volume)>0)
        {
         //--- Current volume minus the volume of all deals except for the first one
         double result=pos.volume-sum_volume;
         //--- If the resulting value is greater than zero, return the result, otherwise return the current position volume         
         deal_volume=result>0 ? result : pos.volume;
        }
      //--- If there are no more deals, other than the entry,
      if(sum_volume==0)
         deal_volume=pos.volume; // return the current position volume
     }
//--- Return the initial position volume
   return(NormalizeDouble(deal_volume,2));
  }

Questa funzione è risultata più complessa delle precedenti. Ho cercato di prendere in considerazione tutte le possibili situazioni che possono portare a un valore sbagliato. Un attento test non ha rivelato alcun problema. I commenti dettagliati forniti nel codice dovrebbero aiutarti a capire il punto.

Sarà anche utile avere una funzione che restituisca la durata della posizione. Lo organizzeremo in modo da consentire all'utente di selezionare il formato appropriato del valore restituito: secondi, minuti, ore o giorni. A tal fine, creiamo un'altra enumerazione:

//--- Position duration
enum ENUM_POSITION_DURATION
  {
   DAYS     = 0, // Days
   HOURS    = 1, // Hours
   MINUTES  = 2, // Minutes
   SECONDS  = 3  // Seconds
  };

Di seguito è riportato il codice della funzione CurrentPositionDuration() responsabile di tutti i calcoli rilevanti:

//+------------------------------------------------------------------+
//| Returning the duration of the current position                   |
//+------------------------------------------------------------------+
ulong CurrentPositionDuration(ENUM_POSITION_DURATION mode)
  {
   ulong     result=0;   // End result
   ulong     seconds=0;  // Number of seconds
//--- Calculate the position duration in seconds
   seconds=TimeCurrent()-pos.time;
//---
   switch(mode)
     {
      case DAYS      : result=seconds/(60*60*24);   break; // Calculate the number of days
      case HOURS     : result=seconds/(60*60);      break; // Calculate the number of hours
      case MINUTES   : result=seconds/60;           break; // Calculate the number of minutes
      case SECONDS   : result=seconds;              break; // No calculations (number of seconds)
      //---
      default        :
         Print(__FUNCTION__,"(): Unknown duration mode passed!");
         return(0);
     }
//--- Return result
   return(result);
  }

Creiamo una funzione CurrentPositionDurationToString() per il pannello informazioni in cui vengono visualizzate le proprietà della posizione. La funzione convertirà la durata della posizione in secondi in un formato facilmente comprensibile dall'utente. Il numero di secondi verrà passato alla funzione, e la funzione a sua volta restituirà una stringa contenente la durata della posizione in giorni, ore, minuti e secondi:

//+------------------------------------------------------------------+
//| Converting the position duration to a string                     |
//+------------------------------------------------------------------+
string CurrentPositionDurationToString(ulong time)
  {
//--- A dash if there is no position
   string result="-";
//--- If the position exists
   if(pos.exists)
     {
      //--- Variables for calculation results
      ulong days=0;
      ulong hours=0;
      ulong minutes=0;
      ulong seconds=0;
      //--- 
      seconds=time%60;
      time/=60;
      //---
      minutes=time%60;
      time/=60;
      //---
      hours=time%24;
      time/=24;
      //---
      days=time;
      //--- Generate a string in the specified format DD:HH:MM:SS
      result=StringFormat("%02u d: %02u h : %02u m : %02u s",days,hours,minutes,seconds);
     }
//--- Return result
   return(result);
  }

Tutto è pronto e pronto ora. Non fornirò i codici funzione GetPositionProperties() e GetPropertyValue() che devono essere modificati in conformità con tutte le modifiche di cui sopra. Se leggi tutti gli articoli precedenti della serie, non dovresti trovare alcuna difficoltà a farlo da solo. In ogni caso, il file del codice sorgente è allegato all'articolo.

Di conseguenza, il pannello delle informazioni dovrebbe apparire come mostrato di seguito:

Fig. 7. Dimostrazione di tutte le proprietà di posizione sul pannello informativo

Fig. 7. Dimostrazione di tutte le proprietà di posizione sul pannello informativo.

Quindi, ora abbiamo la libreria di funzioni per ottenere le proprietà di posizione e probabilmente continueremo a lavorarci nei prossimi articoli, come e quando richiesto.


Ottimizzazione dei parametri e test Expert Advisor

Come esperimento, proviamo a ottimizzare i parametri dell'Expert Advisor. Sebbene quello che abbiamo attualmente non possa ancora essere definito un sistema di trading completo, il risultato che otterremo aprirà i nostri occhi su alcune cose e migliorerà la nostra esperienza come sviluppatori di sistemi di trading.

Effettueremo le impostazioni di Strategy Tester come mostrato di seguito:

Fig. 8. Impostazioni di Strategy Tester per l'ottimizzazione dei parametri

Fig. 8. Impostazioni di Strategy Tester per l'ottimizzazione dei parametri.

Le impostazioni dei parametri esterni dell'Expert Advisor dovrebbero essere le seguenti:

Fig. 9. Impostazioni dei parametri di Expert Advisor per l'ottimizzazione

Fig. 9. Impostazioni dei parametri di Expert Advisor per l'ottimizzazione.

A seguito dell'ottimizzazione, ordiniamo i risultati ottenuti in base al fattore di recupero massimo:

Fig. 10. Risultati ordinati per fattore di recupero massimo

Fig. 10. Risultati ordinati in base al fattore di recupero massimo.

Proviamo ora il set di parametri più in alto, con il valore del fattore di recupero pari a 4,07. Anche considerando che l'ottimizzazione è stata eseguita per EURUSD, possiamo vedere risultati positivi per molti simboli:

Risultati per EURUSD:

Fig. 11. Risultati per EURUSD

Fig. 11. Risultati per EURUSD.

Risultati per AUDUSD:

Fig. 12. Risultati per AUDUSD

Fig. 12. Risultati per AUDUSD.

Risultati per NZDUSD:

Fig. 13. Risultati per NZDUSD

Fig. 13. Risultati per NZDUSD.


Conclusione

Praticamente qualsiasi idea può essere sviluppata e migliorata. Ogni sistema di trading dovrebbe essere testato molto attentamente prima di essere consoderato difettoso. Nei prossimi articoli daremo uno sguardo a vari meccanismi e schemi che possono svolgere un ruolo molto positivo nella personalizzazione e nell'adattamento di quasi tutti i sistemi di trading.

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

File allegati |
Manuale MQL5: Utilizzo degli indicatori per impostare le condizioni di trading in Expert Advisor Manuale MQL5: Utilizzo degli indicatori per impostare le condizioni di trading in Expert Advisor
In questo articolo, continueremo a modificare l'Expert Advisor su cui abbiamo lavorato in tutti gli articoli precedenti della serie Manuale MQL5. Questa volta, l'Expert Advisor sarà arricchito con indicatori i cui valori saranno utilizzati per verificare le condizioni di apertura della posizione. Per ravvivarlo, creeremo un elenco a discesa nei parametri esterni per poter selezionare uno su tre indicatori di trading.
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.
L'indicatore ZigZag: Nuovo approccio e nuove soluzioni L'indicatore ZigZag: Nuovo approccio e nuove soluzioni
L'articolo esamina la possibilità di creare un indicatore ZigZag avanzato. L'idea di identificare i nodi si basa sull'uso dell'indicatore Inviluppo (Envelopes)a. Supponiamo di poter trovare una certa combinazione di parametri di input per una serie di inviluppo, per cui tutti i nodi ZigZag si trovano all'interno dei confini delle bande di Envelopes (inviluppo). Di conseguenza, possiamo provare a prevedere le coordinate del nuovo nodo.
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 ().