Erstellen benutzerdefinierter Optimierungskriterien für Expert Advisors

Dmitriy Skub | 7 April, 2016

Einleitung

Das MetaTrader 5 Client Terminal bietet eine Vielzahl von Optimierungsmöglichkeiten für die Parameter von Expert Advisors. Zusätzlich zu den im Strategietester enthaltenen Optimierungskriterien erhalten Entwickler die Möglichkeit, ihre eigenen Kriterien zu erstellen. Dies führt zu einer fast unbegrenzten Menge an Möglichkeiten zum Testen und Optimieren von Expert Advisors. Dieser Beitrag beschreibt praktische Möglichkeiten zum Erstellen solcher Kriterien, sowohl komplexer als auch einfacher.



1. Überblick über die Funktionen des Strategietesters

Dieses Thema wurde sehr oft besprochen, deshalb erstelle ich nur eine Liste von Beiträgen, jeweils mit einer kurzen Beschreibung. Ich empfehle, dass Sie sich mit den folgenden Materialien vertraut machen, bevor Sie diesen Beitrag lesen.

Natürlich müssen Sie sich zunächst auch mit der Dokumentation vertraut machen, die mit den Client Terminal bereitgestellt wurde.



2. Im Strategietester eingebaute Optimierungskriterien

In der Dokumentation finden Sie die folgende Beschreibung: Ein Optimierungskriterium ist ein bestimmter Faktor, dessen Wert die Qualität eines getesteten Satzes von Parametern definiert. Je höher der Wert der Optimierungskriteriums ist, desto besser ist das Testergebnis mit dem vorliegenden Parametersatz zu bewerten.

Hier sollten wir etwas Wichtiges festhalten: Ein Optimierungskriterium kann nur im genetischen Algorithmusmodus der Optimierung verwendet werden. Es ist klar, dass bei der Betrachtung aller möglichen Kombinationen von Parameterwerten irgendein Faktor für die Auswahl der optimalen Parameter eines Expert Advisors fehlt. Andererseits können wir die Testergebnisse speichern und sie dann verarbeiten, um eine optimale Kombination von Parametern zu finden.

Wie in der Dokumentation dargelegt, enthält der Strategietester die folgenden Optimierungskriterien für die Verwendung mit dem genetischen Algorithmus:

Ein Optimierungskriterium kann in der Registerkarte Settings (Einstellungen) des Strategietesters ausgewählt werden, wie in Abb. 1 dargestellt:

Auswahl der Optimierungskriteriums für den Expert Advisor

Abb. 1. Auswahl der Optimierungskriteriums für den Expert Advisor

Das letzte Kriterium in der Liste, Custom max, ist das interessanteste für uns und seine Verwendung ist das Thema dieses Beitrags.



3. Erstellung benutzerdefinierter Optimierungskriterien

Als Erstes sollte der Benutzer die Möglichkeit erhalten, Parameter frei zu kombinieren (nicht begrenzt auf die in Abb. 1 dargestellten, sondern benutzerdefinierte), die nach jedem Durchlauf des Expert Advisors durch den Strategietester berechnet werden.

Beispielsweise ist die folgende Variante interessant: Balance max + min Drawdown + Trades Number – je mehr Abschlüsse es gibt, desto zuverlässiger ist das Ergebnis. Oder: Balance max + min Drawdown + max Profit Factor. Natürlich gibt es viele weitere interessante Kombinationen, die nicht in den Einstellungen des Strategietesters enthalten sind.

Bezeichnen wir solche Kombinationen von Kriterien als einfache Optimierungskriterien.

Doch diese Kriterien reichen nicht aus, um eine zuverlässige Bewertung eines Handelssystems anzustellen. Wenn wir es aus der Handelsperspektive betrachten – Gewinn machen bei minimalem Risiko –, können wir vom folgenden Kriterium ausgehen: Wir können Parameter optimieren, um eine möglichst glatte Bilanzkurve mit minimaler Abweichung der Ergebnisse verschiedener Abschlüsse von der Geraden zu erhalten.

Bezeichnen wir dieses Kriterium als Kriterium der Optimierung durch die Bilanzkurve.

Das nächste Optimierungskriterium, das wir verwenden werden, ist der Koeffizient der Sicherheit eines Handelssystems. Dieser Koeffizient wird im Beitrag "Be In-Phase" beschrieben. [Anm. d. Übers.: Zum Zeitpunkt der Übersetzung existiert dieser Beitrag nur auf Russisch und trägt den Titel "Будь в фазе".] Er bestimmt die Entsprechung eines Handelssystems mit dem Markt und dies ist, was wir während der Optimierung von Parametern herausfinden müssen. Bezeichnen wir dies als Kriterium der Optimierung durch den Koeffizienten der Sicherheit eines Handelssystems (CSTS).

Zusätzlich ermöglichen wir es, die beschriebenen Kriterien frei zu kombinieren.



4. Die Funktion OnTester()

Bevor wir die Codeteile schreiben, sehen wir uns die Einrichtung der Nutzung benutzerdefinierter Kriterien der Optimierung von EAs im Strategietester an.

Die vordefinierte Funktion OnTester() dient der Erstellung von benutzerdefinierten Optimierungskriterien. Sie wird automatisch am Ende jedes Durchlaufs eines Expert Advisors innerhalb eines festgelegten Zeitbereichs aufgerufen. Diese Funktion wird unmittelbar vor dem Aufruf der Funktion OnDeinit() aufgerufen.

Ich möchte nochmals betonen, dass Sie für die Nutzung der Funktion OnTester() den Optimierungsmodus Fast genetic base algorithm aktivieren sollten, wie in Abb. 1 dargestellt.

Der ausgegebene Wert dieser Funktion hat das Format double, der für die Optimierung im Strategietester verwendet wird.

Sehen Sie sich die Dokumentation erneut an:

Bei der genetischen Optimierung werden die Ergebnisse innerhalb einer Generation in absteigender Reihenfolge angeordnet. Das bedeutet, aus der Sicht des Optimierungskriteriums sind die besten Ergebnisse jene mit den größten Werten. Bei dieser Anordnung befinden sich die schlechtesten Werte am Ende und werden verworfen und beteiligen sich nicht an der Formierung der nächsten Generation.

Somit müssen wir beim Erstellen eines benutzerdefinierten Optimierungskriteriums einen ganzzahligen Wert erhalten, der für die Schätzung des Handels des Expert Advisors verwendet wird. Je höher der Wert ist, desto besser ist der Handel des Expert Advisors.



5. Schreibens eines experimentellen Expert Advisors

Nun ist es an der Zeit, einen Expert Advisor zu erstellen, den wir im Strategietester optimieren werden. Die Hauptanforderungen sind in diesem Fall, dass er einfach und schnell ist, um nicht viel Zeit mit der Routineaufgabe der Optimierung zu verlieren. Es ist auch wünschenswert, dass der Expert Advisor nicht allzu unrentabel ist.

Nutzen wir für das Experiment den im Beitrag "Verschiedene Wege zur Ermittlung eines Trends in MQL5" beschriebenen Expert Advisor und verbessern ihn. Konkret nehmen wir den EA, der auf dem "Fächer" aus drei gleitenden Mittelwerten basiert. Die Verbesserung besteht aus der Beseitigung der Verwendung des Indikators, um die Betriebsgeschwindigkeit zu erhöhen, und der Verschiebung des Berechnungsteils des Codes in das Innere des EAs selbst. Dadurch kann die Testgeschwindigkeit deutlich erhöht werden (knapp um das Dreifache in einem zweijährigen Zeitraum).

Die Festlegung der Eingabeparameter ist einfach:

input double Lots = 0.1; 
input int  MA1Period = 200; // period of the greatest moving average
input int  MA2Period = 50;  // period of the medium moving average
input int  MA3Period = 21;  // period of the smallest moving average

Die Zeiträume der gleitenden Mittelwerte sind es, die wir optimieren werden.

Die Struktur und der Betrieb des Expert Advisors werden im oben genannten Beitrag detailliert beschrieben, deshalb überspringen wir dies an dieser Stelle. Die wichtigste Innovation ist der Handler des Ereignisses des Abschlusses eines weiteren Testdurchlaufs – die Funktion OnTester(). Aktuell ist sie leer und gibt einfach die Steuerung aus.

//---------------------------------------------------------------------
//  The handler of the event of completion of another test pass:
//---------------------------------------------------------------------
double OnTester()
{
  return(0.0);
}

Die EA-Datei FanExpert.mq5 ist an diesen Beitrag angehängt. Wir können uns vergewissern, dass er aus der Sicht der durchgeführten Abschlüsse identisch mit dem EA FanTrendExpert.mq5 ist. Die Überprüfung des Vorhandenseins und der Richtung eines Signals wird bei der Eröffnung eines neuen Balkens in einem Diagramm ausgeführt.

Damit das Testergebnis am Ende jedes Durchlaufs berechnet wird, wird die Funktion TesterStatistics() verwendet. Sie gibt den angeforderten berechneten statistischen Wert als Testergebnis aus. Sie kann ausschließlich aus den Funktionen OnTester() und OnDeinit() aufgerufen werden, andernfalls ist das Ergebnis nicht definiert.

Fügen wir nun ein benutzerdefiniertes Optimierungskriterium hinzu. Nehmen wir an, dass wir optimale Ergebnisse auf Basis eines Maximalwerts des Erholungsfaktors finden müssen – max Recovery Factor. Dazu müssen wir die Werte des max. Wertverlusts der Bilanz in Geldeinheiten und den Bruttogewinn am Ende des Testens kennen. Der Erholungsfaktor wird als Division des Gewinns durch den maximalen Wertverlust berechnet.

Dies dient nur als Beispiel, da der Erholungsfaktor bereits in der Liste der statistischen Testergebnisse enthalten ist.

Fügen Sie dazu den folgenden einfachen Code zur Funktion OnTester() hinzu:

//---------------------------------------------------------------------
//  The handler of the event of completion of another test pass:
//---------------------------------------------------------------------
double OnTester()
{
  double  profit = TesterStatistics(STAT_PROFIT);
  double  max_dd = TesterStatistics(STAT_BALANCE_DD);
  double  rec_factor = profit/max_dd;

  return(rec_factor);
}

Die Überprüfung auf Nulldivision ist zur Vereinfachung aus dem Code ausgeschlossen. Da der maximale Wertverlust Null sein kann, muss diese Überprüfung in einem realen Expert Advisor durchgeführt werden.

Erstellen wir nun das oben erwähnte Kriterium: Balance max + min Drawdown + Trades Number – Bilanz + minimaler Wertverlust + Anzahl der Abschlüsse.

Passen Sie dazu die Funktion OnTester() an, wie folgt:

double OnTester()
{
  double  param = 0.0;

//  Balance max + min Drawdown + Trades Number:
  double  balance = TesterStatistics(STAT_PROFIT);
  double  min_dd = TesterStatistics(STAT_BALANCE_DD);
  if(min_dd > 0.0)
  {
    min_dd = 1.0 / min_dd;
  }
  double  trades_number = TesterStatistics(STAT_TRADES);
  param = balance * min_dd * trades_number;

  return(param);
}

Hier nehmen wir einen dem Wertverlust entgegengesetzten Wert, denn je kleiner der Wertverlust ist, desto besser ist die Situation, vorausgesetzt, die restlichen Bedingungen sind gleich. Führen Sie die Optimierung des EAs FanExpert mit dem erstellten Optimierungskriterium durch den Parameter MA1Period durch und nutzen Sie dazu den Zeitraum 2009.06.01 - 2011.06.03 und den H1-Timeframe. Legen Sie den Wertebereich des gleitenden Mittelwerts zwischen 100 und 2000 fest.

Am Ende der Optimierung erhalten Sie die folgende Wertetabelle, sortiert nach den besten Parametern:

Die besten Optimierungsergebnisse nach dem Kriterium Balance max + min Drawdown + Trades Number

Abb. 2. Die besten Optimierungsergebnisse nach dem Kriterium Balance max + min Drawdown + Trades Number

Die besten Parameter werden hier aufgelistet (nach der Spalte Result (Ergebnis)).

Sehen wir uns nun die schlechtesten Parameter an:

Abb. 3. Die schlechtesten Optimierungsparameter nach dem Kriterium Balance max + min Drawdown + Trades Number

Beim Vergleich der beiden Tabellen können Sie erkennen, dass der Wertverlust und der Gewinn zusammen mit der Anzahl der Abschlüsse berücksichtigt werden, d. h. unser Optimierungskriterium funktioniert. Zusätzlich können wir das Optimierungsdiagramm (linear) ansehen:

Optimierungsdiagramm

Abb. 4. Das Optimierungsdiagramm nach dem Kriterium Balance max + min Drawdown + Trades Number

Die horizontale Achse zeigt den optimierten Parameter, die vertikale das Optimierungskriterium. Man kann ein klares Maximum des festgelegten Kriteriums erkennen. Es befindet sich im Zeitraum zwischen 980 und 1200.

Denken Sie immer daran, dass es sich um die genetische Optimierung von Parametern handelt, keine vollständige Auswahl. Deshalb enthalten die Tabellen in Abb. 2 und Abb. 3 die "lebensfähigsten" Parameter, die die natürliche Auswahl in mehreren Generationen überstanden haben. Vermutlich wurden einige erfolgreiche Varianten verworfen.

Die Bilanz-Kapital-Kurve für den Zeitraum 1106 sieht folgendermaßen aus:

Bilanz-Kapital-Kurve für MA1Period = Zeitraum 1106

Abb. 5. Bilanz-Kapital-Kurve für MA1Period = Zeitraum 1106



6. Erstellung von Klassen benutzerdefinierter Optimierungskriterien

Wir haben also gelernt, wie einfache Optimierungskriterien erstellt und verwendet werden. Schaffen wir nun eine Klasse, um ihre Verwendung in Expert Advisors zu erleichtern. Eine der Hauptanforderungen für eine solche Klasse ist neben der Benutzerfreundlichkeit die Arbeitsgeschwindigkeit. Die Berechnungen von Optimierungskriterien müssen schnell durchgeführt werden, andernfalls müssen Sie zu lange auf die Ergebnisse warten.

Mit MetaTrader 5 lässt sich die Cloud-Berechnungstechnologie für die Optimierung nutzen. Das ist ein bedeutender Durchbruch, denn die Verarbeitung einer großen Menge von Parametern erfordert eine riesige Rechenleistung. Deshalb nutzen wir für die Entwicklung unserer Klasse die einfachsten und schnellsten Lösungen, auch wenn sie aus Programmierersicht nicht sehr elegant sind.

Wir verwenden für die Entwicklung die Standardklassen für die Organisation von Daten, die zusammen mit dem Client Terminal ausgeliefert werden.

Klassifizieren wir zuallererst die Typen der berechneten statistischen Testergebnisse:

In anderen Worten: Je höher der Wert des Testergebnisses ist, desto besser und höher ist der Wert des Optimierungskriteriums. Ein markantes Beispiel eines solchen Testergebnisses ist der Bruttogewinn am Ende des Tests von STAT_PROFIT. Der Wert hat ein Gleitkomma-Format und kann von negativ-unendlich (tatsächlich begrenzt durch den Wert der Einlage) zu positiv-unendlich wechseln.

Ein weiteres Beispiel des Testergebnisses dieses Typen ist die Anzahl der Abschlüsse STAT_TRADES. Allgemein gilt: Je größer die Menge der Abschlüsse, desto zuverlässiger ist das Optimierungsergebnis. Der Wert hat ein ganzzahliges Format und kann von Null zu positiv-unendlich wechseln.

In anderen Worten: Je kleiner der Wert des Testergebnisses ist, desto besser und höher ist der Wert des Optimierungskriteriums. Ein Beispiel eines solchen Testergebnisses ist der maximale Wertverlust der Bilanz in Geldeinheiten STAT_BALANCE_DD sowie jeder andere Wertverlust.

Um diese Art von Testergebnis zu erhalten, nehmen wir einen umgekehrten Wert für die Berechnung des Wertes des Optimierungskriteriums. Natürlich müssen wir die Überprüfung auf Nulldivision implementieren, um den entsprechenden Fehler zu vermeiden.

TCustomCriterion, die Basisklasse für die Erstellung der benutzerdefinierten Optimierungskriterien, ist äußerst simpel. Ihr Zweck ist die Bestimmung der Basisfunktionalität. Das sieht dann so aus:

class TCustomCriterion : public CObject
{
protected:
  int     criterion_level;        // type of criterion

public:
  int   GetCriterionLevel();
  virtual double  GetCriterion();  // get value of the result of optimization
};

Die virtuelle Methode TCustomCriterion::GetCriterion muss in vererbten Klassen überschrieben werden. Dabei handelt es sich um die Hauptmethode, die den Wert des ganzzahligen Ergebnisses des Tests eines Expert Advisors am Ende jedes Testdurchlaufs ausgibt.

Das Klassenmitglied TCustomCriterion::criterion_level speichert den dieser Klasseninstanz inhärenten Typ von benutzerdefiniertem Kriterium. Dies wird im weiteren Verlauf für die Unterscheidung von Objekten nach ihren Typen genutzt.

Nun können wir daraus alle Klassen erben, die für die Optimierung benötigt werden.

Die Klasse TSimpleCriterion dient der Erstellung eines "einfachen" benutzerdefinierten Kriteriums, das einem bestimmten statistischen Testergebnis entspricht. Ihre Bestimmung sieht so aus:

class TSimpleCriterion : public TCustomCriterion
{
protected:
  ENUM_STATISTICS  stat_param_type;

public:
  ENUM_STATISTICS  GetCriterionType();     // get type of optimized stat. parameter

public:
  virtual double   GetCriterion(); // receive optimization result value
  TSimpleCriterion(ENUM_STATISTICS _stat); // constructor
};

Hier nutzen wir einen Konstruktor mit Parametern, der auf folgende Weise umgesetzt wird:

//---------------------------------------------------------------------
//  Constructor:
//---------------------------------------------------------------------
TSimpleCriterion::TSimpleCriterion(ENUM_STATISTICS _stat)
:
stat_param_type( _stat )
{
  criterion_level = 0;
}

Diese neue Funktion in der MQL5-Sprache lässt sich bei der Erstellung von Klasseninstanzen bequem nutzen. Zudem haben wir die virtuelle Methode TSimpleCriterion::GetCriterion überschrieben, die zum Abrufen des Optimierungsergebnisses am Ende jedes Testdurchlaufs verwendet wird. Ihre Umsetzung ist einfach:

//---------------------------------------------------------------------
//  Get the result of optimization:
//---------------------------------------------------------------------
double  TSimpleCriterion::GetCriterion()
{
  return(TesterStatistics(stat_param_type));
}

Wie Sie sehen, gibt sie nur das entsprechende statistische Testergebnis aus.

Der nächste Typ des "einfachen" benutzerdefinierten Optimierungskriteriums wird mithilfe der Klasse TSimpleDivCriterion erstellt. Sie ist für Kriterien mit umgekehrter Proportionalität zwischen den Werten der Testergebnisse und dem Optimierungskriterium vorgesehen.

Die Methode TSimpleDivCriterion::GetCriterion sieht so aus:

//---------------------------------------------------------------------
//  Get value of the optimization result:
//---------------------------------------------------------------------
double  TSimpleDivCriterion::GetCriterion()
{
  double  temp = TesterStatistics(stat_param_type);
  if(temp>0.0)
  {
    return(1.0/temp);
  }
  return(0.0);
}

Der Code benötigt keinerlei zusätzliche Beschreibung.

Zwei weitere Typen "einfacher" benutzerdefinierter Optimierungskriterien werden mithilfe der Klassen TSimpleMinCriterion und TSimpleMaxCriterion erstellt. Sie sind für die Erstellung von Kriterien mit begrenzten Werten von statistischen Testergebnissen jeweils nach Minimum und Maximum vorgesehen.

Sie können nützlich sein, wenn Sie absichtlich falsche Parameterwerte während der Optimierung verwerfen möchten. Beispielsweise können Sie die Mindestmenge von Abschlüssen, den maximalen Wertverlust usw. begrenzen.

Die Beschreibung der Klasse TSimpleMinCriterion sieht so aus:

class TSimpleMinCriterion : public TSimpleCriterion
{
  double  min_stat_param;

public:
  virtual double  GetCriterion();    // receive optimization result value
  TSimpleMinCriterion(ENUM_STATISTICS _stat, double _min);
};

Hier nutzen wir den Konstruktor mit zwei Parametern. Der Parameter _min legt den Mindestwert eines statistischen Testergebnisses fest. Wenn ein weiterer Testdurchlauf zu einem Ergebnis führt, das unter dem festgelegten Wert liegt, wird dieses Ergebnis verworfen.

Die Umsetzung der Methode TSimpleMinCriterion ::GetCriterion sieht so aus:

//---------------------------------------------------------------------
//  Get value of the optimization result:
//---------------------------------------------------------------------
double  TSimpleMinCriterion::GetCriterion()
{
  double  temp = TesterStatistics(stat_param_type);
  if(temp<this.min_stat_param)
  {
    return(-1.0);
  }
  return(temp);
}

Die Klasse TSimpleMaxCriterion wird ähnlich erstellt und benötigt keine weitere Beschreibung. Die weiteren Klassen von "einfachen" benutzerdefinierten Kriterien werden auf ähnliche Weise wie die oben beschriebenen erstellt. Sie finden sie in der an diesen Beitrag angehängten Datei CustomOptimisation.mqh. Das gleiche Prinzip lässt sich auf die Entwicklung jeder beliebigen anderen Klasse für die Nutzung im Zuge der Optimierung anwenden.

Bevor wir die oben beschriebenen Klassen verwenden, erstellen wir eine Container-Klasse für eine bequemere Arbeit mit dem Kriteriensatz. Zu diesem Zweck nutzen wir ebenfalls die Standardklassen für die Organisation von Daten. Da wir eine einfache weitere Verarbeitung der Kriterien benötigen, ist CArrayObj die am besten geeignete Klasse. Sie ermöglicht die Einrichtung eines dynamischen Arrays von Objekten, das von der Klasse CObject vererbt wird.

Die Beschreibung der Container-Klasse TCustomCriterionArray ist äußerst einfach:

class TCustomCriterionArray : public CArrayObj
{
public:
  virtual double  GetCriterion( );  // get value of the optimization result
};

Mit TCustomCriterionArray::GetCriterion verfügt sie nur über eine Methode, die den Wert des Optimierungskriteriums am Ende jedes Testdurchlaufs ausgibt. Ihre Umsetzung sieht so aus:

double  TCustomCriterionArray::GetCriterion()
{
  double  temp = 1.0;
  int     count = this.Total();
  if(count == 0)
  {
    return(0.0);
  }
  for(int i=0; i<count; i++)
  {
    temp *= ((TCustomCriterion*)(this.At(i))).GetCriterion();
    if(temp <= 0.0)
    {
      return(temp);
    }
  }

  return(temp);
}

Beachten Sie: Wenn Sie beim Verarbeiten von Kriterien einen negativen Wert erhalten, ist der weitere Durchlauf des Zyklus sinnlos. Außerdem wird die Situation ausgeschlossen, dass Sie einen positiven Wert als Ergebnis der Multiplikation zweier negativer Werte erhalten.

7. Nutzung von Klassen benutzerdefinierter Optimierungskriterien

Nun haben wir alles, um die "einfachen" benutzerdefinierten Kriterien bei der Optimierung von Expert Advisors nutzen zu können. Analysieren wir die Schritte zum Verbessern des "experimentellen" EAs FanExpert:

#include <CustomOptimisation.mqh>
TCustomCriterionArray*  criterion_Ptr;
  criterion_array = new TCustomCriterionArray();
  if(CheckPointer(criterion_array) == POINTER_INVALID)
  {
    return(-1);
  }

Dies geschieht mithilfe der Funktion OnInit. Bei fehlgeschlagener Erstellung des Objekts wird ein negativer Wert ausgegeben. In diesem Fall bricht der Expert Advisor seine Arbeit ab.

  criterion_Ptr.Add(new TSimpleCriterion(STAT_PROFIT));
  criterion_Ptr.Add(new TSimpleDivCriterion(STAT_BALANCE_DD));
  criterion_Ptr.Add(new TSimpleMinCriterion(STAT_TRADES, 20.0));

In diesem Fall haben wir entschieden, den EA nach maximalem Gewinn, minimalem Wertverlust und der maximalen Menge von Abschlüssen zu optimieren. Zusätzlich verwerfen wir Sätze von externen Parametern des Expert Advisors, die zu weniger als zwanzig Abschlüssen führen.

  return(criterion_Ptr.GetCriterion());
  if(CheckPointer(criterion_Ptr) == POINTER_DYNAMIC)
  {
    delete(criterion_Ptr);
  }

Das ist schon die ganze Optimierung. Führen Sie die Optimierung aus und stellen Sie sicher, dass alles so funktioniert, wie es soll. Legen Sie dazu die Parameter in der Registerkarte Settings des Strategietesters fest, wie in der nachfolgenden Abbildung dargestellt:

Einstellungen des Strategietesters

Abb. 6. Einstellungen des Strategietesters

Anschließend legen Sie den Optimierungsbereich der Eingabeparameter in der Registerkarte Input parameters des Strategietesters fest, wie in Abb. 7 dargestellt:

Optimierte Eingabeparameter

Abb. 7. Optimierte Eingabeparameter

Nutzen Sie für die Optimierung die Cloud-Agenten. Legen Sie dazu die folgenden Parameter in der Registerkarte Agents fest:

Parameter von Testagenten

Abb. 8. Parameter von Testagenten

Klicken Sie nun auf die Schaltfläche Start (Abb. 6) und warten Sie auf die Fertigstellung der Optimierung. Bei der Nutzung der Cloud-Berechnungstechnologie wird die Optimierung ziemlich schnell durchgeführt. Am Ende erhalten wir die folgenden Optimierungsergebnisse nach den festgelegten Kriterien:

Optimierungsergebnisse

Abb. 9. Optimierungsergebnisse

Unser "experimenteller" Expert Advisor wurde erfolgreich optimiert. Mithilfe der Cloud-Agenten hat die Optimierung 13 Minuten gedauert. Der EA für die Überprüfung des Kriteriums befindet sich in der an diesen Beitrag angehängten Datei FanExpertSimple.mq5.



8. Erstellen einer Klasse eines benutzerdefinierten Optimierungskriteriums auf Basis der Analyse der Bilanzkurve

Die Grundlage für die Erstellung dieser Klasse bildet der Beitrag "Kontrolle der Saldo-Gefällekurve während der Arbeit eines Expert Advisors". Die Idee hinter diesem Optimierungskriterium ist es, die Linie der Bilanz so nah wie möglich an eine gerade Linie zu bringen. Das Ausmaß der Nähe zu einer geraden Linie wird anhand des Wertes der Standardabweichung der Handelsergebnisse davon bewertet. Die Gleichung einer geraden Linie wird für die Regressionslinie berechnet, die durch die Ergebnisse von Abschlüssen im Strategietester gezeichnet wird.

Legen Sie zusätzliche Grenzwerte fest, um Kurven mit negativer resultierender Bilanz zu verwerfen: Der resultierende Gewinn muss größer als ein festgelegter Wert sein und die Menge der Abschlüsse darf nicht unter einem festgelegten Wert liegen.

Somit wird unser Optimierungskriterium umgekehrt proportional zum Wert der Standardabweichung der Handelsergebnisse von der geraden Linie unter Berücksichtigung der Grenzwerte des resultierenden Gewinns und der Menge der Abschlüsse sein.

Um das Optimierungskriterium auf Basis der Bilanzkurve umzusetzen, brauchen wir die Klasse TBalanceSlope aus dem oben erwähnten Beitrag. Wir werden diese Klasse anpassen, indem wir (aus Bequemlichkeitsgründen) Konstruktoren mit Parametern nutzen und die Berechnung der Standardabweichung zur Berechnung der linearen Regression hinzufügen. Dieser Code befindet sich in der an diesen Beitrag angehängten Datei BalanceSlope.mqh.

Die Abfolge der Schritte zum Hinzufügen dieses Optimierungskriteriums zum Expert Advisor ist die gleiche wie die oben beschriebene. Nun sehen die Optimierungskriterien so aus:

criterion_Ptr.Add(new TBalanceSlopeCriterion(Symbol( ), 10000.0));

Zusätzlich zum Kriterium der Bilanzkurve können wir weitere von uns entwickelte Kriterien hinzufügen. Ich lasse den Lesern die Möglichkeit, mit verschiedenen Sätzen statistischer Testparameter zu experimentieren.

Führen wir nun die Optimierung nach den festgelegten Kriterien durch. Um mehr Abschlüsse zu erhalten, führen Sie die Optimierung mithilfe des H4-Timeframes, des Zeitraums 2010.01.01 - 2011.01.01 und des Symbols EURUSD aus. Wir erhalten einen Satz von Ergebnissen:

Ergebnis der Optimierung nach Bilanzkurve

Abb. 10. Ergebnis der Optimierung nach Bilanzkurve

Nun müssen wir die Qualität der Optimierung bewerten. Ich bin der Meinung, dass das Hauptkriterium die Arbeit des Expert Advisors außerhalb des Optimierungszeitraums ist. Um dies zu prüfen, führen Sie einen einzelnen Test innerhalb des Zeitraums 2010.01.01 - 2011.06.14 durch.

Vergleichen Sie zwei Ergebnisse (mit fast identischem resultierendem Gewinn) aus dem Satz der optimalen Parameter – das beste Ergebnis mit einem Ergebnis aus dem Mittelfeld. Die Ergebnisse außerhalb des Optimierungszeitraums sind durch die rote Linie abgetrennt:

Bestes Optimierungsergebnis

Abb. 11. Bestes Optimierungsergebnis

Im Allgemeinen hat sich das Verhalten der Kurve nicht verschlechtert. Die Rentabilität ist leicht von 1,60 auf 1,56 gesunken.

Mittleres Testergebnis

Abb. 12. Mittleres Testergebnis

Der Expert Advisor ist außerhalb des Optimierungszeitraums nicht rentabel. Die Rentabilität ist stark von 2,17 auf 1,75 gesunken.

Somit können wir schlussfolgern, dass die Annahme der Korrelation der Bilanzkurve mit der Dauer der Arbeit der optimierten Parameter eine Existenzberechtigung hat. Den Fall, dass ein akzeptables Ergebnis der Nutzung dieses Kriteriums für einen Expert Advisor nicht erreichbar ist, können wir natürlich nicht ausschließen. In diesem Fall müssen wir einige zusätzliche Analysen und Experimente durchführen.

Wahrscheinlich müssen wir für dieses Kriteriums den größten möglichen (vernünftigen) Zeitraum verwenden. Der Expert Advisor für die Überprüfung dieses Kriteriums befindet sich in der an diesen Beitrag angehängten Datei FanExpertBalance.mq5.



9. Erstellen einer Klasse eines benutzerdefinierten Optimierungskriteriums auf Basis des Koeffizienten des sicheren Handelssystems (CSTS)

Wie im Artikel "Be in-Phase" beschrieben, wird der Koeffizient des sicheren Handelssystems (CSTS) mithilfe der folgenden Formel berechnet:

CSTS = Avg.Win / Avg.Loss ((110% - %Win) / (%Win-10%) + 1)

wobei:

Wenn der CSTS-Wert weniger als 1 ist, befindet sich das Handelssystem in einer Zone mit hohem Handelsrisiko. Noch kleinere Werte deuten auf eine Zone mit nicht rentablem Handel hin. Je höher der Wert des CSTS ist, desto besser passt das Handelssystem zum Markt und desto rentabler ist es.

Alle statistischen Werte, die für die Berechnung des CSTS benötigt werden, werden nach jedem Testdurchlauf im Strategietester berechnet. Es muss nur noch die von TCustomCriterion vererbte Klasse TTSSFCriterion erstellt und die Methode GetCriterion() darin implementiert werden. Die Implementierung dieser Methode im Code sieht so aus:

double  TTSSFCriterion::GetCriterion()
{
  double  avg_win = TesterStatistics(STAT_GROSS_PROFIT) / TesterStatistics(STAT_PROFIT_TRADES);
  double  avg_loss = -TesterStatistics(STAT_GROSS_LOSS) / TesterStatistics(STAT_LOSS_TRADES);
  double  win_perc = 100.0 * TesterStatistics(STAT_PROFIT_TRADES) / TesterStatistics(STAT_TRADES);

//  Calculated safe ratio for this percentage of profitable deals:
  double  teor = (110.0 - win_perc) / (win_perc - 10.0) + 1.0;

//  Calculate real ratio:
  double  real = avg_win / avg_loss;

//  CSTS:
  double  tssf = real / teor;

  return(tssf);
}

Ich vermute, dass kurze Zeiträume für dieses Optimierungskriterium geeignet sind. Um unnötige Anpassungen zu vermeiden, sollten wir allerdings Ergebnisse aus der Mitte der Optimierungsergebnisse nehmen.

Ich gebe den Lesern nun die Gelegenheit, selbst eine Optimierung durchzuführen. Der Expert Advisor für die Überprüfung dieses Kriteriums befindet sich in der an diesen Beitrag angehängten Datei FanExpertTSSF.mq5.



Fazit

Sie müssen zugeben, dass eine so einfache Lösung für die Umsetzung der Möglichkeit, benutzerdefinierte Optimierungskriterien zu erstellen (mithilfe einer einzelnen ganzzahligen Kennziffer) im Vergleich mit anderen Varianten fast perfekt ist. Sie ermöglicht es, die Messlatte für die Entwicklung robuster Handelssysteme höher zu legen. Dank der Cloud-Technologie werden die durchgeführten Optimierungen deutlich weniger eingeschränkt.

Weitere Entwicklungsmöglichkeiten sind möglicherweise mit mathematisch und statistisch begründeten Kriterien verbunden, die in anderen Informationsquellen beschrieben werden. Wir verfügen über ein Werkzeug dafür.