English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
MQL5 Assistent: Wie man ein Risiko- und Geldverwaltungsmodul erzeugt

MQL5 Assistent: Wie man ein Risiko- und Geldverwaltungsmodul erzeugt

MetaTrader 5Handelssysteme | 14 März 2016, 15:13
1 262 0
MetaQuotes
MetaQuotes

Einleitung

MetaTrader 5 besitzt ein leistungsstarkes Tool, mit dem Sie schnell verschiedene Handelskonzepte überprüfen können: nämlich die Erzeugung eines Expert Advisors mit Hilfe des MQL5 Assistenten auf Grundlage bereits vorhandener Handelsstrategien.

Ein mit Hilfe des MQL5 Assistenten erzeugter Expert Advisor beruht auf vier Säulen - den vier Basisklassen:

Abb. 1 Struktur der CExpert Basisklasse

Abb. 1 Struktur der CExpert Basisklasse

  1. Die CExpert Klasse (oder ihre Unterklasse) ist der "primäre" Motor des Expert Advisors. Eine Instanz von CExpert enthält eine Kopie jeder Klasse: CExpertSignal, CExpertMoney und CExpertTrailing (oder ihre Unterklassen):
  2. CExpertSignal ist die Grundlage des Handelssignale-Generator. Eine Instanz der von der CExpertSignal abgeleiteten Klasse, die in CExpert mit vorhanden ist, liefert dem Expert Advisor, auf Grundlage des eingebauten Algorithmus, Informationen über die Möglichkeit in den Markt einzusteigen, die Einstiegslevels und Platzierung von schützenden Order Der Expert Advisor entscheidet dann, ob er in den Markt einsteigt. Der Beitrag "MQL5 Assistent: Wie man ein Modul mit Handelssignalen erzeugt" erklärt Ihnen die CExpertSignal Klasse und ihren Einsatz in allen Einzelheiten.
  3. Die CExpertMoney Klasse ist die Basis des Risiko- und Geldverwaltungsmechanismus. Eine Instanz der von der CExpertMoney abgeleiteten Klasse, die in CExpert mit vorhanden ist, liefert dem Expert Advisor, auf Grundlage des eingebauten Algorithmus, Informationen über mögliche Volumen zur Eröffnung von Positions and der Platzierung von pending Orders. Der Expert Advisor trifft dann eine Entscheidung bzgl. des Volumens.
  4. Die CExpertTrailing Klasse ist die Grundlage des Mechanismus zur Unterstützung offener Positionen. Eine Instanz der von der CExpertTrailing abgeleiteten Klasse, die in CExpert mit vorhanden ist, liefert dem Expert Advisor, auf Grundlage des eingebauten Algorithmus, Informationen über die Möglichkeit, schützende Orders der Position zu verändern. Der Expert Advisor trifft dann eine Entscheidung bzgl. der Veränderung von Orders. Weitere Einzelheiten über die CExpertTrailing Klasse und ihren Einsatz werden in einem extra Artikel erklärt.

Zusätzlich dazu sind die Mitglieder der CExpert Klasse alles Instanzen der folgenden Klassen:

  • CExpertTrade (für den Handel)
  • CIndikators (zur Kontrolle der Indikatoren und der Zeitreihen, die an der Arbeit des EA beteiligt sind).
  • CSymbolInfo (zum Erhalt von Informationen über das Instrument)
  • CAccountInfo (zum Erhalt von Informationen über den Status des Handels-Accounts)
  • CPositionInfo (zum Erhalt von Informationen über Positions)
  • COrderInfo (zum Erhalt von Informationen über pending Orders)

Im Folgenden bezeichnet daher der Begriff "Expert" eine Instanz der CExpert Klasse oder ihrer Unterklassen.

Weitere Einzelheiten zur CExpert Klasse und ihren Einsatz werden in einem extra Artikel erklärt.


1. CExpertMoney Basisklasse

Wie oben bereits erwähnt, ist die CExpertMoney Klasse die Grundlage des Mechanismus zur Geld- und Risikoverwaltung. Zur Kommunikation mit der "externen" Welt verfügt die CExpertMoney Klasse über eine Reihe an public virtuellen Methoden:

Initialisierung

 Beschreibung

virtuelle Init

Initialisierung der Klasseninstanz ermöglicht die Synchronisierung der Moduldaten mit den EA-Daten

Prozent

Einrichtung des Werts des "Prozent an Risiko"-Parameters

virtuelle ValidationSettings

Bestätigung der eingerichteten Parameter

virtuelle InitIndicators

Erzeugung und Initialisierung aller Indikatoren und Zeitreihen, die für die Abläufe des Risiko- und Geldverwaltungsmechanismus notwendig sind

Methoden zur Prüfung der Notwendigkeit, eine Position zu eröffnen/umkehren/schließen

 

virtuelle CheckOpenLong

Festlegung des Volumens zur Eröffnung einer Long Position

virtuellel CheckOpenShort

Festlegung des Volumens zur Eröffnung einer Long Position

virtuellel CheckReverse

Festlegung des Volumens zur Umkehr einer Position

virtuelle CheckClose

Festlegung der Notwendigkeit eine Position zu schließen

Beschreibung der Methoden


1.1 Initialisierungsmethoden

1.1.1 Init

Die Init() Methode wird direkt nach dem die einem Expert die Klasseninstanz hinzugefügt wurde, automatisch aufgerufen. Eine Aufhebung dieser Methode ist nicht nötig.

virtual bool Init(CSymbolInfo* symbol, ENUM_TIMEFRAMES period, double adjusted_point);

1.1.2 Prozent

Die Percent() Methode wird zur Konfiguration der entsprechenden Parameter aufgerufen. Ihr Wert kann von 0,0 bis einschl. 100,0 reichen. Die Standardeinstellung ist 100,0. Eine Aufhebung dieser Methode ist nicht nötig.

void Percent(double percent);

1.1.3 Validierungseinstellungen

Die ValidationSettings() Methode wird direkt vom Experten aufgerufen, wenn alle Parameter eingerichtet sind Sollte es noch zusätzliche Einrichtungs-Parameter geben, muss diese Methode aufgehoben werden.

virtual bool ValidationSettings();

Wenn alle Optionen gültig (also einsetzbar) sind, muss die aufgehobene Methode 'true' liefern. Ist mind. einer der Parameter nicht korrekt, dann muss sie 'false' liefern, d.h. eine weitere Arbeit ist nicht möglich. Die aufgehobene Methode muss die Basisklasse mit der Prüfung des Ergebnisses aufrufen.

Die CExpertMoney Basisklasse besitzt den Prozent-Parameter, sodass die Basisklassen-Methode entsprechend, nachdem sie den Parameter geprüft und bestätigt hat, 'true' liefert, wenn sich sein wert innerhalb des zulässigen Bereichs befindet. Ansonsten liefert sie 'false'.

1.1.4 InitIndikatoren

Die InitIndicators() Methode implementiert die Erzeugung und Initialisierung aller notwendigen Indikatoren und Zeitreihen. Sie wird vom Expert aufgerufen, nachdem alle Parameter eingerichtet und ihre Exaktheit erfolgreich bestätigt worden ist. Diese Methode sollte aufgehoben werden, wenn der Mechanismus zur Risiko- und Geldverwaltung mind. einen Indikator oder Zeitreihen verwendet.

virtual bool InitIndicators(CIndicators* indicators);

Indikatoren und/oder Zeitreihen sollten via der entsprechenden Klassen der Standard Library verwendet werden. Der Indikator-Sammlung eines Expert sollten Zeiger aller Indikatoren und/oder Zeitreihen hinzugefügt werden (ein Zeiger an den er als ein Parameter übertragen wird).

Die aufgehobene Methode muss 'true' liefern, wenn alle Handlungen bei den Indikatoren und/oder Zeitreihen erfolgreich waren (d.h. es kann mit ihnen gearbeitet werden). Sobald mind. eine Handlung bei den Indikatoren und/oder Zeitreihen gescheitert ist, muss die Methode 'false' liefern (d.h. es kann nicht weiter gearbeitet werden).

Die CExpertMoney Basisklasse verwendet keine Indikatoren oder Zeitreihen, daher liefert diese Basisklassenmethode immer 'true' und führt jedoch dabei keinerlei Handlung aus.

1.2 Methoden zur Bestimmung des Volumens einer Position

1.2.1 CheckOpenLong

Die CheckOpenLong() Methode berechnet das Volumen zur Eröffnung einer Long Position. Sie wird von einem Expert zur Festlegung des Volumens für die Eröffnung einer Long Position aufgerufen. Diese Methode muss aufgehoben werden, wenn Sie das Eröffnungsvolumen für eine Long Position mit Hilfe des Algorithmus berechnen wollen, der sich vom dem in der Basisklasse implementierten, unterscheidet.

\virtual double CheckOpenLong(double price, double sl);

Die Methode muss den Algorithmus zur Berechnung des Volumens für die Eröffnung der Long Position implementieren. Die Methode muss danach das berechnete Volumen liefern.

Die CExpertMoney Basisklasse besitzt keinen eingebauten Algorithmus zur Berechnung des Volumens für die Eröffnung von Long Positions. Die Basisklasse-Methode muss stets das zulässige Mindestvolumen für das Finanzinstrument liefern.

1.2.2 CheckOpenShort

Die CheckOpenShort() Methode berechnet das Volumen zur Eröffnung einer Short Position. Sie wird von einem Expert zur Festlegung des Volumens für die Eröffnung einer Short Position aufgerufen. Diese Methode muss aufgehoben werden, wenn Sie das Eröffnungsvolumen für eine Short Position mit Hilfe des Algorithmus berechnen wollen, der sich vom dem in der Basisklasse implementierten, unterscheidet. 

virtual double CheckOpenShort(double price, double sl);

Die Methode muss den Algorithmus zur Berechnung des Volumens für die Eröffnung der Short Position implementieren. Die Methode muss danach das berechnete Volumen liefern.

Die CExpertMoney Basisklasse besitzt keinen eingebauten Algorithmus zur Berechnung des Volumens für die Eröffnung von Short Positions. Die Basisklasse-Methode muss stets das zulässige Mindestvolumen für das Finanzinstrument liefern.

1.2.3 CheckReverse

Die CheckReverse() Methode berechnet das Volumen zur Umkehr einer Position. Sie wird von einem Expert zur Festlegung des Volumens zur Umkehr einer Position aufgerufen. Diese Methode muss aufgehoben werden, wenn Sie das Umkehrvolumen für eine Position mit Hilfe des Algorithmus berechnen wollen, der sich vom dem in der Basisklasse implementierten, unterscheidet (z.B. Umkehr mit einem doppelten Volumen). 

virtual double CheckReverse(CPositionInfo* position, double sl);

Die Methode muss den Algorithmus zur Berechnung des Volumens zur Umkehr einer Position implementieren; diesbezügliche Information erhält man mittels des Position-Zeigers. Die Methode muss danach das berechnete Volumen zur Umkehr der Position liefern.

Die CExpertMoney Basisklasse besitzt den folgenden Algorithmus zur Berechnung des Volumens zur Umkehr einer Position - die Umkehr einer Position dergestalt, dass das Ergebnis eine gegenteilige Position mit dem kleinstmöglichen Volumen ist.

1.2.4 CheckClose

Die CheckClose() Methode prüft, ob es notwendig ist, eine Position zu schießen (in Bezug auf Geld- und Risikoverwaltung). Sie wird von einem Expert zur Feststellung, ob eine Position geschlossen werden muss, aufgerufen. Diese Methode muss aufgehoben werden, wenn Sie eine Position mit Hilfe des Algorithmus, der sich vom dem in der Basisklasse implementierten, unterscheidet, schließen wollen (z.B. teilweises Schließen). 

virtual double CheckClose(CPositionInfo* position);

Die Methode muss den Algorithmus zur Feststellung der Notwendigkeit, eine Position zu schließen, implementieren; diesbezügliche Information erhält man mittels des Position-Zeigers. Die Methode muss danach das berechnete Volumen für das Schließen der Position liefern.

Die CExpertMoney Basisklasse besitzt den folgenden Algorithmus zur Feststellung, ob eine Position geschlossen werden muss: die Basisklassen-Methode bietet an, die Position komplett zu schließen, wenn der aktuelle Verlust bei einer Position größer ist als der angegebene Prozentwert des Depots.

2. Einen Mechanismus zur Geld- und Risikoverwaltung schaffen

Nachdem wir uns gerade die Struktur der CExpertMoney Basisklasse angesehen haben, können Sie bereits mit der Erzeugung Ihres eigenen Mechanismus zur Geld- und Risikoverwaltung beginnen. Dieser Mechanismus zur Geld- und Risikoverwaltung wird im Folgenden kurz "Geldverwalter" genannt.

Wie bereits ausgeführt, ist die CExpertMoney Klasse eine Reihe von public virtuellen "Hilfsseilen" - Methoden mit deren Hilfe der Expert die Meinung des Geldverwalters bzgl. des Volumens für einen Einstieg in den Markt in eine Richtung oder die andere, erfährt.

Daher ist unser primäres Ziel die Erzeugung unserer eigenen Klasse des Geldverwalters, die wir von der CExpertMoney Klasse ableiten und die die passende virtuellen Methoden aufhebt und die erforderlichen Algorithmen implementiert.

Unser zweites Ziel ist (und das ist nicht weniger wichtig), unsere Klasse für den MQL5 Assistenten "sichtbar" zu machen. Doch gehen wir der Reihe nach vor.

2.1 Die Kasse des Handelssignale-Generators erzeugen

Also los.

Zuerst erzeugen wir (z.B. in dem wir denselben MQL5 Assistenten verwenden) eine einzuschließende Datei mit der Erweiterung .mqh.

Im Dateimenü wählen wir dazu "Erzeugen" aus (oder drücken Ctrl+N) und geben die Erzeugung einer eingeschlossenen Datei an

Abb. 2 Erzeugen einer einzuschließenden Datei mit Hilfe des MQL5 Assistenten

Abb. 2 Erzeugen einer einzuschließenden Datei mit Hilfe des MQL5 Assistenten

An dieser Stelle möchte ich darauf hinweisen, dass diese Datei, damit sie vom MQL5 Assistenten später als Geldverwalter "entdeckt" werden kann, im Include\Expert -Ordner erzeugt werden sollte.

Um die Standard Library nicht zuzumüllen, sollten Sie Ihren eigenen Include\Expert\Money\MyMoneys-Ordner anlegen, in dem wir dann die SampleMoney.mqh Datei anlegen und die Parameter im MQL5 Assistenten anlegen:

Abb. 3 Den Standort der einzuschließenden Datei einrichten

Abb. 3 Den Standort der einzuschließenden Datei einrichten

Als Ergebnis der Arbeit des MQL5 Assistenten erhalten wir dann das folgenden Muster:

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
// #define MacrosHello   "Hello, world!"
// #define MacrosYear    2010
//+------------------------------------------------------------------+
//| DLL imports                                                      |
//+------------------------------------------------------------------+
// #import "user32.dll"
//   int      SendMessageA(int hWnd,int Msg,int wParam,int lParam);
// #import "my_expert.dll"
//   int      ExpertRecalculate(int wParam,int lParam);
// #import
//+------------------------------------------------------------------+
//| EX5 imports                                                      |
//+------------------------------------------------------------------+
// #import "stdlib.ex5"
//   string ErrorDescription(int error_code);
// #import
//+------------------------------------------------------------------+

Was nun folgt ist nur "manuelle" Arbeit. Die unnötigen Teile entfernen und alles was benötigt wird, hinzufügen - die einzuschließende Datei ExpertMoney.mqh der Standard Library mit einer leeren Klassenbeschreibung.

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management.                    |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
  };
//+------------------------------------------------------------------+

Als nächstes müssen wir die Algorithmen auswählen.

Wir verwenden folgenden Algorithmus als Basis für unseren Geldverwalter: Unter "normalen" Bedingungen wird vorgeschlagen, ein fixes, vorab festgelegtes Abschlussvolumen zu verwenden. Doch wurde die vorige Position mit einem Verlust geschlossen, wird vorgeschlagen, eine Position mit einem doppelten Volumen zu eröffnen.

Dies sollte unsere Datei abbilden.

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management                     |
//|             doubling the volume after a loss deal.               |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
  };
//+------------------------------------------------------------------+

Legen Sie eine Liste der Einstellungen für unseren Geldverwalter fest. Tatsächlich wird es sie nicht geben. Alle Einstellungen sind in einem einzigen Parameter umfasst, der das Volumen einer Transaktion unter "normalen" Bedingungen festlegt.

Der Parameter wird in einem geschützten Datenmitglied der Klasse abgelegt. Zugriff auf den Parameter wird durch die entsprechende public Methode implementiert. Im Klassen-Constructor, wird der Parameter mittels eines Standardwerts initialisiert. Um die Parameter prüfen zu können, heben wir die virtuelle Methode ValidationSettings gemäß der Beschreibung der Basisklasse auf und

nehmen diese Veränderungen in unsere Datei auf:

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management                     |
//|             doubling the volume after a loss deal.               |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
protected:
   //--- setup parameters
   double            m_lots;   // deal volume for "normal" conditions

public:
                     CSampleMoney();
   //--- methods to set the parameters
   void              Lots(double lots) { m_lots=lots; }
  };
//+------------------------------------------------------------------+
//| Constructor CSampleMoney.                                        |
//| INPUT:  no.                                                      |
//| OUTPUT: no.                                                      |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
void CSampleMoney::CSampleMoney()
  {
//--- setting the default values
   m_lots=0.1;
  }
//+------------------------------------------------------------------+

Sehen wir uns nun separat an, wie man die ValidationSettings() Methode implementiert. Der Punkt hierbei ist, dass die Basisklasse bereits einen Konfigurationsparameter besitzt, der ebenfalls verifiziert werden muss.

Wir sollten daher in der aufgehobenen ValidationSettings() Methode, ValidationSettings() der Basisklasse mit der Prüfung der Ergebnisse der Ausführung aufrufen.

Implementierung der ValidationSettings() Methode:

//+------------------------------------------------------------------+
//| Validation of the setup parameters.                              |
//| INPUT:  no.                                                      |
//| OUTPUT: true if the settings are correct, otherwise false.       |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSampleMoney::ValidationSettings()
  {
//--- Call the base class method
   if(!CExpertMoney::ValidationSettings()) return(false);
//--- Validation of parameters
   if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax())
     {
      printf(__FUNCTION__+": the deal volume must be in the range %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax());
      return(false);
     }
   if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10)
     {
      printf(__FUNCTION__+": the volume of the deal must be multiple of %f",m_symbol.LotsStep());
      return(false);
     }
//--- Successful completion
   return(true);
  }

Die Einstellungen sind fertig, also können jetzt mit der Arbeit am Geldverwalter weitermachen. Wir brauchen eine Methode, die festlegt, ob der vorherige Abschluss Verluste gemacht hat und ggf. sein Volumen definiert. Dies wird in der Beschreibung der Klasse deklariert:

class CSampleMoney : public CExpertMoney
  {
protected:
   //--- Setup parameters
   double            m_lots;  // deal volume for "normal" conditions

public:
                    CSampleMoney();
   //--- Methods to set parameters
   void             Lots(double lots) { m_lots=lots; }
   //--- Methods to validate parameters
   virtual bool      ValidationSettings();

protected:
   double            CheckPrevLoss();
  };

Implementierung der Methode:

//+------------------------------------------------------------------+
//| Defines whether the prev. deal was losing.                       |
//| INPUT:  no.                                                      |
//| OUTPUT: volume of the prev. deal if it's losing, otherwise 0.0   |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckPrevLoss()
  {
   double lot=0.0;
//--- Request the history of deals and orders
   HistorySelect(0,TimeCurrent());
//--- variables
   int       deals=HistoryDealsTotal();  // Total number of deals in the history
   CDealInfo deal;
//--- Find the previous deal
   for(int i=deals-1;i>=0;i--)
     {
      if(!deal.SelectByIndex(i))
        {
         printf(__FUNCTION__+": Error of deal selection by index");
         break;
        }
      //--- Check the symbol
      if(deal.Symbol()!=m_symbol.Name()) continue;
      //--- Check the profit
      if(deal.Profit()<0.0) lot=deal.Volume();
      break;
     }
//--- Return the volume
   return(lot);
  }

Werfen wir abermals einen Blick auf unsere Algorithmen, diesmal noch genauer (wir sind ja schon ziemlich detailliert dabei).

Ohne zu viele Feinheiten zu erwähnen, stellen wir dennoch fest, dass unser Geldverwalter vorschlägt, das Volumen des Abschlusses bei Eintreten eines Verlusts beim vorherigen Abschluss zu erhöhen. Hat der vorherige Abschluss keinen Verlust gemacht, bieten wir die Eröffnung einer Position mit einem fixen Volumen an, das von einem bestimmten Parameter festgelegt wird.

Dazu heben wir die virtuellen CheckOpenLong und CheckOpenShort Methoden auf, und füllen sie mit der entsprechenden Funktionalität.

Beschreibung der Klasse:

//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management                     |
//|             doubling the volume after a loss deal.               |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
protected:
   //--- Setup parameters
   double            m_lots;  // Deal volume for "normal" conditions

public:
                    CSampleMoney();
   //--- Methods to set the parameters
   void             Lots(double lots) { m_lots=lots; }
   //--- Methods to validate the parameters
   virtual bool      ValidationSettings();
   //--- Methods to define the volume
   virtual double    CheckOpenLong(double price,double sl);
   virtual double    CheckOpenShort(double price,double sl);

protected:
   double            CheckPrevLoss();
  };

Die Implementierung von CheckOpenLong und CheckOpenShort ist eigentlich identisch. Beide Methoden legen die Notwendigkeit fest, das Volumen zu erhöhen, indem sie die zuvor implementierte CheckPrevLoss Methode aufrufen.

Als nächstes müssen wir berücksichtigen, dass wir das Handelsvolumen nicht unbegrenzt erhöhen können. Das Volumen einer Position unterliegt zwei Beschränkungen:

  1. Das Maximalvolumen für einen Abschluss für dieses Symbol, das in den Servereinstellungen (SYMBOL_VOLUME_MAX) festgelegt wurde.
  2. Verfügbarkeit des benötigten Betrags an freiem Geld im Depot.

Implementierung der CheckOpenLong and CheckOpenShort Methoden:

//+------------------------------------------------------------------+
//| Defining the volume to open a long position.                     |
//| INPUT:  no.                                                      |
//| OUTPUT: lot-if successful, 0.0 otherwise.                        |
//| REMARK: not.                                                     |
//+------------------------------------------------------------------+
double CSampleMoney::CheckOpenLong(double price,double sl)
  {
   if(m_symbol==NULL) return(0.0);
//--- Select the lot size
   double lot=2*CheckPrevLoss();
   if(lot==0.0) lot=m_lots;
//--- Check the limits
   double maxvol=m_symbol.LotsMax();
   if(lot>maxvol) lot=maxvol;
//--- Check the margin requirements
   if(price==0.0) price=m_symbol.Ask();
   maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent);
   if(lot>maxvol) lot=maxvol;
//--- Return the trade volume
   return(lot);
  }
//+------------------------------------------------------------------+
//| Defining the volume to open a short position.                    |
//| INPUT:  no.                                                      |
//| OUTPUT: lot-if successful, 0.0 otherwise.                        |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckOpenShort(double price,double sl)
  {
   if(m_symbol==NULL) return(0.0);
//--- Select the lot size
   double lot=2*CheckPrevLoss();
   if(lot==0.0) lot=m_lots;
//--- Check the limits
   double maxvol=m_symbol.LotsMax();
   if(lot>maxvol) lot=maxvol;
//--- Check the margin requirements
   if(price==0.0) price=m_symbol.Bid();
   maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent);
   if(lot>maxvol) lot=maxvol;
//--- Return the trade volume
   return(lot);
  }

So, das erste Problem wäre gelöst. Der oben stehende Code ist ein "Quellcode" der Geldverwalter-Klasse, die unsere Hauptaufgabe erfüllt.

2.2 Eine Beschreibung der generierten Geldverwalter-Klasse für den MQL5 Assistent erzeugen

Wenden wir uns nun unserem zweiten Problem zu. Unser Geldverwalter sollte vom Generator der Handelsstrategien des MQL5 Assistenten auch "erkannt" werden.

Die erste dazu notwendige Bedingung haben wir schon geschaffen: wir haben die Datei, in der er vom MQL5 Assistenten "gefunden" werden kann, platziert. Doch das genügt noch nicht. Der MQL5 Assistent muss die Datei nicht nur "finden", er muss sie auch als solche "erkennen". Dazu müssen wir dem ursprünglichen Text den Klassen-Descriptor für den MQL5 Assistenten hinzufügen.

Einen Klassen-Descriptor ist ein Block an Kommentaren, der gemäß bestimmter Regeln zusammengesetzt ist.

Und die sehen wir uns jetzt mal an.

1. Der Kommentarblock sollte mit den folgenden Zeilen beginnen:

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |

2. Die nächste Zeile ist ein Text-Descriptor (das was wir im MQL5 Assistenten dann sehen, wenn wir das Signal auswählen) im Format "//| Title=<Text> |". Ist der Text zu lang für einen Zeile, dann fügen Sie noch eine Zeile (aber nicht mehr!) hinzu. 

In unserem Fall ergibt das dann:

//| Title=Trade with a doubling of lot after a loss                  |

3. Danach folgt einen Zeile mit dem spezifizierten Klassentyp im Format "//| Type=<Type> |". Das <Typ> Feld muss den Geldwert besitzen (zusätzlich zu Geldverwaltern kennt der MQL5 Assistent auch noch andere Typen an Klassen).

Man schreibt:

//| Type=Money                                                       |

4. Die folgende Zeile im Format "//| Name=<Name> |" ist der Kurzname des Signals (den der MQL5 Assistent zur Generierung der Namen der globalen Variablen des Experts verwendet).

Wir erhalten folgendes:

//| Name=Sample                                                      |

5. Der Name einer Klasse ist ein wichtiges Element der Beschreibung. In der Zeile im Format "//| Class=<ClassNameа> |", muss der <ClassName> Parameter mit dem Namen unserer Klasse übereinstimmen:

//| Class=CSampleMoney                                               |

6. Wir füllen diese Zeile nicht, doch muss sie trotzdem da sein (sie stellt die Verbindung zum Bereich Sprachreferenz dar):

//| Page=                                                            |

7. Des weiteren gibt es die Beschreibungen der Parameter für die Einrichtung des Signals, die

aus einer Anzahl Reihen bestehen (ihre Anzahl = der Anzahl der Parameter).

Das Format jeder Zeile lautet: "//| Parameter=<NameOfMethode>,<TypeOfParameter>,<DefaultValue> |".

Und das ist unser Parameter-Set:

//| Parameter=Lots,double,0.1                                        |
//| Parameter=Percent,double,100.0                                   |

8. Der Kommentarblock sollte mit den folgenden Zeilen enden

//+------------------------------------------------------------------+
// wizard description end

2-7. Die Elemente 2-7 müssen wir noch weiter erklären. Gewisse Abschnitte des Klassen-Descriptors enthalten Schlüsselworte (Titel, Art, Name, Klasse, Seite, Parameter). Leider kann unser MQL5 Assistent nicht alle möglichen Zeichenkombinationen als Teil der Klassenbeschreibung interpretieren.

Um also unnötige Fehler zu vermeiden, bitte folgendermaßen schreiben:
[Slash][Slash][VerticalLine][Space]<Keyword>[EqualitySign]<Description>;

<Description> darf beim Schlüsselwort 'Titel' Leerräume haben. Absätze 1 und 8 sollten "genauso" kopiert werden.

Der Descriptor der Klasse (erste Zeile) darf in der Datei nicht später als in ihrer 20. Zeile stehen.

Ergänzen wir den Quellcode um den Descriptor.

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
#include <Trade\DealInfo.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Trading with lot doubling after a loss                     |
//| Type=Money                                                       |
//| Name=Sample                                                      |
//| Class=CSampleMoney                                               |
//| Page=                                                            |
//| Parameter=Lots,double,0.1                                        |
//| Parameter=Percent,double,100.0                                   |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management                     |
//|             doubling the volume after a loss deal.               |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
protected:
   //--- Setup parameters
   double            m_lots;  // Deal volume for "normal" conditions

public:
                     CSampleMoney();
   //--- Methods to set the parameters
   void              Lots(double lots) { m_lots=lots; }
   //--- Methods to validate the parameters
   virtual bool      ValidationSettings();
   //--- Methods to define the volume
   virtual double    CheckOpenLong(double price,double sl);
   virtual double    CheckOpenShort(double price,double sl);

protected:
   double            CheckPrevLoss();
  };
//+------------------------------------------------------------------+
//| Constructor CSampleMoney.                                        |
//| INPUT:  no.                                                      |
//| OUTPUT: no.                                                      |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
void CSampleMoney::CSampleMoney()
  {
//--- Setting default values
   m_lots=0.1;
  }
//+------------------------------------------------------------------+
//| Validation of the setup parameters.                              |
//| INPUT:  no.                                                      |
//| OUTPUT: true if the settings are correct, otherwise false.       |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSampleMoney::ValidationSettings()
  {
//--- Call the base class method
   if(!CExpertMoney::ValidationSettings()) return(false);
//--- Validating the parameters
   if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax())
     {
      printf(__FUNCTION__+": The deal volume must be in the range %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax());
      return(false);
     }
   if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10)
     {
      printf(__FUNCTION__+": The deal volume must be multiple of  %f",m_symbol.LotsStep());
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Defining the volume to open a long position.                     |
//| INPUT:  no.                                                      |
//| OUTPUT: lot-if successful, 0.0 otherwise.                        |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckOpenLong(double price,double sl)
  {
   if(m_symbol==NULL) return(0.0);
//--- Select the lot size
   double lot=2*CheckPrevLoss();
   if(lot==0.0) lot=m_lots;
//--- Check the limits
   double maxvol=m_symbol.LotsMax();
   if(lot>maxvol) lot=maxvol;
//--- Check the margin requirements
   if(price==0.0) price=m_symbol.Ask();
   maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent);
   if(lot>maxvol) lot=maxvol;
//--- Return the trade volume
   return(lot);
  }
//+------------------------------------------------------------------+
//|Defining the volume to open a short position.                     |
//| INPUT:  no.                                                      |
//| OUTPUT: lot-if successful, 0.0 otherwise.                        |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckOpenShort(double price,double sl)
  {
   if(m_symbol==NULL) return(0.0);
//--- Select the lot size
   double lot=2*CheckPrevLoss();
   if(lot==0.0) lot=m_lots;
//--- Check the limits
   double maxvol=m_symbol.LotsMax();
   if(lot>maxvol) lot=maxvol;
//--- Check the margin requirements
   if(price==0.0) price=m_symbol.Bid();
   maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent);
   if(lot>maxvol) lot=maxvol;
//--- Return the trade volume
   return(lot);
  }
//+------------------------------------------------------------------+
//| Defines whether the prev. deal was losing.                       |
//| INPUT:  no.                                                      |
//| OUTPUT: Volume of the prev. deal if it's losing, otherwise 0.0   |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckPrevLoss()
  {
   double lot=0.0;
//--- Request the history of deals and orders
   HistorySelect(0,TimeCurrent());
//--- variables
   int       deals=HistoryDealsTotal();  // Total number of deals in the history
   CDealInfo deal;
//--- Find the previous deal
   for(int i=deals-1;i>=0;i--)
     {
      if(!deal.SelectByIndex(i))
        {
         printf(__FUNCTION__+": Error of deal selection by index");
         break;
        }
      //--- Check the symbol
      if(deal.Symbol()!=m_symbol.Name()) continue;
      //---Check the profit
      if(deal.Profit()<0.0) lot=deal.Volume();
      break;
     }
//--- Return the volume
   return(lot);
  }
//+------------------------------------------------------------------+

Und das ist alles. Der Geldverwalter ist nun einsatzbereit.

Damit der Handelsstrategien-Generator des MQL5 Assistenten unseren Geldverwalter auch verwenden kann, sollte der MetaEditor neu gestartet werden (der MQL5 Assistent scannt den Ordner Include\Expert nur beim Booten).

Nach einem Neustart des MetaEditor, kann das generierte Geldverwalter Modul im MQL5 Assistenten eingesetzt werden:

Abb. 5 Der im MQL5 Assistenten generierte Geldverwalter

Abb. 5 Der im MQL5 Assistenten generierte Geldverwalter

Die im Abschnitt der Beschreibung der Geldverwalter Parameter festgelegten Eingabeparameter können nun verwendet werden:

Abb. 6 Eingabeparameter des im MQL5 Assistenten generierten Geldverwalters

Abb. 6 Eingabeparameter des im MQL5 Assistenten generierten Geldverwalters

Die besten Werte der Eingabeparameter der implementierten Handelsstrategie erhält man mit Hilfe des Strategie-Testers des MetaTrader 5 Terminals.

Abb. 7 zeigt die Testergebnisse des Expert Advisors, der in Übereinstimmung mit diesem Geldverwaltung-System handelt (EURUSD H1, Testzeitraum: 01.01.2010-05.01.2011).

Abb. 7 Ergebnisse des Tests vor der History der Strategie mit dem Geldverwaltungsmodul mit einer Verdoppelung nach einem Loss

Abb. 7 Ergebnisse des Tests vor der History der Strategie mit dem Geldverwaltungsmodul mit einer Verdoppelung nach einem Loss

Bei der Erzeugung eines Expert Advisors, haben wir das im Beitrag "MQL5 Assistent: Wie man ein Handelssignale-Modul erzeugt" implementierte Handelssignale-Modul verwendet . Die Parameter des Expert Advisors: (ZeitraumMA=12, WechselMA=0, MethodeMA=MODE_EMA, AngewandterMA=PRICE_CLOSE, Limit=-70, StopLoss=145, TakeProfit=430, Ablauf=10, Posten=0.1, Prozent=100).

Fazit

Der Handelsstrategien-Generator des MQL5 Assistenten erleichtert das Testen von Handelskonzepten ganz enorm. Der Code des generierten Experten beruht auf den Handelsstrategie-Klassen der Standard Library, die zur Erzeugung bestimmter Implementierungen von Handelssignalklassen, Geld- und Risikoverwaltung und Support-Klassen für Positions verwendet werden. 

Dieser Beitrag beschreibt die Entwicklung eines individuell angepassten Risiko- und Geldverwaltung Moduls und seine Aktivierung im MQL5 Assistenten. Als Beispiel haben wir einen Geldverwaltung-Algorithmus betrachtet, in dem die Größe des Handelsvolumens durch die Ergebnisse des vorigen Abschlusses festgelegt wird. Die Struktur und das Format der Beschreibung der für diesen MQL5 Assistenten erzeugte Klasse wurden hier ebenfalls besprochen.

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

Beigefügte Dateien |
samplemoney.mqh (7.15 KB)
MQL5 Assistent: Erstellen eines Moduls zum Verfolgen offener Positionen MQL5 Assistent: Erstellen eines Moduls zum Verfolgen offener Positionen
Als Erzeuger von Handelsstrategien vereinfacht der MQL5 Wizard das Testen von Handelsideen enorm. In diesem Beitrag wird besprochen, wie Ihre eigene Klasse zum Verwalten offener Positionen durch die Verschiebung des Stop-Loss-Niveaus in einen verlustfreien Bereich, wenn sich der Preis in Richtung der Position bewegt, geschrieben und mit dem MQL5 Wizard verbunden werden kann, um Ihren Gewinn beim Handel vor Drawdowns zu schützen. Es wird auch auf die Struktur und das Format der Beschreibung der erstellten Klasse für den MQL5 Wizard eingegangen.
Elektronische Tabellen in MQL5 Elektronische Tabellen in MQL5
Dieser Beitrag beschreibt eine Klasse eines dynamischen zweidimensionalen Arrays, die in ihrer ersten Dimension Daten verschiedener Typen enthält. Diese Daten in Form einer Tabelle abzulegen, ist zur Lösung von vielen Problemen bei der Anordnung, Speicherung und der Arbeit mit gebundenen Informationen unterschiedlicher Arten sehr bequem. Der Quellcode der Klasse, die Funktionalität mit Tabellen arbeiten zu können, implementiert, ist an diesen Beitrag angehängt.
Die Umsetzung des Mehrwährungsmodus in MetaTrader 5 Die Umsetzung des Mehrwährungsmodus in MetaTrader 5
Man interessiert sich schon lange für Mehrwährungsanalysen und Mehrwährungshandel. Die Gelegenheit, ein vollwertiges Mehrwährungssystem umzusetzen, ergab sich erst mit der Veröffentlichung von MetaTrader 5 und der Programmiersprache MQL5. In diesem Beitrag erörtern wir eine Möglichkeit, alle eingehenden Ticks für mehrere Symbole zu analysieren und zu verarbeiten. Als Illustration betrachten wir einen Mehrwährungs-RSI-Indikator des USDx-Dollar-Index.
Der MQL5 Assistent: Wie man ein Modul an Handelssignalen erzeugt Der MQL5 Assistent: Wie man ein Modul an Handelssignalen erzeugt
Dieser Beitrag beschreibt, wie man seine eigene Klasse an Handelssignalen mit der Implementierung von Signalen am Schnittpunkt des Kurses und gleitenden Durchschnitts schreiben und sie in den Handelsstrategien-Generator des MQL5 Assistenten einschließen kann. Er erklärt auch die Struktur und das Format der Beschreibung der generierten Klassen für den MQL5 Assistenten.