English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
Das MQL5-Kochbuch: Schreiben der Historie von Abschlüssen in eine Datei und Erstellen von Bilanzdiagrammen für jedes Symbol in Excel

Das MQL5-Kochbuch: Schreiben der Historie von Abschlüssen in eine Datei und Erstellen von Bilanzdiagrammen für jedes Symbol in Excel

MetaTrader 5Beispiele | 10 Mai 2016, 10:53
1 465 0
Anatoli Kazharski
Anatoli Kazharski

Einleitung

Bei der Kommunikation in diversen Foren nutze ich oft Beispiele meiner Testergebnisse in der Darstellung in Form von Screenshots von Excel-Diagrammen. Ich werde häufig gebeten, zu erklären, wie solche Diagramme erstellt werden können. Excel bietet umfangreiche Funktionen zum Erstellen von Diagrammen und es gibt zahlreiche Bücher zu diesem Thema. Um die erforderliche Information in einem Buch zu finden, muss man es möglicherweise komplett lesen. Nun habe ich endlich etwas Zeit gefunden, alles in diesem Beitrag zu erklären.

In den beiden vorherigen Beiträgen Das MQL5-Kochbuch: Mehrwährungsfähiger Expert Advisor – eine einfache, saubere und schnelle Herangehensweise und Das MQL5-Kochbuch: Entwicklung eines mehrwährungsfähigen Expert Advisors mit unbegrenzter Anzahl von Parametern haben wir die Entwicklung von mehrwährungsfähigen EAs in MQL5 behandelt. Wir wissen, dass die Testergebnisse in MetaTrader 5 als allgemeine Bilanz-/Eigenkapitalkurve dargestellt werden, d. h., wenn Sie die Ergebnisse für jedes Symbol gesondert betrachten möchten, müssen Sie die externen Parameter des Expert Advisors immer wieder aufrufen, um alle Symbole außer demjenigen, dessen Ergebnisse Sie benötigen, zu deaktivieren, und dann den Test erneut ausführen. Das ist ziemlich unpraktisch.

Deshalb zeige ich Ihnen heute eine einfache Methode, mit der Sie Bilanzdiagramme für alle Symbole zusammen mit dem Gesamtergebnis eines mehrwährungsfähigen Expert Advisors in einem einzelnen Excel-Diagramm mit nur wenigen Klicks erhalten können. Um dieses Beispiel zu rekonstruieren, nehmen wir den mehrwährungsfähigen Expert Advisor aus dem vorherigen Beitrag. Er wird um eine Funktion erweitert, die die Historie von Abschlüssen und die Bilanzkurven für alle Symbole nach dem Abschluss des Tests in eine .csv-Datei schreibt. Außerdem fügen wir eine weitere Spalte im Bericht ein, in der die Wertverluste aus allen lokalen Maxima angezeigt werden.

Erstellen wir eine Excel-Tabelle mit der Möglichkeit, sich mit der Datendatei zu verbinden. Die Tabelle kann die ganze Zeit über geöffnet bleiben, also muss sie vor dem Ausführen eines weiteren Tests nicht geschlossen werden. Nach dem Abschluss des Tests müssen Sie lediglich die Daten aktualisieren, indem Sie einen bestimmten Knopf drücken, um die Änderungen im Bericht und im Diagramm sehen zu können.


Entwicklung des Expert Advisors

Wir werden keine großen Änderungen an unserem EA vornehmen, sondern lediglich ein paar Funktionen hinzufügen. Fangen wir an, indem wir die Struktur und das Array für Bilanzen von Symbolen zur Hauptdatei hinzufügen.

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

Anschließend erstellen wir separat die Include-Datei Report.mqh für Funktionen, die Testberichte erzeugen, und binden sie in der Hauptdatei des Expert Advisors ein (siehe markierte Zeile im nachfolgenden Code):

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

Erstellen wir als Erstes eine Struktur für die Eigenschaften von Abschlüssen ähnlich der, die wir in unserem Projekt bereits für die Eigenschaften von Positionen und Symbolen haben. Dazu fügen wir die Aufzählung der Identifikatoren von Eigenschaften zur Datei Enums.mqh hinzu:

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

Anschließend erstellen wir in der Datei Report.mqh die Struktur der Eigenschaften von Abschlüssen und die Funktion GetHistoryDealProperties(), die die Eigenschaft eines Abschlusses ausgibt. Die Funktion akzeptiert zwei Parameter: Ticket des Abschlusses und Identifikator der Eigenschaft.

Nachfolgend sehen Sie den Code der Struktur und der Funktion 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;
     }
  }

Wir werden außerdem mehrere Funktionen brauchen, die einige Eigenschaften von Abschlüssen in String-Werte umwandeln. Diese einfachen Funktionen geben einen Bindestrich ("-") aus, wenn der übergebene wert leer oder Null ist. Schreiben wir sie in die Datei 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));
  }

Nun haben wir alles, was wir zum Schreiben der Funktion CreateSymbolBalanceReport() benötigen, die die Daten für den Bericht vorbereitet und sie in die Datei LastTest.csv schreibt. Es ist ziemlich simpel: Als Erstes schreiben wir die Kopfzeile (achten Sie darauf, wie der String angepasst wird, falls der Test für mehr als ein Symbol ausgeführt wurde), dann werden die erforderlichen Eigenschaften von Abschlüssen für den Bericht zu einem String verbunden, der anschließend in die Datei geschrieben wird.

Nachfolgend sehen Sie den Code der Funktion 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())+"");
  }

Die im Code markierte Funktion MaxDrawdownToString() berechnet alle Wertverluste aus lokalen Maxima und gibt eine String-Darstellung der Zeit aus, zu der ein neues lokales Maximum auftritt. In allen anderen Fällen gibt die Funktion einen String mit einem "-" (Bindestrich) aus.

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

Alle Funktionen für die Erzeugung des Berichts sind also fertig. Wir müssen nur noch herausfinden, wie wir all das nutzen können. Dazu wird die Funktion OnTester() benötigt, die beim Abschluss des Testings aufgerufen wird. Stellen Sie sicher, dass Sie die detaillierte Beschreibung dieser Funktion im Nachschlagewerk MQL5 ansehen.

Schreiben Sie einfach einige Codezeilen in den Körper der Funktion OnTester(), in denen Sie die Bedingung festlegen, unter der der Bericht erzeugt werden soll. Den entsprechenden Code-Ausschnitt sehen Sie unten:

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

Wenn Sie nun den Expert Advisor im Strategietester ausführen, sehen Sie am Ende des Tests einen Ordner des Expert Advisors im Terminal-Stammverzeichnis C:\ProgramData\MetaQuotes\Terminal\Common\Files. Außerdem wird die Bericht-Datei LastTest.csv im Ordner des Expert Advisors erzeugt. Wenn Sie die Datei im Editor öffnen, sehen Sie in etwa Folgendes:

Abbildung 1. Bericht-Datei im .csv-Format

Abbildung 1. Bericht-Datei im .csv-Format.

Erstellen von Diagrammen in Excel

Wir können die erstellte Datei in Excel öffnen und sehen, dass sich jeder Datentyp in einer separaten Spalte befindet. Auf diese Art können die Daten viel bequemer betrachtet werden. An dieser Stelle sind wir technisch gesehen bereit, Diagramme zu erstellen und die Datei als Excel-Tabelle im Format *.xlsx zu speichern. Wenn wir allerdings anschließend den Test ausführen und die Tabelle erneut öffnen, sehen wir immer noch die alten Daten.

Wenn wir versuchen, die Daten zu aktualisieren, während die Datei LastTest.csv bereits in Excel verwendet wird, wird die Datei nicht aktualisiert, da es dem Expert Advisor nicht möglich ist, die Datei zum Schreiben zu öffnen, während sie von einer anderen Anwendung verwendet wird.

Abbildung 2. Bericht-Datei im .csv-Format in Excel 2010

Abbildung 2. Bericht-Datei im .csv-Format in Excel 2010.

Dafür gibt es in unserem Fall eine Lösung. Erstellen Sie zunächst eine Excel-Tabelle im Format *.xlsx in einem beliebigen Ordner. Öffnen Sie die Tabelle und gehen Sie zur Registerkarte Daten.

Abbildung 3. Registerkarte Daten in Excel 2010

Abbildung 3. Registerkarte Daten in Excel 2010.

Wählen Sie im Ribbon dieser Registerkarte die Option Aus Text. Es öffnet sich der Dialog Textdatei importieren, in dem Sie die Datei "LastTest.csv" auswählen. Wählen Sie die Datei aus und klicken Sie auf Öffnen. Der Dialog Textkonvertierungs-Assistent - Schritt 1 von 3 öffnet sich, wie unten dargestellt:

Abbildung 4. Dialog "Textkonvertierungs-Assistent - Schritt 1 von 3"

Abbildung 4. Dialog "Textkonvertierungs-Assistent - Schritt 1 von 3".

Passen Sie die Einstellungen an, wie oben dargestellt, und klicken Sie auf Weiter >. Hier (Schritt 2 von 3) müssen Sie das in der Datendatei genutzte Trennzeichen festlegen. In unserem Fall ist es "," (Komma).

Abbildung 5. Dialog "Textkonvertierungs-Assistent - Schritt 2 von 3"

Abbildung 5. Dialog "Textkonvertierungs-Assistent - Schritt 2 von 3".

Klicken Sie auf Weiter >, um mit Textkonvertierungs-Assistent - Schritt 3 von 3 fortzufahren. Wählen Sie hier Standard als Datenformat für alle Spalten. Sie können das Format später ändern.

Abbildung 6. Dialog "Textkonvertierungs-Assistent - Schritt 3 von 3"

Abbildung 6. Dialog "Textkonvertierungs-Assistent - Schritt 3 von 3".

Nachdem Sie auf Fertig stellen geklickt haben, öffnet sich das Fenster Daten importieren, in dem Sie das Arbeitsblatt und die Zelle für den Datenimport festlegen müssen.

Abbildung 7. Auswahl der Zelle für den Datenimport in Excel 2010

Abbildung 7. Auswahl der Zelle für den Datenimport in Excel 2010.

Für gewöhnlich wählen wir die obere linke Zelle A1. Bevor Sie auf OK klicken, klicken Sie auf Eigenschaften..., um die Eigenschaften des externen Datenbereiches festzulegen. Sie sehen das unten abgebildete Dialogfenster.

Abbildung 8. Eigenschaften des externen Datenbereichs beim Importieren von Daten aus Textdateien in Excel 2010

Abbildung 8. Eigenschaften des externen Datenbereichs beim Importieren von Daten aus Textdateien in Excel 2010.

Passen Sie die Einstellungen an, wie oben abgebildet, und klicken Sie in diesem und dem nachfolgenden Fenster auf OK.

Als Ergebnis erscheinen Ihre Daten in der gleichen Form, als hätten Sie einfach die .csv-Datei geladen. Doch nun können Sie wiederholte Tests in MetaTrader 5 ausführen, ohne die Excel-Tabelle schließen zu müssen. Nach dem Test müssen sie lediglich mithilfe von Strg+Alt+F5 die Daten aktualisieren oder auf die Schaltfläche Alle aktualisieren im Ribbon der Registerkarte Daten klicken.

Mithilfe der Bedingten Formatierung in der Registerkarte Start können Sie die erforderlichen optischen Eigenschaften der Darstellung der Daten festlegen.

Abbildung 9. Bedingte Formatierung in Excel 2010

Abbildung 9. Bedingte Formatierung in Excel 2010.

Nun müssen wir die Daten in Excel-Diagrammen abbilden. Ein Diagramm wird alle Bilanzdiagramme anzeigen, das andere alle Wertverluste aus lokalen Maxima als Histogramm.

Erstellen wir als Erstes ein Diagramm für die Bilanzdiagramme. Wählen Sie die Überschriften aller Bilanzen und den gesamten Datenbereich von oben nach unten (halten Sie dabei die Umschalttaste gedrückt, drücken Sie die Taste Ende und dann den Pfeil nach unten). Wählen Sie nun unter der Registerkarte Einfügen den erforderlichen Diagrammtyp.

Abbildung 10. Auswahl des Diagrammtypen in Excel 2010

Abbildung 10. Auswahl des Diagrammtypen in Excel 2010.

Es wird ein Diagramm erstellt, das zur Erleichterung der Arbeit in ein anderes Arbeitsblatt verschoben werden kann. Wählen Sie es dazu einfach aus und drücken Sie Strg+X (Ausschneiden). Wechseln Sie dann zum neu erstellten Arbeitsblatt, wählen Sie die Zelle A1 und drücken Sie Strg+V (Einfügen).

Das erstellte Diagramm mit Standardeinstellungen ist in der nachfolgenden Abbildung dargestellt:

Abbildung 11. Look and Feel des Diagramms mit Standardeinstellungen.

Abbildung 11. Look and Feel des Diagramms mit Standardeinstellungen.

Sie können jedes Element des Diagramms personalisieren: Größe, Farbe Stil usw. ändern.

In der obigen Abbildung zeigt die horizontale Achse die Anzahl der Abschlüsse. Verändern wir sie dahingehend, dass sie stattdessen Daten anzeigt. Rechtsklicken Sie hierzu auf das Diagramm und wählen Sie die Option Daten auswählen... aus dem Kontextmenü. Es erscheint der Dialog Datenquelle auswählen. Klicken Sie auf Bearbeiten, dann auf den erforderlichen Datenbereich in der Spalte TIME und zum Schluss auf OK.

Abbildung 12. Dialogfenster "Datenquelle auswählen"

Abbildung 12. Dialogfenster "Datenquelle auswählen".

Versuchen Sie, das Diagramm der Wertverluste selbst zu erstellen, und platzieren Sie es unter dem ersten Diagramm. Nun können ihre optischen Eigenschaften angepasst werden, falls erforderlich. Ich persönlich gestalte sie für gewöhnlich so:

Abbildung 13. Benutzerdefinierte Diagramme in Excel 2010.

Abbildung 13. Benutzerdefinierte Diagramme in Excel 2010.


Fazit

Nun verfügen wir über Excel-Diagramme mit Testergebnissen, die ziemlich gut aussehen. In einem meiner zukünftigen Beiträge werde ich Ihnen zeigen, wie Sie noch informationsreichere Berichte erstellen können. Im Anhang des Beitrags finden Sie ein Archiv mit den Dateien des Expert Advisors.

Legen Sie den Ordner ReportInExcel nach dem Entpacken der Dateien in das Verzeichnis MetaTrader 5\MQL5\Experts. Außerdem muss der Indikator EventsSpy.mq5 im Ordner MetaTrader 5\MQL5\Indicators abgelegt werden.

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/651

Beigefügte Dateien |
eventsspy__4.mq5 (7.59 KB)
reportinexcel.zip (26.73 KB)
Das MQL5-Kochbuch: Abschwächen der Auswirkungen von Überanpassungen und Umgang mit mangelnden Geboten Das MQL5-Kochbuch: Abschwächen der Auswirkungen von Überanpassungen und Umgang mit mangelnden Geboten
Ganz egal, welche Handelsstrategie Sie anwenden, wird immer die Frage bestehen, welche Parameter gewählt werden sollen, um zukünftige Gewinne zu sichern. Dieser Beitrag liefert ein Beispiel für einen Expert Advisor mit der Möglichkeit, mehrere Symbolparameter gleichzeitig zu optimieren. Diese Methode dient dazu, die Auswirkungen der Überanpassung von Parametern abzuschwächen und mit Situationen umzugehen, in denen die Daten aus einem einzelnen Symbol nicht für eine eingehende Betrachtung ausreichen.
Das MQL5-Kochbuch: Entwicklung eines mehrwährungsfähigen Expert Advisors mit unbegrenzter Anzahl von Parametern Das MQL5-Kochbuch: Entwicklung eines mehrwährungsfähigen Expert Advisors mit unbegrenzter Anzahl von Parametern
In diesem Beitrag werden wir ein Muster erstellen, das einen einzelnen Satz von Parametern für die Optimierung eines Handelssystems nutzt und gleichzeitig eine unbegrenzte Anzahl von Parametern ermöglicht. Die Liste der Symbole wird in einer Standard-Textdatei (*.txt) erstellt. Die Eingabeparameter jedes Symbols werden ebenfalls in Dateien gespeichert. Auf diese Weise können wir die Terminal-seitige Begrenzung der Anzahl von Eingabeparametern eines Expert Advisors umgehen.
Multiple Regressionsanalyse. Anlegen und Prüfen von Strategien aus einer Hand Multiple Regressionsanalyse. Anlegen und Prüfen von Strategien aus einer Hand
Dieser Beitrag schildert die Anwendung der multiplen Regressionsanalyse bei der Entwicklung automatischer Handelssysteme (im Weiteren Expert-Systeme). Es werden Beispiele für ihren Einsatz bei der Automatisierung der Suche nach der richtigen Strategie sowie für eine ohne nennenswerte Vorkenntnisse in Sachen Programmierung angelegte und in ein Expert-System integrierte Regressionsgleichung.
Das MQL5-Kochbuch: Mehrwährungsfähiger Expert Advisor – eine einfache, saubere und schnelle Herangehensweise Das MQL5-Kochbuch: Mehrwährungsfähiger Expert Advisor – eine einfache, saubere und schnelle Herangehensweise
In diesem Beitrag wird die Umsetzung einer einfachen Herangehensweise an einen mehrwährungsfähigen Expert Advisor beschrieben. Das heißt, Sie werden in der Lage sein, den Expert Advisor für das Testen/den Handel unter identischen Bedingungen aber mit unterschiedlichen Parametern je Symbol einzurichten. Als Beispiel erstellen wir ein Muster für zwei Symbole auf eine Weise, mit der Sie nach Bedarf zusätzliche Symbole hinzufügen können, indem Sie kleine Änderungen am Code vornehmen.