English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
MQL5 Cookbook : Écriture de l'historique des transactions dans un fichier et création des graphiques d’équilibre pour chaque symbole dans Excel

MQL5 Cookbook : Écriture de l'historique des transactions dans un fichier et création des graphiques d’équilibre pour chaque symbole dans Excel

MetaTrader 5Exemples | 13 janvier 2022, 10:45
183 0
Anatoli Kazharski
Anatoli Kazharski

Introduction

Lorsque je communiquais dans divers forums, j'utilisais souvent des exemples de mes résultats de test affichés sous forme de captures d'écran de graphiques Microsoft Excel. On m'a souvent demandé d'expliquer comment de tels graphiques peuvent être créés. Excel offre de nombreuses fonctionnalités pour créer des graphiques et il existe de nombreux livres sur ce sujet. Pour trouver les informations requises dans un livre, il peut être nécessaire de tout lire. Maintenant, enfin, j'ai un peu de temps pour tout expliquer dans cet article.

Dans les deux articles précédents, MQL5 Cookbook : Expert Advisor multi-devises - Une approche simple, nette et rapide et MQL5 Cookbook : Développement d'un Expert Advisor multi-devises avec un nombre illimité de paramètres, nous avons traité du développement d'EA multi-devises dans MQL5. Nous savons que les résultats des tests dans MetaTrader 5 sont affichés sous la forme d'une courbe Equilibre/Equité générale, c'est-à-dire que si vous devez afficher les résultats pour chaque symbole séparément, vous devez encore et encore accéder aux paramètres externes de l'Expert Advisor pour désactiver tous les symboles. à l'exception de celui dont les résultats sont requis, puis relancez le test. Ce n'est pas pratique.

Aujourd'hui, je vais donc vous montrer une méthode simple pour obtenir des graphiques d’équilibre pour chaque symbole pour tous les symboles ainsi que le résultat cumulé d'un Expert Advisor multi-devises sur un seul diagramme Excel en quelques clics. Pour reconstruire l'exemple, nous prendrons l'Expert Advisor multi-devises de article précédent . Il sera amélioré avec une fonction qui écrira l'historique des transactions et les courbes d'équilibre pour tous les symboles dans un fichier .csv à la fin du test. De plus, nous ajouterons une autre colonne au rapport pour afficher les prélèvements de tous les maxima locaux.

Créons un livre Excel configuré de manière à pouvoir connecter le fichier de données. Le livre peut être ouvert tout le temps, il n'aura donc pas besoin d'être fermé avant d'exécuter un autre test. À la fin du test, il vous suffira d'actualiser les données en appuyant sur une certaine touche pour pouvoir voir les changements dans le rapport et sur le graphique.


Développement d’Expert Advisor

Il n'y aura pas de changements significatifs dans notre EA, nous ajouterons juste quelques fonctions. Commençons par ajouter la structure et le tableau des équilibres de symboles au fichier principal.

//--- Arrays for balances
struct Balance
  {
   double            balance[];
  };
//--- Array of balances for all symbols
Balance symbol_balance[];

Ensuite, nous créons le fichier d'inclusion Report.mqh séparé pour les fonctions qui génèrent des rapports de test et l'incluons dans le fichier principal de l'Expert Advisor (voir la ligne mise en évidence dans le code ci-dessous) :

//--- Include custom libraries
#include "Include/Auxiliary.mqh"
#include "Include/Enums.mqh"
#include "Include/Errors.mqh"
#include "Include/FileFunctions.mqh"
#include "Include/InitializeArrays.mqh"
#include "Include/Report.mqh"
#include "Include/ToString.mqh"
#include "Include/TradeFunctions.mqh"
#include "Include/TradeSignals.mqh"

Créons d'abord une structure de propriété de transaction, comme celle que nous avons déjà dans le projet pour les propriétés de position et de symbole. Pour ce faire, nous ajoutons l'énumération des identifiants de propriété au fichier Enums.mqh :

//+------------------------------------------------------------------+
//| Enumeration of deal properties                                   |
//+------------------------------------------------------------------+
enum ENUM_DEAL_PROPERTIES
  {
   D_SYMBOL     = 0, // Deal symbol
   D_COMMENT    = 1, // Deal comment
   D_TYPE       = 2, // Deal type
   D_ENTRY      = 3, // Deal entry - entry in, entry out, reverse
   D_PRICE      = 4, // Deal price
   D_PROFIT     = 5, // Deal result (profit/loss)
   D_VOLUME     = 6, // Deal volume
   D_SWAP       = 7, // Cumulative swap on close
   D_COMMISSION = 8, // Deal commission
   D_TIME       = 9, // Deal time
   D_ALL        = 10 // All of the above mentioned deal properties
  };

De plus, dans le fichier Report.mqh, nous créons la structure de la propriété de la transaction et la fonction GetHistoryDealProperties() qui renvoie une propriété de la transaction. La fonction accepte deux paramètres : le ticket de transaction et l'identifiant de la propriété.

Ci-dessous, vous pouvez voir le code de la structure et la fonction GetHistoryDealProperties() :

//--- Deal properties in the history
struct HistoryDealProperties
  {
   string            symbol;     // Symbol
   string            comment;    // Comment
   ENUM_DEAL_TYPE    type;       // Deal type
   ENUM_DEAL_ENTRY   entry;      // Direction
   double            price;      // Price
   double            profit;     // Profit/Loss
   double            volume;     // Volume
   double            swap;       // Swap
   double            commission; // Commission
   datetime          time;       // Time
  };
//--- Variable of deal properties
HistoryDealProperties  deal;
//+------------------------------------------------------------------+
//| Gets deal properties by ticket                                   |
//+------------------------------------------------------------------+
void GetHistoryDealProperties(ulong ticket_number,ENUM_DEAL_PROPERTIES history_deal_property)
  {
   switch(history_deal_property)
     {
      case D_SYMBOL     : deal.symbol=HistoryDealGetString(ticket_number,DEAL_SYMBOL);                 break;
      case D_COMMENT    : deal.comment=HistoryDealGetString(ticket_number,DEAL_COMMENT);               break;
      case D_TYPE       : deal.type=(ENUM_DEAL_TYPE)HistoryDealGetInteger(ticket_number,DEAL_TYPE);    break;
      case D_ENTRY      : deal.entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket_number,DEAL_ENTRY); break;
      case D_PRICE      : deal.price=HistoryDealGetDouble(ticket_number,DEAL_PRICE);                   break;
      case D_PROFIT     : deal.profit=HistoryDealGetDouble(ticket_number,DEAL_PROFIT);                 break;
      case D_VOLUME     : deal.volume=HistoryDealGetDouble(ticket_number,DEAL_VOLUME);                 break;
      case D_SWAP       : deal.swap=HistoryDealGetDouble(ticket_number,DEAL_SWAP);                     break;
      case D_COMMISSION : deal.commission=HistoryDealGetDouble(ticket_number,DEAL_COMMISSION);         break;
      case D_TIME       : deal.time=(datetime)HistoryDealGetInteger(ticket_number,DEAL_TIME);          break;
      case D_ALL        :
         deal.symbol=HistoryDealGetString(ticket_number,DEAL_SYMBOL);
         deal.comment=HistoryDealGetString(ticket_number,DEAL_COMMENT);
         deal.type=(ENUM_DEAL_TYPE)HistoryDealGetInteger(ticket_number,DEAL_TYPE);
         deal.entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket_number,DEAL_ENTRY);
         deal.price=HistoryDealGetDouble(ticket_number,DEAL_PRICE);
         deal.profit=HistoryDealGetDouble(ticket_number,DEAL_PROFIT);
         deal.volume=HistoryDealGetDouble(ticket_number,DEAL_VOLUME);
         deal.swap=HistoryDealGetDouble(ticket_number,DEAL_SWAP);
         deal.commission=HistoryDealGetDouble(ticket_number,DEAL_COMMISSION);
         deal.time=(datetime)HistoryDealGetInteger(ticket_number,DEAL_TIME);                           break;
         //---
      default: Print("The passed deal property is not listed in the enumeration!");                          return;
     }
  }

Nous aurons également besoin de plusieurs fonctions qui convertiront certaines propriétés de transaction en valeurs de chaîne. Ces fonctions simples renvoient un tiret ("-") si la valeur passée est vide ou nulle. Écrivons-les dans le fichier ToString.mqh :

//+------------------------------------------------------------------+
//| Returns the symbol name, otherwise - dash                        |
//+------------------------------------------------------------------+
string DealSymbolToString(string deal_symbol)
  {
   return(deal_symbol=="" ? "-" : deal_symbol);
  }
//+------------------------------------------------------------------+
//| Converts deal type to string                                     |
//+------------------------------------------------------------------+
string DealTypeToString(ENUM_DEAL_TYPE deal_type)
  {
   string str="";
//---
   switch(deal_type)
     {
      case DEAL_TYPE_BUY                      : str="buy";                      break;
      case DEAL_TYPE_SELL                     : str="sell";                     break;
      case DEAL_TYPE_BALANCE                  : str="balance";                  break;
      case DEAL_TYPE_CREDIT                   : str="credit";                   break;
      case DEAL_TYPE_CHARGE                   : str="charge";                   break;
      case DEAL_TYPE_CORRECTION               : str="correction";               break;
      case DEAL_TYPE_BONUS                    : str="bonus";                    break;
      case DEAL_TYPE_COMMISSION               : str="commission";               break;
      case DEAL_TYPE_COMMISSION_DAILY         : str="commission daily";         break;
      case DEAL_TYPE_COMMISSION_MONTHLY       : str="commission monthly";       break;
      case DEAL_TYPE_COMMISSION_AGENT_DAILY   : str="commission agent daily";   break;
      case DEAL_TYPE_COMMISSION_AGENT_MONTHLY : str="commission agent monthly"; break;
      case DEAL_TYPE_INTEREST                 : str="interest";                 break;
      case DEAL_TYPE_BUY_CANCELED             : str="buy canceled";             break;
      case DEAL_TYPE_SELL_CANCELED            : str="sell canceled";            break;
      //--- Unknown deal type
      default : str="unknown";
     }
//---
   return(str);
  }
//+------------------------------------------------------------------+
//| Converts direction of deal to string                             |
//+------------------------------------------------------------------+
string DealEntryToString(ENUM_DEAL_ENTRY deal_entry)
  {
   string str="";
//---
   switch(deal_entry)
     {
      case DEAL_ENTRY_IN    : str="in";            break;
      case DEAL_ENTRY_OUT   : str="out";           break;
      case DEAL_ENTRY_INOUT : str="in/out";        break;
      case DEAL_ENTRY_STATE : str="status record"; break;
      //--- Unknown direction type
      default : str="unknown";
     }
//---
   return(str);
  }
//+------------------------------------------------------------------+
//| Converts volume to string                                        |
//+------------------------------------------------------------------+
string DealVolumeToString(double deal_volume)
  {
   return(deal_volume<=0 ? "-" : DoubleToString(deal_volume,2));
  }
//+------------------------------------------------------------------+
//| Converts price to string                                         |
//+------------------------------------------------------------------+
string DealPriceToString(double deal_price,int digits)
  {
   return(deal_price<=0 ? "-" : DoubleToString(deal_price,digits));
  }
//+------------------------------------------------------------------+
//| Converts deal result to string                                   |
//+------------------------------------------------------------------+
string DealProfitToString(string deal_symbol,double deal_profit)
  {
   return((deal_profit==0 || deal_symbol=="") ? "-" : DoubleToString(deal_profit,2));
  }
//+------------------------------------------------------------------+
//| Converts swap to string                                          |
//+------------------------------------------------------------------+
string DealSwapToString(double deal_swap)
  {
   return(deal_swap<=0 ? "-" : DoubleToString(deal_swap,2));
  }

Maintenant, tout est prêt pour écrire la fonction CreateSymbolBalanceReport() qui prépare les données pour le rapport et les écrit dans le fichierLastTest.csv. C'est assez simple : nous écrivons d'abord l'en-tête (notez comment la chaîne de caractères est ajustée si le test a été exécuté pour plus d'un symbole), puis les propriétés de transaction requises pour le rapport sont concaténées consécutivement dans une chaîne de caractères qui est ensuite écrite dans le fichier.

Vous trouverez ci-dessous le code de la fonction CreateSymbolBalanceReport() :

//+------------------------------------------------------------------+
//| Creates the test report on deals in .csv format                  |
//+------------------------------------------------------------------+
void CreateSymbolBalanceReport()
  {
   int    file_handle =INVALID_HANDLE; // File handle
   string path        ="";             // File path

//--- If an error occurred when creating/getting the folder, exit
   if((path=CreateInputParametersFolder())=="")
      return;
//--- Create file to write data in the common folder of the terminal
   file_handle=FileOpen(path+"\\LastTest.csv",FILE_CSV|FILE_WRITE|FILE_ANSI|FILE_COMMON);
//--- If the handle is valid (file created/opened)
   if(file_handle>0)
     {
      int    digits          =0;   // Number of decimal places in the price
      int    deals_total     =0;   // Number of deals in the specified history
      ulong  ticket          =0;   // Deal ticket
      double drawdown_max    =0.0; // Maximum drawdown
      double balance         =0.0; // Balance
      //---
      string delimeter       =","; // Delimiter
      string string_to_write ="";  // To generate the string for writing

      //--- Generate the header string
      string headers="TIME,SYMBOL,DEAL TYPE,ENTRY TYPE,VOLUME,PRICE,SWAP($),PROFIT($),DRAWDOWN(%),BALANCE";
      //--- If more than one symbol is involved, modify the header string
      if(SYMBOLS_COUNT>1)
        {
         for(int s=0; s<SYMBOLS_COUNT; s++)
            StringAdd(headers,","+InputSymbols[s]);
        }
      //--- Write the report headers
      FileWrite(file_handle,headers);
      //--- Get the complete history
      HistorySelect(0,TimeCurrent());
      //--- Get the number of deals
      deals_total=HistoryDealsTotal();
      //--- Resize the array of balances according to the number of symbols
      ArrayResize(symbol_balance,SYMBOLS_COUNT);
      //--- Resize the array of deals for each symbol
      for(int s=0; s<SYMBOLS_COUNT; s++)
         ArrayResize(symbol_balance[s].balance,deals_total);
      //--- Iterate in a loop and write the data
      for(int i=0; i<deals_total; i++)
        {
         //--- Get the deal ticket
         ticket=HistoryDealGetTicket(i);
         //--- Get all the deal properties
         GetHistoryDealProperties(ticket,D_ALL);
         //--- Get the number of digits in the price
         digits=(int)SymbolInfoInteger(deal.symbol,SYMBOL_DIGITS);
         //--- Calculate the overall balance
         balance+=deal.profit+deal.swap+deal.commission;
         //--- Generate a string for writing via concatenation
         StringConcatenate(string_to_write,
                           deal.time,delimeter,
                           DealSymbolToString(deal.symbol),delimeter,
                           DealTypeToString(deal.type),delimeter,
                           DealEntryToString(deal.entry),delimeter,
                           DealVolumeToString(deal.volume),delimeter,
                           DealPriceToString(deal.price,digits),delimeter,
                           DealSwapToString(deal.swap),delimeter,
                           DealProfitToString(deal.symbol,deal.profit),delimeter,
                           MaxDrawdownToString(i,balance,max_drawdown),delimeter,
                           DoubleToString(balance,2));

         //--- If more than one symbol is involved, write their balance values
         if(SYMBOLS_COUNT>1)
           {
            //--- Iterate over all symbols
            for(int s=0; s<SYMBOLS_COUNT; s++)
              {
               //--- If the symbols are equal and the deal result is non-zero
               if(deal.symbol==InputSymbols[s] && deal.profit!=0)
                 {
                  //--- Display the deal in the balance for the corresponding symbol
                  //    Take into consideration swap and commission
                  symbol_balance[s].balance[i]=symbol_balance[s].balance[i-1]+
                                               deal.profit+
                                               deal.swap+
                                               deal.commission;
                  //--- Add to the string
                  StringAdd(string_to_write,","+DoubleToString(symbol_balance[s].balance[i],2));
                 }
               //--- Otherwise write the previous value
               else
                 {
                  //--- If the deal type is "Balance" (the first deal)
                  if(deal.type==DEAL_TYPE_BALANCE)
                    {
                     //--- the balance is the same for all symbols
                     symbol_balance[s].balance[i]=balance;
                     StringAdd(string_to_write,","+DoubleToString(symbol_balance[s].balance[i],2));
                    }
                  //--- Otherwise write the previous value to the current index
                  else
                    {
                     symbol_balance[s].balance[i]=symbol_balance[s].balance[i-1];
                     StringAdd(string_to_write,","+DoubleToString(symbol_balance[s].balance[i],2));
                    }
                 }
              }
           }
         //--- Write the generated string
         FileWrite(file_handle,string_to_write);
         //--- Mandatory zeroing out of the variable for the next string
         string_to_write="";
        }
      //--- Close the file
      FileClose(file_handle);
     }
//--- If the file could not be created/opened, print the appropriate message
   else
      Print("Error creating file: "+IntegerToString(GetLastError())+"");
  }

La fonction MaxDrawdownToString() mise en évidence dans le code ci-dessus calcule tous les tirages à partir des maxima locaux et renvoie une représentation sous forme de chaîne de l'heure du nouveau maximum local. Dans tous les autres cas, la fonction renvoie une chaîne de caractères contenant "-" (un tiret).

//+------------------------------------------------------------------+
//| Returns the maximum drawdown from the local maximum              |
//+------------------------------------------------------------------+
string MaxDrawdownToString(int deal_number,double balance,double &max_drawdown)
  {
//--- The string to be displayed in the report
   string str="";
//--- To calculate the local maximum and drawdown
   static double max=0.0;
   static double min=0.0;
//--- If this is the first deal
   if(deal_number==0)
     {
      //--- No drawdown yet
      max_drawdown=0.0;
      //--- Set the initial point as the local maximum
      max=balance;
      min=balance;
     }
   else
     {
      //--- If the current balance is greater than in the memory
      if(balance>max)
        {
         //--- calculate the drawdown using the previous values
         max_drawdown=100-((min/max)*100);
         //--- update the local maximum
         max=balance;
         min=balance;
        }
      else
        {
         //--- Return zero value of the drawdown
         max_drawdown=0.0;
         //--- Update the minimum
         min=fmin(min,balance);
        }
     }
//--- Determine the string for the report
   if(max_drawdown==0)
      str="-";
   else
      str=DoubleToString(max_drawdown,2);
//--- Return result
   return(str);
  }

Ainsi, toutes les fonctions de génération de rapports sont prêtes. Nous avons seulement besoin de voir comment nous devrions utiliser tout ce qui précède. Cela nécessitera l'appel de OnTester() function à la fin du test. Assurez-vous de vérifier la description détaillée de cette fonction dans la référence MQL5.

Écrivez simplement quelques lignes de code dans le corps de la fonction OnTester() pour spécifier la condition à laquelle le rapport doit être généré. L'extrait de code correspondant est fourni ci-dessous :

//+------------------------------------------------------------------+
//| Handler of the event of testing completion                       |
//+------------------------------------------------------------------+
double OnTester()
  {
//--- Write the report only after testing
   if(IsTester() && !IsOptimization() && !IsVisualMode())
      //--- Generate the report and write it to the file
      CreateSymbolBalanceReport();
//---
   return(0.0);
  }

Maintenant, si vous exécutez l'Expert Advisor dans le Strategy Tester, à la fin du test, vous verrez un dossier de l'Expert Advisor créé dans le dossier des terminaux communs C:\ProgramData\MetaQuotes\Terminal\Common\Files. Et le fichier de rapport LastTest.csv sera généré dans le dossier de l'Expert Advisor. Si vous ouvrez le fichier avec le Bloc-notes, vous verrez quelque chose comme ceci :

Figure 1. Le fichier de rapport au format .csv

Figure 1. Le fichier de rapport au format .csv.

Création de graphiques dans Excel

Nous pouvons ouvrir le fichier créé dans Excel et voir que chaque type de données se trouve dans une colonne distincte. De cette façon, les données semblent beaucoup plus pratiques pour la visualisation. À ce stade, nous sommes techniquement prêts à créer des graphiques et à enregistrer le fichier en tant que livre Excel au format *.xlsx. Cependant, si par la suite nous exécutons le test et ouvrons à nouveau le livre, nous verrons toujours les anciennes données.

Si nous essayons de rafraîchir les données, alors que le fichier LastTest.csv est déjà utilisé dans Excel, le fichier ne sera pas mis à jour, car l'Expert Advisor ne pourra pas l'ouvrir en écriture pendant qu'il est utilisé par une autre application.

Figure 2. Le fichier de rapport au format .csv dans Excel 2010

Figure 2. Le fichier de rapport au format .csv dans Excel 2010.

Il existe une solution qui peut être utilisée dans notre cas. Créez d'abord un livre Excel au format *.xlsx dans le dossier de votre choix. Ensuite, ouvrez-le et accédez à l'onglet Data.

Figure 3. L'onglet Data dans Excel 2010

Figure 3. L'onglet Data dans Excel 2010.

Sur le ruban de cet onglet, sélectionnez l'option From Text. La boîte de dialogue Import Text File apparaîtra où vous devrez sélectionner le fichier "LastTest.csv". Sélectionnez le fichier et cliquez sur le bouton Open. La boîte de dialogue Text Import Wizard - Step 1 of 3 apparaîtra comme indiqué ci-dessous :

Figure 4. La boîte de dialogue "Text Import Wizard - Step 1 of 3"

Figure 4. La boîte de dialogue "Text Import Wizard - Step 1 of 3".

Ajustez les paramètres comme indiqué ci-dessus et cliquez sur Next >. Ici, (étape 2 sur 3), vous devez spécifier le délimiteur utilisé dans le fichier de données. Dans notre fichier, c'est "," (virgule).

Figure 5. La boîte de dialogue "Text Import Wizard - Step 2 of 3"

Figure 5. La boîte de dialogue "Text Import Wizard - Step 2 of 3".

Cliquez sur Next > pour passer à l'Assistant d'importation de texte - Étape 3 sur 3 (Text Import Wizard - Step 3 of 3). Ici, laissez le General comme format de données pour toutes les colonnes. Vous pouvez changer le format plus tard.

Figure 6. La boîte de dialogue "Text Import Wizard - Step 3 of 3"

Figure 6. La boîte de dialogue "Text Import Wizard - Step 3 of 3".

Après avoir cliqué sur le bouton Finish, la fenêtre Import Data apparaîtra où vous devrez spécifier la feuille de calcul et la cellule pour l'importation de données.

Figure 7. Sélection de la cellule pour l'importation de données dans Excel 2010

Figure 7. Sélection de la cellule pour l'importation de données dans Excel 2010.

Habituellement, nous sélectionnons la cellule en haut à gauche A1. Avant de cliquer sur OK, cliquez sur le bouton Propriétés... pour définir les propriétés de la plage de données externes. Vous verrez une boîte de dialogue comme indiqué ci-dessous.

Figure 8. Propriétés de la plage de données externes lors de l'importation de données à partir de fichiers texte dans Excel 2010

Figure 8. Propriétés de la plage de données externes lors de l'importation de données à partir de fichiers texte dans Excel 2010.

Ajustez les paramètres exactement comme indiqué ci-dessus et cliquez sur OK dans la fenêtre actuelle et la suivante.

En conséquence, vos données apparaîtront exactement comme si vous aviez simplement chargé le fichier .csv. Mais maintenant, vous pouvez exécuter des tests répétés dans MetaTrader 5, sans avoir à fermer le Excel book. Après avoir exécuté le test, il vous suffit d'actualiser simplement les données à l'aide du raccourci Ctrl+Alt+F5 ou du bouton Refresh All du ruban de l'onglet Data.

À l'aide des options Conditional Formatting du ruban de l'onglet Home, vous pouvez définir les propriétés visuelles requises pour la représentation des données.

Figure 9. Mise en forme conditionnelle dans Excel 2010

Figure 9. Mise en forme conditionnelle dans Excel 2010.

Nous devons maintenant afficher les données sur des graphiques Excel. Un graphique affichera tous les graphiques d'équilibre et l'autre affichera tous les prélèvements des maxima locaux sous forme d'histogramme.

Commençons par créer un diagramme pour les tableaux d'équilibre. Sélectionnez les en-têtes de tous les équilibres et l'ensemble du tableau de données de haut en bas (tout en maintenant la touche Shift, appuyez sur la touche End puis sur la touche Down Arrow ). Maintenant, dans l'onglet Insert, sélectionnez le type de graphique souhaité.

Figure 10. Sélection d'un type de graphique dans Excel 2010

Figure 10. Sélection d'un type de graphique dans Excel 2010.

En conséquence, le graphique sera créé et pourra être déplacé vers une autre feuille de calcul pour plus de commodité. Pour ce faire, sélectionnez-le simplement et appuyez sur Ctrl+X (Couper). Ensuite, accédez à la feuille de calcul nouvellement créée, sélectionnez la cellule A1 et appuyez sur Ctrl + V (Coller).

Le graphique créé avec les paramètres par défaut est affiché dans l'image ci-dessous :

Figure 11. Présentation du graphique avec les paramètres par défaut.

Figure 11. Présentation du graphique avec les paramètres par défaut.

Vous pouvez personnaliser n'importe quel élément du graphique : changer sa taille, sa couleur, son style, etc.

Dans l'image ci-dessus, l'axe horizontal indique le nombre de transactions. Modifions-le pour qu'il affiche les dates à la place. Pour cela, cliquez avec le bouton droit sur le graphique et sélectionnez l'option Select Data dans le menu contextuel. La boîte de dialogue Select Data Source apparaîtra. Cliquez sur le bouton Edit, puis sélectionnez la plage de données requise dans la colonne TIME et cliquez sur OK.

Figure 12. La boîte de dialogue "Select Data Source"

Figure 12. La boîte de dialogue "Select Data Source".

Essayez de créer vous-même le graphique des retraits et placez-le sous le premier graphique. Désormais, leurs propriétés visuelles peuvent être personnalisées, si nécessaire. Personnellement, j'ai l'habitude de le faire :

Figure 13. Graphiques personnalisés dans Excel 2010..

Figure 13. Graphiques personnalisés dans Excel 2010.


Conclusion

Nous avons donc les graphiques Excel avec des résultats de test qui semblent assez décents. Dans l'un de mes futurs articles, je vous montrerai comment créer des rapports encore plus informatifs. L'archive téléchargeable avec les fichiers de l'Expert Advisor est jointe à l'article pour votre considération.

Après avoir extrait les fichiers de l'archive, placez le dossier ReportInExcel dans le répertoire MetaTrader 5\MQL5\Experts. De plus, l'indicateur EventsSpy.mq5 doit être placé dans le répertoire MetaTrader 5\MQL5\Indicators.

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

Fichiers joints |
eventsspy__4.mq5 (7.59 KB)
reportinexcel.zip (26.73 KB)
MQL5 Cookbook : Réduction de l'effet du surajustement et traitement de l'absence de cotations MQL5 Cookbook : Réduction de l'effet du surajustement et traitement de l'absence de cotations
Quelle que soit la stratégie de trading que vous utilisez, il y aura toujours une question de quels paramètres choisir pour assurer des bénéfices futurs. Cet article donne un exemple d'Expert Advisor avec la possibilité d'optimiser plusieurs paramètres de symboles en même temps. Cette méthode est destinée à réduire l'effet du surajustement des paramètres et à traiter les situations où les données d'un seul symbole ne sont pas suffisantes pour l'étude.
MQL5 Cookbook : Développement d’un Expert Advisor Multi-devises avec un nombre illimité de paramètres MQL5 Cookbook : Développement d’un Expert Advisor Multi-devises avec un nombre illimité de paramètres
Dans cet article, nous allons créer un modèle qui utilise un seul ensemble de paramètres pour l'optimisation d'un système de trading, tout en permettant un nombre illimité de paramètres. La liste des symboles sera créée dans un fichier texte standard (*.txt). Les paramètres d'entrée pour chaque symbole seront également stockés dans des fichiers. De cette façon, nous pourrons contourner la restriction du terminal sur le nombre de paramètres d'entrée d'un Expert Advisor.
Débogage des programmes MQL5 Débogage des programmes MQL5
Cet article est principalement destiné aux programmeurs qui ont déjà appris le langage mais qui ne maîtrisent pas encore complètement le développement du programme. Il révèle quelques techniques de débogage et présente une expérience combinée de l'auteur et de nombreux autres programmeurs.
MQL5 Cookbook : Expert Advisor multi-devises - Approche simple, nette et rapide MQL5 Cookbook : Expert Advisor multi-devises - Approche simple, nette et rapide
Cet article décrira une mise en œuvre d'une approche simple adaptée à un Expert Advisor multi-devises. Cela signifie que vous pourrez configurer l'Expert Advisor pour les tests/trading dans des conditions identiques mais avec des paramètres différents pour chaque symbole. A titre d'exemple, nous allons créer un motif pour deux symboles mais de manière à pouvoir ajouter des symboles supplémentaires, si nécessaire, en apportant de petites modifications au code.