Universeller Expert Advisor: Handelsmodi von Strategien (Teil 1)

Vasiliy Sokolov | 7 April, 2016

Gliederung

 

Einleitung

Im Laufe der Umsetzung eines Hanldesalgorithmus stellen sich verschiedene Aufgaben. Dazu gehören sowohl die Analyse der Marktumgebung und das Erhalten von Signalen zum Einstieg, als auch das Schließen einer vorhandenen Position. Des Weiteren zählen dazu die Kontrolle über die Korrektheit von Operationen des Expert Advisors sowie eine richtige Bearbeitung von Fehlern beim Handel. Schließlich ist auch ein einfacher und bequemer Zugang zu Marktdaten und eigenen Positionen des Expert Advisors von großer Bedeutung. Diese Aufgaben werden unmittelbar im Quellcode des Experten umgesetzt.

Von der anderen Seite muss man zwischen der technischen Seite des Handelsprozesses und der eigentlichen Idee unterscheiden, die im Expert Advisor umgesetzt wird. Mit dem objektorientierten Ansatz kann man diese zwei unterschiedlichen Aufgaben trennen und einer bestimmten für alle Strategien gemeinsamen Klasse delegieren, die manchmal auch als Trading-Engine bezeichnet wird.

Dieser Beitrag eröffnet eine Artikelserie, die die Arbeit einer solchen Engine beschreibt, die man "Universeller Experte" nennen kann. Der Name vereint Klassen-Sets, mit denen man Handelsalgorithmen auf eine einfache Weise durch die Aufzählung von Bedingungen für Einstieg und Ausstieg schreiben kann. Dabei braucht man den eigenen Experten nicht mit Daten oder der Handelslogik wie Iteration von Positionen versehen — all das erledigt die Trading-Engine.

Das Material ist sehr umfangreich, aus diesem Grund wurde er in vier Teile aufgeteilt. Gehen wir genauer darauf ein.

Teil 1. Handelsmodi einer Strategie. Darum geht es in diesem Beitrag. Der erste Teil handelt von einer originalen Konzeption der Verwaltung von Positionen auf Basis von Handelsmodi. Die Handelsmodi erlauben, die Logik des Experten schnell und einfach zu formulieren. Die Expert Advisors, die auf diese Weise geschrieben wurden, lassen sich einfach debuggen. Die Logik solcher Experten ist universell und immer gleich, was die Verwaltung dieser Strategien wesentlich erleichtert. Die in diesem Beitrag vorgestellten Ideen sind universell und brauchen keinen objektorientierten Code. Dies bedeutet, egal ob Sie den Set der vorgeschlagenen Bibliotheken nutzen werden oder nicht, kann dieser Artikel für Sie von Interesse sein.

Teil 2. Das Ereignis-Modell und der Prototyp einer Handelstrategie. In diesem Beitrag wird das originale Ereignis-Modell auf Basis einer zentralisierten Bearbeitung von Ereignissen beschrieben. Das bedeutet, dass alle Ereignisse an einer Stelle der Handelslogik "gesammelt" werden, die diese bearbeitet. Darüber hinaus gelten die Ereignisse für mehrere Währungen, d.h. wenn der Experte auf dem Währungspaar EURUSD gestartet wurde, kann man das Ereignis über einen neuen eingehenden Tick auf dem Symbol GBPUSD bekommen. Das Ereignis-Modell kann beim Schreiben der Experten hilfreich sein, die mit mehreren Symbolen handeln. Dieser Teil beschreibt die Basisklasse der Trading-Engine CStrategy und die CPositionMT5 Klasse, die eine Position im MetaTrader 5 darstellt.

Teil 3. Benutzerstrategien und Hilfsklassen. In dem Teil geht es um das Schreiben von Expert Advisors. In diesem Teil erfahren Sie, wie man mithilfe einer einfachen Aufzählung von Bedingungen für Einstieg und Ausstieg einen Experten erstellen kann. Darüber hinaus werden in diesem Teil verschiedene zusätzliche Algorithmen beschrieben, welche den Zugang zur Handelsinformation erheblich erleichtern.

Teil 4. Handel in einer Gruppe und Verwaltung eines Strategieportfolios. In diesem Teil geht es um spezielle Algorithmen, mit denen man mehrere Handelslogiken in ein Ausführungsmodul ex5 integrieren kann. Des Weiteren werden Mechanismen geschildert, mit denen man einen Set von Benutzerstrategien unter Verwendung einer XML-Datei bilden kann.

 

Methoden der Eröffnung einer neuen und der Verwaltung einer vorhandenen Position

Um den im Artikel beschriebenen Ansatz zu verstehen, versuchen wir ein klassisches Handelssystem zu beschreiben, welches auf zwei gleitenden Durchschnitten beruht. Der Erste mit einer kurzen Glättungs-Periode und der Zweite - mit einer langen Periode. Somit ist der gleitende Durchschnitt mit der größeren Periode langsamer im Vergleich zum gleitenden Durchschnitt mit der kleineren Periode der Mittelung. Die Handelsregeln sind einfach: wenn der schnelle gleitende Durchschnitt über dem langsamen liegt, befindet sich der Expert Advisor im Buy-Modus, und umgekehrt: wenn der schnelle gleitende Durchschnitt unter dem langsamen liegt, ist der EA im Sell-Modus. Um das oben Beschriebene zu veranschaulichen, nehmen wir den folgenden Chart, der unsere Strategie schematisch darstellt:

Abb. 1. Der Chart des Handelssystems auf zwei gleitenden Durchschnitten

Die rote Linie stellt den schnellen gleitenden Durchschnitt mit der Periode 50 dar. Die blaue Linie bezeichnet den langsamen gleitenden Durchschnitt mit der Periode 120. Im Moment, wo der eine gleitende Durchschnitt den anderen durchkreuzt (diese sind mit den blauen Punktlinien hervorgehoben) wendet sich die Position des Experten in die entgegengesetzte Richtung. Aus einem nicht algorithmischen Blickwinkel reicht diese Beschreibung, damit jeder Trader versteht, wie man nach dieser Strategie handelt. Wenn wir uns aber vorgenommen haben, einen Expert Advisor zu erstellen, der auf dieser Strategie beruht, reicht diese Beschreibung nicht aus.

Betrachten wir die Aktionen, die der Experte in dem Moment durchführen muss, wenn der schnelle gleitende Durchschnitt den langsamen von unten nach oben kreuzt:

  1. Wenn in diesem Moment eine offenen Short-Position im Expert Advisor vorhanden ist, muss diese geschlossen werden.
  2. Überprüfen, dass es keine früher eröffnete Long-Position gibt. Wenn keine Long-Position vorhanden ist - eine eröffnen, wenn es eine gibt - nichts unternehmen.

Wenn der schnelle gleitende Durchschnitt den langsamen von oben nach unten kreuzt, muss man umgekehrt vorgehen:

  1. Wenn es im Moment, in dem sich die gleitenden Durchschnitte kreuzen, eine offene Long-Position gibt, muss man diese schließen.
  2. Überprüfen, dass es keine früher eröffnete Short-Position gibt. Wenn keine Short-Position vorhanden ist — eine eröffnen, wenn es eine bereits gibt — nichts tun.

Für die Beschreibung des ganzen Handelsprozesses der Strategie haben wir insgesamt vier Aktionen. Zwei von ihnen beschreiben die Regeln der Eröffnung und der Verwaltung einer Long-Position. Die zwei Weiteren beschreiben die Regeln der Eröffnung und der Verwaltung einer Short-Position. Es kann den Eindruck erwecken, dass vier Handlungen viel zu viel für die Beschreibung eines so einen einfachen Handelsverfahrens sind. Die Momente des Einstiges in eine Long-Position stimmen tatsächlich mit den des Ausstiegs aus einer Short-Position überein. Wäre es denn nicht einfacher, diese Aktionen zu kombinieren oder mindestens in eine logische Aktion zu vereinen? Die Antwort lautet nein. Um nachzusehen, ob das tatsächlich zutrifft, muss man einfach die Bedingungen der anfänglichen Strategie ein bisschen ändern.

Jetzt wird unsere Strategie verschiedene Sets von Gleitenden Durchschnitten für Kauf und Verkauf nutzen. Eine Long-Position wird z.B. eröffnet, wenn der schnelle gleitende Durchschnitt mit der Periode 50 den langsamen mit der Periode 120 kreuzt. Eine Short-Position wird eröffnet, wenn der schnelle gleitende Durchschnitt mit der Periode 20 den langsamen gleitenden Durchschnitt mit der Periode 70 kreuzt. Laut den neuen Regeln stimmen die Kaufsignale mit den Verkaufssignalen nicht mehr überein. Die Signale werden zu verschiedenen Zeitpunkten in verschiedenen Marktsituationen entstehen.

Die vorgeschlagenen Regeln sind nicht bloß ausgedacht. Häufig werden gegengleiche Bedingungen für Einstieg und Ausstieg in Strategien verwendet: der Einstieg in eine Long-Position bedeutet den Ausstieg aus einer Short-Position und umgekehrt. Dies ist aber nicht immer der Fall, und wenn wir einen universellen Prototyp erstellen wollen, müssen wir dies berücksichtigen. Aus diesem Grund haben wir insgesamt vier Regeln.

Betrachten wir unsere Aktionen aus einer anderen Perspektive. Führen wir eine Tabelle an, in welcher horizontal der Tradetyp (Buy oder Sell) und vertikal — der Typ der Aktionen angegeben sind (Öffnen oder Schließen). Die Tabellenzellen enthalten einen konkreten Set von Aktionen:

Buy Sell
Eröffnen 1. Wenn keine Long-Positionen vorhanden sind und der schnelle gleitende Durchschnitt mit der Periode 50 höher als der langsame gleitende Durchschnitt mit der Periode 120 liegt - eine Long-Position eröffnen 2. Wenn keine Short-Positionen vorhanden sind und der schnelle gleitende Durchschnitt mit der Periode 20 tiefer als der langsame gleitende Durchschnitt mit der Periode 70 liegt — eine Short-Position eröffnen
Schließen 3. Wenn sich der schnelle gleitende Durchschnitt mit der Periode 50 tiefer als der langsame gleitende Durchschnitt mit der Periode 120 befindet — eine Long-Position schließen 4. Wenn der schnelle gleitende Durchschnitt mit der Periode 20 höher als der langsame gleitende Durchschnitt mit der Periode 70 liegt — eine Short-Position schließen

Tabelle 1. Sets von Aktionen

Aus der Perspektive des Programmierens stellen unsere "Regeln" oder die Blöcke der Tabelle einfache Funktionen oder Methoden dar, die ein Teil der zukünftigen Klasse universeller Strategien sein werden. Benennen wir diese vier Methoden:

Was bietet diese Herangehensweise? Erstens, haben wir die Aktionen klassifiziert, die der Expert Advisor für eine richtige Lösung der Handelsaufgabe ausführen muss. Alle Aktionen sind in unabhängige Blöcke aufgeteilt — gewöhnliche Klassenmethoden. Dies bedeutet, dass wir uns keine Gedanken darüber machen sollen, an welcher Stelle welcher Teil der Handelslogik bearbeitet werden muss. In diesem Fall beschränkt sich das Programmieren auf die Beschreibung dieser vier Methoden.

Zweitens, wenn es in der Zukunft nötig sein wird, die Logik des Experten zu ändern, ist dieses sehr einfach. Dafür braucht man dann nur die entsprechenden Methoden durch zusätzliche Bedingungen zu ergänzen. Drittens, wird die vorgeschlagene Handelslogik "Handelsmodi" jeden Expert Advisor unterstützen, der in diesem Stil geschrieben wurde.

 

Handelsmodi einer Strategie

Häufig muss man die Aktionen von Experten beschränken. Das einfachste Beispiel — dem Experten zu verbieten, Short- oder umgekehrt Long-Trades auszuführen. MetaTrader 4 bietet eine Auswahlmöglichkeit für diese Modi an. Er befindet sich im Tab des Einstellungen-Fensters, das beim Starten des Experten erscheint:

Abb. 2. Handelsmodi in MetaTrader 4

Es können aber auch mehr Modi vorhanden sein. Das scheint es notwendig zu machen, dass flexiblere Werkzeuge für die Konfiguration dieser Modi benötigt werden. In einigen Experten muss man z.B. den Handel zu bestimmten Zeitpunkten vorübergehend stoppen. Nehmen wir an, dass der Handelsexperte während der pazifischen Handelszeit neue Signale zum Einstieg ignorieren muss. Das ist eine klassische Methode, den Handel des Experten während einer niedrigen Volatilität auf dem Devisenmarkt zu beschränken. Wie implementiert man diesen Handelsmodus am besten und macht ihn dabei optional? Die Handelslogik aus vier Blöcken hilft uns wieder dabei.

Wenn man beim Handel Verkäufe für eine Weile verbieten muss, ist es ausreichend, die SellInit Methode nicht mehr aufzurufen, die die Regeln zur Eröffnung einer Short-Position enthält. Denn die Operationen, die einen neuen Verkauf initiieren, werden im Rahmen dieser Methode ausgeführt. Das gleiche gilt für den Kauf: wenn man die BuyInit Methode nicht aufruft, werden keine Long-Positionen eröffnet. Auf diese Weise werden verschiedene Kombinationen dieser Aufrufe bestimmten Handelsmodi des Experten entsprechen. Beschreiben wir diese Modi in der Tabelle 2:

Handelsmodus Beschreibung Methoden, die aufgerufen werden Methoden, deren Aufrufe ignoriert werden
Buy und Sell Sowohl Kauf- als auch Verkaufsaufträge sind erlaubt. Keine Begrenzungen im Handel. BuyInit
SellInit
BuySupport
SellSupport
Nur Buy Nur Kaufoperationen sind erlaubt. Sell-Operationen werden nicht ausgeführt. Die früher eröffneten Short-Positionen werden bis zur Schließung im Normalmodus verwaltet. BuyInit
BuySupport
SellSupport
SellInit
Nur Sell Nur Verkaufsaufträge sind erlaubt. Keine Kaufaufträge werden ausgeführt. Die früher eröffneten Long-Positionen werden bis zum Moment der Schließung verwaltet. SellInit
BuySupport
SellSupport
BuyInit
Keine neuen Einstiege Es ist verboten, neue Sell- oder Buy-Trades zu eröffnen. Die früher eröffneten Long- und Short-Positionen werden bis zum Moment der Schließung bei Ausstiegssignalen verwaltet. BuySupport
SellSupport
BuyInit
SellInit
Warten Die Kontrolle über die Verwaltung von früher eröffneten Positionen wird beendet. Die Initialisierung neuer Sell- und Buy-Trades wird eingestellt. Dieser Modus wird dann verwendet, wenn der Markt geschlossen ist, und keine Handelsoperationen getätigt werden dürfen. BuyInit
SellInit
BuySupport
SellSupport
Stopp Alle früher eröffneten Positionen werden geschlossen. Neue Positionen (sowohl Sell als auch Buy) werden nicht initialisiert. Schließung aller offenen Positionen durch eine spezielle Methode BuyInit
SellInit
BuySupport
SellSupport

Tabelle 2. Handelsmodi des Experten

Alle Handelsmodi werden bei der praktischen Implementierung in MQL mit einer speziellen Struktur ENUM_TRADE_STATE gesetzt. Hier ist ihre Beschreibung:

//+------------------------------------------------------------------+
//| Bestimmt den Handelsstatus des Experten.                         |
//+------------------------------------------------------------------+
enum ENUM_TRADE_STATE
{
   TRADE_BUY_AND_SELL,              // Buy- und Sell-Operationen erlaubt.
   TRADE_BUY_ONLY,                  // Nur Kauf. Verkauf verboten.
   TRADE_SELL_ONLY,                 // Nur Verkauf erlaubt. Kauf verboten.
   TRADE_STOP,                      // Handel verboten. Alle Positionen umgehend schließen. Neue Signale zum Einstieg ignorieren.
   TRADE_WAIT,                      // Die Kontrolle über offene Positionen wird eingestellt. Neue Signale werden ignoriert. Hilfreich im Moment, wenn Nachrichten erscheinen.
   TRADE_NO_NEW_ENTRY               // Signale zum Einstieg ingnorieren. Die bereits eröffneten Positionen werden nach Handelslogik verwaltet. 
};

Dank dieser Modi kann jeder Experte, der nach der vorgeschlagenen Herangehensweise geschrieben wurde, Handelsmodule einfach aktivieren oder deaktivieren, und somit zwischen den Handelsmodi blitzschnell umschalten.

 

"Umschalter" von Handelsmodi CTradeState

Wenn der Experte Handelsmodi benutzt, weiß er immer, wann er diese oder jene Handlungen durchführen muss. Ein genauer Zeitpunkt muss aber für jeden Experten einzeln angegeben werden. Besonders wichtig ist die Verwaltung der Modi beim Handel in FORTS an der Moskauer Börse. Der Börsenhandel in dieser Sektion weist eine Reihe von Besonderheiten auf, zur wichtigsten von denen die Durchführung von Clearing zweimal pro Tag, von 14:00 bis 14:03 (Zwischenclearing) und von 18:45 bis 19:00 (Hauptclearing) gehört. Es ist wünschenswert, dass der Experte zu dieser Zeit keine Handelsoperationen ausführt.

Natürlich, wenn der Experte nur während des Auftretens neuer Ticks oder Bildung neuer Balken Transaktionen vornimmt, dann wird er nicht funktionieren, wenn der Markt geschlossen ist, denn neue Notierungen gibt es in dem Momenten nicht. Viele Expert Advisors arbeiten aber mit einer eingestellten Periodizität (nach Timer), und für solche ist die Kontrolle über Transaktionen von großer Bedeutung. Der Handel kann auch am Wochenenden oder an Feiertagen betrieben werden, einige Forex-Broker bieten den Handel sogar an Wochenenden an. Aber wegen einer niedrigen Volatilität an diesen Tagen sowie wegen ihrer kleinen statistischen Bedeutung, sollte man diese Tage überspringen und nicht berücksichtigen.

Auf jeden Fall ist die Verwaltung von Handelsmodi für jeden professionellen Algotrader sehr wichtig. Diese Aufgabe kann mit dem speziellen Modul CTradeState delegiert werden. Dieses Modul wird als eine MQL5-Klasse implementiert, und eine seiner Aufgaben ist gerade den Handelsmodus zu liefern, der der laufenden Zeit entspricht. Z. B. wenn die aktuelle Zeit mit dem Moment des Clearings zusammenfällt, liefert das Modul den Status TRADE_WAIT, und wenn alle Positionen geschlossen werden müssen, liefert das Modul den Status TRADE_STOP. Gehen wir genauer aus seine Arbeit und Konfigurierungsmethoden ein. Dafür sehen wir uns die Kopfzeile dieser Klasse an:

//+------------------------------------------------------------------+
//|                                                  TimeControl.mqh |
//|                                 Copyright 2015, Vasiliy Sokolov. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Vasiliy Sokolov."
#property link      "http://www.mql5.com"
#include "Strategy.mqh"
#define ALL_DAYS_OF_WEEK 7
//+------------------------------------------------------------------+
//| Modul von Handelsstatus TradeState                               |
//+------------------------------------------------------------------+
class CTradeState
{
private:
   ENUM_TRADE_STATE  m_state[60*24*7];  // Maske von Handelsstatus
public:
                     CTradeState(void);
                     CTradeState(ENUM_TRADE_STATE default_state);
   ENUM_TRADE_STATE  GetTradeState(void);
   ENUM_TRADE_STATE  GetTradeState(datetime time_current);
   void              SetTradeState(datetime time_begin, datetime time_end, int day_of_week, ENUM_TRADE_STATE state);
};

Diese Klasse hat eine einzige Aufgabe, den laufenden Modus zu liefern. Dafür muss die GetTradeState Methode aufgerufen werden. Aber bevor das Modul einen Status liefern kann, muss dieser zuerst mit der SetTradeState Methode hinzugefügt werden.

Der Algorithmus des Moduls erinnert einen an den Zeitplan-Tab des Testagenten im MetaTrader 5:

Abb. 3. Zeitplan-Tab im MetaTrader 5 Testagenten

Dieses Fenster ermöglicht es, Arbeitszeiträume nach Wochentagen zu setzten, während denen es erlaubt ist, Aufgaben aus dem MQL5 Cloud Network auszuführen. Die CTradeState funktioniert ähnlich, aber sie lässt für jeden Zeitraum einen der fünf Aufzählungswerte ENUM_TRADE_STATE zu.

Für ein besseres Verständnis, wie CTradeState genutzt wird, lassen Sie uns das Modul der Handelsstatus konfigurieren. In der Routine auf dem FORTS-Markt verwendet der Autor des Artikels die folgende Konfiguration:

Zeit Modus Beschreibung
10:00-10:01 TRADE_WAIT Eröffnung des Marktes. Der Moment der Eröffnung wird durch eine hohe Volatilität und Preisschwankungen gekennzeichnet. Zu dieser Zeit gehen Handelsoperationen mit hohen Risiken einher. Aus diesem Grund sollte man während der ersten Minute auf den Handel verzichten und den Experten dafür in den Wartemodus versetzen.
14:00 - 14:03 TRADE_WAIT Zeit des Zwischenclearings. Während dieser Zeit arbeitet der Markt nicht, aus diesem Grund muss auch der Experte in den TRADE_WAIT Modus versetzt werden.
18:45 - 18:49 TRADE_WAIT Zeit des Hauptclearings. In diesem Moment ist der Market ist zu, und der Handel ist verboten. Der TRADE_WAIT-Modus ist ein.
23:50 - 9:59 TRADE_WAIT Der Markt ist zu, Handel verboten. TRADE_WAIT Modus.
Freitag, ab 15:00 TRADE_NO_NEW_ENTRY Freitag ist der letzte Handelstag der Woche. Damit keine Positionen über Wochenende geöffnet bleiben, müssen diese am letzten Handelstag geschlossen werden. Aus diesem Grund ist es sinnlos, neue Positionen am letzten Handelstag zu eröffnen und diese dann wenige Stunden später zu schließen. Gerade diesen Zielen dient der Modus NO_NEW_ENTRY. Jeden Freitag ab 15:00 werden neue Einstiegssignale ignoriert. Die vorhandenen Positionen können nur geschlossen werden.
Freitag, 23:40-23:50 TRADE_STOP Zeit vor der Schließung des Marktes. Zu dieser Zeit müssen alle Positionen geschlossen werden. Der Handelsexperte wechselt um 23:40 in den TRADE_STOP Modus, schließt seine offene Position und schaltet in den Wartemodus.
Samstag, Sonntag TRADE_WAIT Am Wochenende wird nicht gehandelt. Wegen der Verschiebung von Feiertagen werden einige Samstage zu Arbeitstagen. An diesen Tagen arbeitet die Börse. Das kommt sehr selten vor und man sollte solche "Arteitstage" wegen einer niedrigen Volatilität und statistischen Unbestimmtheit vermeiden. Während dieser Tage muss der Handel verboten werden unabhängig davon, ob dies ein Arbeitstag ist oder nicht.

Tabelle 3. Handelsmodi je nach Zeit

Aus der Tabelle folgt, dass die notwendige Konfigurierung eine ungewöhnliche Aufgabe ist. Die CTradeState Klasse ermöglicht aber die Erstellung solcher Kombination von Modi. Führen wir ein Skript als Beispiel an, welches die Modi aus der Tabelle setzt und dann einen Modus je nach Zeit aufruft:

//+------------------------------------------------------------------+
//|                                               TestTradeState.mq5 |
//|                                 Copyright 2015, Vasiliy Sokolov. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Vasiliy Sokolov."
#property link      "http://www.mql5.com"
#property version   "1.00"
#include <Strategy\TradeState.mqh>

CTradeState TradeState(TRADE_BUY_AND_SELL);  // Setzt den Standardmodus Buy And Sell
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   TradeState.SetTradeState(D'15:00', D'23:39', FRIDAY, TRADE_NO_NEW_ENTRY);
   TradeState.SetTradeState(D'10:00', D'10:01', ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'14:00', D'14:03', ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'18:45', D'18:59', ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'23:50', D'23:59', ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'0:00',  D'9:59',  ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'23:40', D'23:49', FRIDAY, TRADE_STOP);
   TradeState.SetTradeState(D'00:00', D'23:59', SATURDAY, TRADE_WAIT);
   TradeState.SetTradeState(D'00:00', D'23:59', SUNDAY, TRADE_WAIT);
   
   printf("10:00 - " + EnumToString(TradeState.GetTradeState(D'10:00')));
   printf("14:01 - " + EnumToString(TradeState.GetTradeState(D'14:01')));
   printf("18:50 - " + EnumToString(TradeState.GetTradeState(D'18:50')));
   printf("23:50 - " + EnumToString(TradeState.GetTradeState(D'23:51')));
   printf("Friday, > 15:00 - " + EnumToString(TradeState.GetTradeState(D'2015.11.27 15:00')));
   printf("Saturday - " + EnumToString(TradeState.GetTradeState(D'2015.11.28')));
   printf("Sunday - " + EnumToString(TradeState.GetTradeState(D'2015.11.29')));
   printf("Default State - " + EnumToString(TradeState.GetTradeState(D'11:40')));
}
//+------------------------------------------------------------------+

Der Output für dieses Skript wird folgendermaßen aussehen:

Default State - TRADE_BUY_AND_SELL
Sunday - TRADE_WAIT
Saturday - TRADE_WAIT
Friday, > 15:00 - TRADE_NO_NEW_ENTRY
23:50 - TRADE_STOP
Ы18:50 - TRADE_WAIT
14:01 - TRADE_WAIT
10:00 - TRADE_WAIT

Beachten Sie, wie die Handelsmodi gesetzt werden. Die Komponenten des Datums werden dabei nicht verwendet, nur Stunden und Minuten (D'15:00' oder D'18:40'). Wenn man der Methode ein vollständiges Datum übergibt, z.B.:

TradeState.SetTradeState(D'2015.11.27 15:00', D'2015.11.27 23:39', FRIDAY, TRADE_NO_NEW_ENTRY);

wird die Komponente des Datums trotzdem ignoriert.

Der zweite Punkt, den man berücksichtigen sollte, ist die Reihenfolge der Aufrufe von SetTradeState. Die Reihenfolge spielt eine wichtige Rolle! Das liegt daran, dass das CTradeState Modul die Maske von Handelsmodi als ENUM_TRADE_STATE Array speichert, dessen Elementenzahl der Zahl von Minuten in einer Woche gleich ist (10.080 Elemente). Die SetTradeState Methode berechnet anhand der Daten den Bereich von Elementen dieses Arrays, und füllt sie dann mit dem entsprechenden Status aus. Dies bedeutet, dass der vorherige Status durch den neuen ersetzt wird. Auf diese Weise bleibt die letzte Änderung endgültig. Der ganze Code dieser Methode ist unten angeführt:

//+------------------------------------------------------------------+
//| Setzt den Handelszustand TradeState                              |
//| INPUT:                                                           |
//| time_begin  - Zeit, von der der Handelsstatus gültig             |
//|                     ist.                                         |
//| time_end    - Zeit, bis der der Handelsstatus gültig ist         |
//| day_of_week - für welchen die Einstellung des Handelsstatus      |
//|               gilt. Entspricht den Modifikatoren                 |
//|           ENUM_DAY_OF_WEEK oder dem Modifikator ALL_DAYS_OF_WEEK |
//| state       - Handesstatus.                                      |
//| Die Datenkomponente wird in time_begin und time_end ignoriert.   |
//+------------------------------------------------------------------+
void CTradeState::SetTradeState(datetime time_begin,datetime time_end, int day_of_week, ENUM_TRADE_STATE state)
{
   if(time_begin > time_end)
   {
      string sb = TimeToString(time_begin, TIME_MINUTES);
      string se = TimeToString(time_end, TIME_MINUTES);
      printf("Time " + sb + " must be more time " + se);
      return;
   }
   MqlDateTime btime, etime;
   TimeToStruct(time_begin, btime);
   TimeToStruct(time_end,  etime);
   for(int day = 0; day < ALL_DAYS_OF_WEEK; day++)
   {
      if(day != day_of_week && day_of_week != ALL_DAYS_OF_WEEK)
         continue;
      int i_day = day*60*24;
      int i_begin = i_day + (btime.hour*60) + btime.min;
      int i_end = i_day + (etime.hour*60) + etime.min;
      for(int i = i_begin; i <= i_end; i++)
         m_state[i] = state;
   }
}

Die GetTradeState Methode funktioniert einfacher. Sie berechnet den Index des Array-Elements, der der angeforderten Zeit entspricht, und liefert dann seinen Wert:

//+------------------------------------------------------------------+
//| Liefert den früher gesetzten Handelsstatus für die               |
//| angeforderte Zeit.                                               |
//+------------------------------------------------------------------+
ENUM_TRADE_STATE CTradeState::GetTradeState(datetime time_current)
{
   MqlDateTime dt;
   TimeToStruct(time_current, dt);
   int i_day = dt.day_of_week*60*24;
   int index = i_day + (dt.hour*60) + dt.min;
   return m_state[index];
}

Der vollständige Quellcode der CTradeState Klasse ist in der TradeState.mqh Datei zu finden und steht Ihnen auch als Bestandteil der Quellcodes der Tading-Engine zur Verfügung. Die Informationen darüber, wie diese Klasse in der Trading-Engine funktioniert, erfahren Sie aus den nächsten Teilen des Artikels.

 

Fazit

Wir haben die vier grundlegenden Handelsregeln beschrieben, mit denen man die Logik für fast jeden Experten schnell und einfach formulieren kann. Jede Handelsregel stellt eine einzelne Funktion oder Klassenmethode dar. Unterschiedliche Kombinationen der Aufrufe dieser Methoden bestimmen den Modus der Strategie. Auf diese Weise wird mit minimalen Ressourcen ein relativ flexibles Verwaltungssystem des Expert Advisors umgesetzt.

Im nächsten Teil wird ein zentralisiertes Ereignis-Modell beschrieben, damit die Hauptmethoden der Handelslogik besser verstanden werden können. Darüber hinaus gehen wir auf Hilfsalgorithmen für das Trading ein, die das Erhalten von Handelsinformationen wesentlich vereinfachen.

Sie können die vollen Quellcodes der Bibliothek "Universeller Experte" herunterladen. Den Quellcode der Bibliothek finden Sie im Anhang. Die meisten Klassen dieser Bibliothek werden in den nächsten Beiträgen dieser Folge beschrieben.