Universeller Expert Advisor: Zugang zu Symboleigenschaften (Teil 8)
Einleitung
Seit der Veröffentlichung des letzten Teils des Artikels zum Thema CStrategy Trading-Engine ist eine Weile vergangen. Diese Zeit wurde benötigt, um die Entwicklung von CStrategy von einer Hilfsbibliothek bis zu einer funktionsfähigen Engine, die die meisten häufig verwendeten Werkzeuge für die Erstellung einer Handelsstrategie beinhaltet, zu reflektieren. Nach dieser Zeit habe ich die weitere Entwicklung von CStrategy umgedacht. Die praktische Anwendung von CStrategy hat eine Reihe von Nachteilen in den letzten Versionen der Engine an den Tag gebracht. Die Beseitigung dieser Nachteile führte zur Veröffentlichung neuer Artikel der Reihe "Universeller Expert Advisor". In diesem Artikel geht es um die Arbeit mit Handelssymbolen über die objektorientierte Klasse CStrategy.
Übersicht der Arbeit mit Symbolen in den vorherigen Versionen von CStrategy
Die Handelsumgebung eines Expert Advisors ist umfangreich und vielfältig. Dazu gehören verschiedene Informationen über das Konto, Kursdaten, Funktionen für die Arbeit mit der Zeit und, natürlich, Informationen über Handelssymbole. Die meisten Informationen befinden sich in den Funktionen für die Arbeit mit Handelssymbolen: das Erhalten aktueller Kurse und die Arbeit mit Eigenschaften eines Symbols. In der Regel arbeiten alle Expert Advisors intensiv mit Preisinformationen. Sie berechnen ein Preismuster oder ein Handelssignal anhand Preisdaten und führen Trades basierend auf diesem Muster aus. Für die richtige Bildung einer Handelsanfrage verwenden sie Informationen über die Eigenschaften des aktuellen Symbols: zum Beispiel, das minimale Volumen des Trades oder Freeze Level, den Abstand vom aktuellen Preis, innerhalb dessen die Platzierung von Pending Orders verboten ist.
Selbstverständlich muss diese Information leicht zugänglich sein. War es aber in den vorherigen Versionen von CStrategy auch der Fall? Setzen wir uns mit der Situation auseinander und blicken wir zurück in die Geschichte: beschreiben wir, wie die Arbeit mit einem Handelssymbol früher erfolgte. Im dritten Teil des Artikels wurde ein Modell für den Zugriff auf Kurse über den üblichen Index [] dargestellt. In die Klasse CStrategy wurden mehrere Hilfsklassen COpen, CHigh, CLow, CClose, CVolume und CTime eingebettet, jede von denen den entsprechenden Wert nach dem abgerufenen Index zurückgegeben hat. Dies ermöglichte es, Informationen über den aktuellen Symbol relativ einfach im Code des Expert Advisors zu erhalten. Um den Schlusskurs des aktuellen Balkens herauszufinden, reichte es zu schreiben:
...
double close = Close[0];
...
Der Zugriff auf Kurse im Format OHLC reichte nicht aus, und der Klasse CStrategy wurden die Methoden Ask(), Bid() und Last() zusätzlich hinzugefügt. Nach einiger Zeit reichten auch diese Methoden nicht mehr aus. Es war nötig, weitere Methode ähnlich der FreezeLevel(), die Grundinformationen über das aktuelle Symbol erhalten, hinzuzufügen. Das Volumen der Basisklasse CStrategy begann schnell zuzunehmen. Die Vielzahl der vorhandenen Methoden innerhalb von CStrategy führte zu einem Durcheinander. Aber die richtigen Schwierigkeiten begannen, wenn der Versuch gemacht wurde, mithilfe von CStrategy einen gleichzeitig auf mehreren Symbolen handelnden Expert Advisor zu erstellen. Rein formell ist CStrategy eine Multiwährungs-Engine. Dies bedeutet, dass man mit ihrer Hilfe sowohl mehrere Expert Advisors erstellen kann, die mit verschiedenen Symbolen unabhängig voneinander handeln als auch einen Expert Advisor, der zwei und mehr Symbole handelt. Das Letzte ist nicht so einfach zu implementieren, denn in diesem Fall hätten wir die Klassen von Zeitrahmen neu konfigurieren sollen:
string symbol1 = "EURUSD"; string symbol2 = "GBPUSD"; Close.Symbol(symbol1); double close_eurusd = Close[0]; Close.Symbol(symbol2); double close_gbpusd = Close[0]; ...
Diese Schwierigkeiten haben uns vor Augen geführt, dass die Informationen über das Symbol für die Implementierung in CStrategy zu umfangreich und vielfältig sind. Die Klasse CStrategy leistet bereits eine aufwändige und komplizierte Arbeit hinsichtlich der Organisation der Reihenfolge von Operationen, und die zusätzlichen Funktionen haben dazu geführt, dass der Code weniger handhabbar wurde. Stattdessen wurde die Entscheidung getroffen, Methoden für die Arbeit mit dem Symbol einer separaten Klasse CSymbol zuzuweisen.
Einführende Informationen zum Objekt WS und zur Klasse CSymbol
Statt sporadischer Methoden wie Ask(), Bid() und Last sowie spezieller Klassen wie CHigh und CLow, ist nun einer Handelsstrategie basierend auf CStrategy ein besonderes Objekt verfügbar - WS auf der Grundlage der Klasse CSymbol. Diese Klasse, die den Bibliotheken von CStrategy gehört, verfügt über eine Reihe von Methoden, die sie der Standardklasse СSymbolInfo ähnlich machen. Das ist aber eine andere Klasse, die nicht nur mit den Eigenschaften des Symbols arbeitet, sondern auch es erlaubt, seine Kurse zu erhalten einschließlich Limit Orders (Markttiefe). Der Name des Objekts "WS" stellt ein Akronym von "Work Symbol" dar, und es ist im Code der Strategie verfügbar. Dieser kurze Name wurde nicht durch Zufall ausgewählt. Während der Arbeit muss man häufig diese oder jene Eigenschaft des Symbols abrufen, deswegen erlaubt das Akronym aus zwei Zeichen dem Code kompakt und ausdrucksvoll zu bleiben.
Wie wir bereits in den vorherigen Artikeln gesagt haben, initialisiert die CStrategy Trading-Engine eine Reihe von Objekten der internen Umgebung. Der Name des Symbols und der Zeitrahmen werden gespeichert, es werden die Klassen erstellt, die das Eintreffen neuer Ereignisse abfangen (standardmäßig geht es um die Ereignisse "Neuer Tick" und "Neuer Balken"). Es wird das Logging eingestellt, Flags der Arbeitsmodi werden gesetzt. In demselben Moment wird das Objekt WS der Klasse CSymbol initialisiert. Es ist relativ einfach geschaffen. Es beinhaltet zwei interne Felder: Symbol und dessen Zeitrahmen sowie spezielle Objekte für den Zugang zu den Kursen des Symbols. Das Objekt WS wird durch die Methode InitSeries initialisiert. Wenn man das Symbol und die Timeframe des Expert Advisors kennt, ist es ganz einfach, es zu initialisieren:
CStrategy::CStrategy(void)
{
WS.InitSeries(ExpertSymbol(), Timeframe());
}
Nach der Initialisierung des Objekts kann man Eigenschaften des Symbols erhalten. Um den Hoch des aktuellen Balkens zu erhalten, schreibt man:
double max = WS.High[0];
Das Objekt WS verfügt über eine Reihe von Eigenschaften, dank denen seine Anwendung in den Berechnungen einfach und praktisch ist. Betrachten wir eine häufige Situation, dass man eine BuyStop Order ein wenig oberhalb des Hochs des vorherigen Balkens platzieren muss. Wenn wir auf EURUSD handeln und unsere Stop Order mit einem Abstand von drei fünfstelligen Punkten vom vorherigen Balken platzieren möchten, müssen wir den folgenden Code schreiben:
void CMovingAverage::InitBuy(const MarketEvent &event) { ... Trade.BuyStop(1.0, WS.High[1] + WS.StepToPrice(3), WS.Name()); ... }
So haben wir innerhalb einer Code-Zeile viele Operationen platziert:
- Extremum des vorherigen Balkens (WS.High[1]) erhalten;
- Den Wert eines Punktes mit drei multiplizieren, dadurch erhalten wir einen Kursspielraum in Höhe von drei Punkten (WS.StepToPrice(3));
- Den erhaltenen Wert (WS.High[1] + WS.StepToPrice(3)) zum Preis des Extremums addieren;
- Handelsanfrage BuyStop senden, die Auslösungsebene ist der resultierende Preis, als Symbol den Namen des aktuellen Symbols (WS.Name()) angeben.
Die Methode StepToPrice kann sich vom üblichen Bezeichnungssystem in MetaTrader unterscheiden. In den anderen Handelsplattformen ist mit dem Price Step die minimale Preisänderung gemeint. Ihre Entsprechung heißt SYMBOL_TRADE_TICK_SIZE in MetaTrader. Dieser Name ist mit der Größe oder mit dem Preis eines Ticks SYMBOL_TRADE_TICK_VALUE leicht zu verwechseln, deswegen wird ein anderer Name für diesen Parametter in CSymbol verwendet. Aber die meisten anderen Methodennamen CSymbol stimmen mit System-Modifikatoren und Methoden in MQL5 überein, allerdings wie der Beispiel mit StepToPrice zeigt, sind sie nicht immer identisch. Das Hauptziel von CSymbol besteht darin, eine einfache und intuitive Methode zum Erhalten vollständiger Informationen über ein Handelssymbol bereitzustellen.
Struktur der Klasse CSymbol. Vergleichstabelle der Methoden
Handelssymbole verfügen in MetaTrader über eine breite Palette von Eigenschaften. Alle Eigenschaften kann man in ganzzahlige, reelle und String-Eigenschaften teilen. Zu den ganzzahligen Eigenschaften gehören logische Eigenschaften (bool), System-Modifikatoren in Form von Aufzählungen (enum), Zeit und Datum (datetime) und ganzzahlige Eigenschaften (int und long). Zu den reellen Eigenschaften gehören verschiedene gebrochene Zahlen (double). Zu den String-Eigenschaften gehören die Eigenschaften, die Strings zurückgeben: Symbolname, Beschreibung des Symbols nach Strings usw. Für das Symbol ist auch eine Reihe von Eigenschaften verfügbar, die für einen bestimmten Marktsegment charakteristisch sind. Für den FORTS-Markt sind zusätzliche Eigenschaften der aktuellen Handelssitzung verfügbar. Für Optionsmärkte sind spezielle einzigartige Eigenschaften verfügbar. Die Klasse CSymbol bestimmt Eigenschaften der aktuellen FORTS-Handelssitzung in einer zusätzlichen internen Klasse SessionInfo. Alle anderen Eigenschaften werden nicht nach Typen geteilt und sind als gleichnamige Methoden so, wie sie sind, vorhanden.
Darüber hinaus beinhaltet die Klasse CSymbol zusätzliche Sammlungen, die den Abruf von Kursen eines Symbols ermöglichen. Für den Zugriff auf die Serien OHLCV werden die Klassen COpen, CHigh, CLow, CClose und CVolume öffentlich deklariert, und für den Zugang zur Markttiefe wird eine besondere Klasse verwendet, CMarketWatch, die in einem separaten Artikel beschrieben wurde: "Das MQL5-Kochbuch: Implementierung Ihrer eigenen Markttiefe". Neben gleichnamigen Methoden und Indexer-Klassen, wie zum Beispiel CClose, beinhaltet die Klasse CSymbol mehrere Methoden, die keine Entsprechungen unter MQL5 Standardfunktionen oder der Klasse SymbolInfo haben. Gehen wir darauf ausführlicher ein.
Available — diese Methode gibt true zurück, wenn das Symbol mit dem angegebenen Namen im Terminal vorhanden ist. Wenn es dieses Symbol nicht gibt, wird false zurückgegeben.
IndexByTime — gibt den Index des Balkens zurück, der der angegebenen Zeit entspricht. Zum Beispiel wird der Variablen index der Wert 1 zugewiesen:
int index = WS.IndexByTime(WS.Time[1]); // index = 1;
Diese Methode ist sehr praktisch, wenn uns die Zeit bekannt ist, und wenn wir die Nummer des Balkens erhalten möchten, der dieser Zeit entspricht. Nehmen wir an, der Expert Advisor muss eine Position schließen, nachdem er sie während BarsHold Balken gehalten hat. Ein solcher Code könnte wie folgt aussehen:
//+------------------------------------------------------------------+ //| Verwaltung einer Long-Position nach Moving Average | //+------------------------------------------------------------------+ void CImpulse::SupportBuy(const MarketEvent &event,CPosition *pos) { int bar_open = WS.IndexByTime(pos.TimeOpen()); if(bar_open >= BarsHold) pos.CloseAtMarket("Exit by time hold"); }
StepToPrice — minimale Preisänderung in Punkten des Symbols. Die Bestimmung dieser Methode wurde oben beschrieben.
Die ganze Liste der Methoden CSymbol ist in einer Tabelle unten dargestellt. Das Feld "Beschreibung" beinhaltet eine kurze Beschreibung der Methode. Meistens fällt sie mit der offiziellen Beschreibung der gleichen Eigenschaft des Symbols in der Dokumentation zusammen, aber ich glaube für einige Methoden ist die Beschreibung sogar besser gelungen.
Das Feld "Typ" des Rückgabewertes beinhaltet den Typ, den eine Methode oder Sammlung liefert.
Das Feld "MQL5 Funktion oder System-Identifier" beinhaltet den Namen eines MQL5 System-Identifiers oder einer MQL5 Funktion, die die gleichen Funktionen hat. Wenn eine Systemfunktion angegeben wird, hat sie am Ende des Namens runde Klammern, zum Beispiel: CopyOpen() oder MarketBookGet(). Mit System-Modifikator ist einer der drei Modifikatoren gemeint, der beim Aufruf der Funktionen SymbolInfoInteger, SymbolInfoDouble oder SymbolInfoString angegeben werden muss. Dieser Modifikator muss zu einer der drei Aufzählungen gehören: ENUM_SYMBOL_INFO_INTEGER, ENUM_SYMBOL_INFO_DOUBLE oder ENUM_SYMBOL_INFO_STRING. Zum Beispiel: wenn der Modifikator SYMBOL_TRADE_STOPS_LEVEL in der Spalte "MQL5 Funktion oder System-Identifizierer" angegeben wurde, bedeutet dies, dass die Funktion SymbolInfoInteger für die Erhaltung dieser Eigenschaft aufgerufen werden muss:
int stop_level = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
Die Spalte "Name der Methode CSymbol" beinhaltet den Namen der Methode, die für die Rückgabe einer Eigenschaft zuständig ist. Um den Wochentag der Anrechnung von Swap zu erhalten, muss man die folgende Methode aufrufen:
ENUM_DAY_OF_WEEK day = WS.DayOfSwap3x();
Tabelle der Methoden:
Beschreibung | Typ des Rückgabewertes | Funktion oder System-Identifizierer in MQL5 | Name der Methode von CSymbol |
---|---|---|---|
ZUGANG ZU HISTORISCHEN DATEN DES SYMBOLS | |||
Erhalten des Eröffnungskurses nach dem angegebenen Index des Balkens mit einem vorgegebenen Zeitrahmen | double | CopyOpen() | Open[] |
Erhalten des Hochkurses nach dem angegebenen Index des Balkens mit einem vorgegebenen Zeitrahmen | double | CopyHigh() | High[] |
Erhalten des Tiefkurses nach dem angegebenen Balkenindex mit einem vorgegebenen Zeitrahmen | double | CopyLow() | Low[] |
Erhalten des Schlusskurses nach dem angegebenen Index des Balkens mit einem vorgegebenen Zeitrahmen | double | CopyClose() | Close[] |
Erhalten des Volumens, das dem Balken mit dem angegebenen Index entspricht | double | CopyVolume() | Volume[] |
Erhalten der Eigenschaften der Markttiefe des Symbols, Zugriff auf Kurse des zweiten Levels (Level II) | MqlBookInfo | MarketBookGet() | MarketBook |
REELLE EIGENSCHAFTEN DES SYMBOLS | |||
Zeichen dafür, dass dieses Symbol im Terminal vorhanden ist | bool | Keine Entsprechung | Available |
Anzahl der Balken auf diesem Symbol mit dieser Timeframe | int | Bars() | BarsTotal |
Zeitrahmen des Symbols | ENUM_TIMEFRAMES | Period() | Period |
Zeichen dafür, dass das Symbol in der Marktübersicht ausgewählt wurde | bool | SYMBOL_SELECT | SelectInMarketWatch |
Zeichen für Floating Spread | bool | SYMBOL_SPREAD_FLOAT | SpreadFloat |
Spread in Punkten | int | SYMBOL_SPREAD | Spread |
Minimaler Abstand (in Punkten) vom aktuellen Preis für die Platzierung einer Stop-Order | int | SYMBOL_TRADE_STOPS_LEVEL | StopLevel |
Freeze Level (in Punkten) | int | SYMBOL_TRADE_FREEZE_LEVEL | FreezeLevel |
Flags der erlaubten Modi des Ablaufs einer Order | int | SYMBOL_EXPIRATION_MODE | FlagsExpirationOrders |
Flags der erlaubten Ausführungsmodi einer Order | int | SYMBOL_FILLING_MODE | FlagsExecutionOrders |
Flags der erlaubten Ordertypen | int | SYMBOL_ORDER_MODE | FlagsAllowedOrders |
Gibt den Index des Balkens zurück, dessen Eröffnungskurs dem übergebenen Argument entspricht | int | Keine Entsprechung | IndexByTime |
Berechnungsmethode des Terminkontraktes | ENUM_SYMBOL_CALC_MODE | SYMBOL_TRADE_CALC_MODE | CalcContractType |
Typ der Orderausführung | ENUM_SYMBOL_TRADE_MODE | SYMBOL_TRADE_MODE | ExecuteOrderType |
Modus der Ausführung von Trades | ENUM_SYMBOL_TRADE_EXECUTION | SYMBOL_TRADE_EXEMODE | ExecuteDealsType |
Muster für die Swap-Berechnung | ENUM_SYMBOL_SWAP_MODE | SYMBOL_SWAP_MODE | CalcSwapMode |
Wochentag der Berechnung eines dreifachen Swaps | ENUM_DAY_OF_WEEK | SYMBOL_SWAP_ROLLOVER3DAYS | DayOfSwap3x |
Optionstyp | ENUM_SYMBOL_OPTION_MODE | SYMBOL_OPTION_MODE | OptionType |
Optionsrecht (Call/Put) | ENUM_SYMBOL_OPTION_RIGHT | SYMBOL_OPTION_RIGHT | OptionRight |
Zeit des letzten Kurses | datetime | SYMBOL_TIME | TimeOfLastQuote |
Erster Handelstag für das Symbol (wird gewöhnlich für Futures verwendet) | datetime | SYMBOL_START_TIME | StartDate |
Letzter Handelstag für das Symbol (wird gewöhnlich für Futures verwendet) | datetime | SYMBOL_EXPIRATION_TIME | ExpirationDate |
EIGENSCHAFTEN DER AKTUELLEN HANDELSSITZUNG für MOEX FUTURES | |||
Gesamtzahl der Trades in der aktuellen Handelssitzung | long | SYMBOL_SESSION_DEALS | SymbolInfo.DealsTotal |
Gesamtzahl der Buy Orders im Moment | long | SYMBOL_SESSION_BUY_ORDERS | SymbolInfo.BuyOrdersTotal |
Gesamtzahl der Sell Orders im Moment | long | SYMBOL_SESSION_SELL_ORDERS | SymbolInfo.SellOrdersTotal |
Max.Volumen während der aktuellen Handelssitzung | long | SYMBOL_VOLUMEHIGH | SymbolInfo.HighVolume |
Min. Volumen während der aktuellen Handelssitzung | long | SYMBOL_VOLUMELOW | SymbolInfo.LowVolume |
Max. Bid während des Tages | double | SYMBOL_BIDHIGH | SymbolInfo.BidHigh |
Max. Ask während des Tages | double | SYMBOL_ASKHIGH | SymbolInfo.AskHigh |
Min. Bid während des Tages | double | SYMBOL_BIDLOW | SymbolInfo.BidLow |
Min. Ask während des Tages | double | SYMBOL_ASKLOW | SymbolInfo.AskLow |
Max. Last während des Tages | double | SYMBOL_LASTHIGH | SymbolInfo.LastHigh |
Min. Last während des Tages | double | SYMBOL_LASTLOW | SymbolInfo.LastLow |
Gesamtvolumen der Trades während der aktuellen Handelssitzung | double | SYMBOL_SESSION_VOLUME | SymbolInfo.VolumeTotal |
Gesamtumsatz während der aktuellen Handelssitzung | double | SYMBOL_SESSION_TURNOVER | SymbolInfo.TurnoverTotal |
Gesamtvolumen der offenen Positionen | double | SYMBOL_SESSION_INTEREST | SymbolInfo.OpenInterestTotal |
Gesamtvolumen der Kauforders im Moment | double | SYMBOL_SESSION_BUY_ORDERS_VOLUME | SymbolInfo.BuyOrdersVolume |
Gesamtvolumen der Verkaufsorders im Moment | double | SYMBOL_SESSION_SELL_ORDERS_VOLUME | SymbolInfo.SellOrdersVolume |
Eröffnungskurs der Handelssitzung | double | SYMBOL_SESSION_OPEN | SymbolInfo.PriceSessionOpen |
Schlusskurs der Handelssitzung | double | SYMBOL_SESSION_CLOSE | SymbolInfo.PriceSessionClose |
Gewichteter Durchschnittspreis | double | SYMBOL_SESSION_AW | SymbolInfo.PriceSessionAverage |
Abrechnungskurs während der aktuellen Handelssitzung | double | SYMBOL_SESSION_PRICE_SETTLEMENT | SymbolInfo.PriceSettlement |
Maximal zulässiger Kursänderungsbetrag während einer Handelssitzung | double | SYMBOL_SESSION_PRICE_LIMIT_MAX | SymbolInfo.PriceLimitMax |
Minimal zulässiger Kursänderungsbetrag während einer Handelssitzung | double | SYMBOL_SESSION_PRICE_LIMIT_MIN | SymbolInfo.PriceLimitMin |
REELLE EIGENSCHAFTEN DES SYMBOLS | |||
Ask — bester Verkaufskurs | double | SYMBOL_ASK | Ask |
Bid — bester Kaufkurs | double | SYMBOL_BID | Bid |
Last — Preis, zu welchem der letzte Trade ausgeführt wurde | double | SYMBOL_LAST | Last |
Wert der minimalen Preisänderung multipliziert mit der übergebenen Anzahl von Price Step | double | Keine Entsprechung | StepToPrice |
Wert eines Punktes (Ticks) | double | SYMBOL_POINT | PriceStep |
Preis eines Punktes (Ticks) in der Kontowährung | double | SYMBOL_TRADE_TICK_VALUE | TickValue |
Basispreis der Option | double | SYMBOL_OPTION_STRIKE | OptionStrike |
Kontraktgröße | double | SYMBOL_TRADE_CONTRACT_SIZE | ContractSize |
Min. Volumen für die Ausführung eines Trades | double | SYMBOL_VOLUME_MIN | VolumeContractMin |
Max. Volumen für die Ausführung eines Trades | double | SYMBOL_VOLUME_MAX | VolumeContractMax |
Minimale Schrittweite der Volumenänderung für den Abschluss eines Trades | double | SYMBOL_VOLUME_STEP | VolumeContractStep |
Maximal zulässiges Gesamtvolumen einer offenen Position und Pending Orders in einer Richtung (Kauf oder Verkauf) für dieses Symbol | double | SYMBOL_VOLUME_LIMIT | VolumeContractLimit |
Swap, der beim Halten einer Long-Position mit dem Volumen von einem Kontrakt gerechnet wird | double | SYMBOL_SWAP_LONG | SwapLong |
Swap, der beim Halten einer Short-Position mit dem Volumen von einem Kontrakt angerechnet wird | double | SYMBOL_SWAP_SHORT | SwapShort |
Margin, die für die Eröffnung einer 1-Lot-Position benötigt wird | double | SYMBOL_MARGIN_INITIAL | MarginInit |
Margin, die für die Erhaltung eines Lots einer offenen Position benötigt wird | double | SYMBOL_MARGIN_MAINTENANCE | MarginMaintenance |
Margin, die für das Halten eines Lot einer abgesicherten Position benötigt wird | double | SYMBOL_MARGIN_HEDGED | MarginHedged |
STRING-EIGENSCHAFTEN DES SYMBOLS | |||
Symbolname | string | Symbol() | Name |
Name des Basis-Vermögenswertes für ein abgeleitetes Symbol | string | SYMBOL_BASIS | NameBasisSymbol |
Basiswährung des Symbols | string | SYMBOL_CURRENCY_BASE | NameBasisCurrency |
Währung des Profits | string | SYMBOL_CURRENCY_PROFIT | NameCurrencyProfit |
Währung der Margin | string | SYMBOL_CURRENCY_MARGIN | NameCurrencyMargin |
Quelle des aktuellen Kurses | string | SYMBOL_BANK | NameBank |
String-Beschreibung des Symbols | string | SYMBOL_DESCRIPTION | Description |
Name des Handelssymbols im System der internationalen Identifikationsnummern von Wertpapieren — ISIN | string | SYMBOL_ISIN | NameISIN |
Pfad im Baum der Symbole | string | SYMBOL_PATH | SymbolPath |
Verwendung mehrerer Symbole gleichzeitig
Da CSymbol eine einfache Klasse darstellt, kann man unbegrenzt viele Objekte diese Klasse innerhalb des Expert Advisors erstellen. Das Objekt WS stellt nur eines dieser Objekte dar, das vorher durch die CStrategy Trading-Engine erstellt wurde, und das auf das aktuelle Symbol und auf den Zeitrahmen des Expert Advisors hinweist. Der Expert Advisor selbst kann ein zusätzliches Symbol erstellen, der Zugriff auf jedes andere Symbol bietet. Nehmen wir an, der Expert Advisor handelt am Terminmarkt der Moskauer Börse und verfolgt gleichzeitig zwei Symbole — Si und Brent. In seinem Code kann man zwei CSymbol Objekte platzieren und diese Si und Brent benennen:
//+------------------------------------------------------------------+ //| EventListener.mqh | //| Copyright 2017, Vasiliy Sokolov, St-Petersburg, Russia | //| https://www.mql5.com/de/users/c-4 | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Vasiliy Sokolov." #property link "https://www.mql5.com/de/users/c-4" #include <Strategy\Strategy.mqh> //+-------------------------------------------------------------------------------+ //| Das Template für eine Strategie, die mit zwei Symbolen gleichzeitig arbeitet | //+-------------------------------------------------------------------------------+ class CIntRate : public CStrategy { CSymbol Si; // Rubel-Dollar CSymbol Brent; // Öl public: virtual void OnEvent(const MarketEvent& event); virtual bool OnInit(); }; //+------------------------------------------------------------------+ //| Initialisiert die Symbole Öl und Rubel | //+------------------------------------------------------------------+ bool CIntRate::OnInit(void) { Si.InitSeries("Si Splice", Timeframe()); Brent.InitSeries("BR Splice", Timeframe()); return true; } //+------------------------------------------------------------------+ //| Ölpreis in Rubel | //+------------------------------------------------------------------+ void CIntRate::OnEvent(const MarketEvent &event) { double brent_in_rub = Brent.Last()*Si.Last()/Si.ContractSize(); } //+------------------------------------------------------------------+
Dieser Code des Expert Advisors erhält die letzten Kurse der Öl- und Rubel-Futures und berechnet die bekannte Formel des Ölpreises in Rubel. Da ein Si Terminkontrakt gleich 1000$ ist, muss man das Ergebnis zusätzlich durch die Größe eines Terminkontrakts teilen. Da aber alle Eigenschaften in der Klasse CSymbol vereinigt sind, ist das eine einfache Operation. Der restliche Code ist auch einfach und bündig. Wichtig ist nicht zu vergessen, die Objekte Si und Brent beim Starten des Expert Advisors in der Methode OnInit zu initialisieren.
Zeichnung des Profils des Zinssatzes mithilfe von CSymbol
Das letzte Anwendungsbeispiel von CSymbol ist ein wenig komplizierter aber auch interessanter. Es ist bekannt, dass Futures mit einem Contango in Hinsicht auf den Basis-Vermögenswert gehandelt werden. Dies ist damit verbunden, dass der Preis für die Ware in der Zukunft teurer sein wird als der aktuelle Preis. Diese Differenz bestimmt den Zinssatz für eine Ware oder ein Vermögenswert auf dem Markt. Betrachten wir ein Beispiel mit dem Future Rubel/Dollar. Als ich den Artikel schrieb, machte sein Preis 56.2875 Rubel pro 1 Dollar aus, und der Preis des nächsten Terminkontraktes Si-6.17 belief sich auf 56682 Rubel pro 1000$ oder 56,682 Rubel pro 1 Dollar. D.h. die Differenz zwischen dem Preis und dem Preis in 30 Tagen (zum 16.05.2017, Si-6.17 verfällt in genau 30 Tagen) beträgt 0,395 Rubel oder 39,5 Kopeken. Der Rubel wertet also laut dem Markt ab und sinkt auf 39,5 Kopeken, was 0.7% von seinem aktuellen Preis ausmacht. Es ist leicht zu berechnen, dass die Inflation in 12 Monaten laut dem Markt 8,42% betragen wird. Das ist aber die Inflationsrate, die nur für den nächsten Future berechnet wurde. Wenn man Si-6.17 durch Si-9.17 ersetzt, fällt die Inflationsrate niedriger aus und beläuft sich auf 7.8% im Jahr. Wenn wir alle Si Futures mit dem Basispreis des Vermögenswertes vergleichen, können wir das Profil des Zinssatzes erhalten. Dieses Profil wird als Tabelle dargestellt, die die Erwartungen der Investoren je nach Zeit zeigt. Wir können, zum Beispiel, den Zinssatz für die nächsten 30, 100, 200, 300, 400 und 500 Tagen herausfinden.
Um diese Werte zu berechnen, müssen wir anscheinend verschiedene Eigenschaften der Symbole verwenden sowie die Liste der Symbole manipulieren. Die Aufgabenstellung für die Berechnung des Profils des Zinssatzes sieht wie folgt aus.
- Der Expert Advisor wird auf jedem Futures-Symbol gestartet. Er analysiert den Namen des Symbols und lädt die mit ihm verbundenen Futures.
- Jeder geladene Future stellt ein CSymbol Objekt dar, dass in der Liste der Symbole platziert wird.
- Im Moment des Eintreffens eines neuen Ticks durchläuft der Expert Advisor die Sammlung der Symbole. Für jedes Symbol wird sein Basis-Symbol gefunden.
- Es wird die Differenz zwischen dem Preis des ausgewählten Symbols und dem Preis des Basis-Symbols berechnet. Diese Differenz wird in Prozent umgerechnet und danach in den jährlichen Gegenwert umgewandelt. Dafür wird die Restlaufzeit des Futures berücksichtigt.
- Die erhaltene Differenz wird als eine Tabellenzeile auf das Panel ausgegeben. Jede Zeile sieht wie folgt aus: "Name des Futures — Anzahl der Tage bis zum Verfallstag — Zinssatz".
Aus der Beschreibung folgt, dass der Algorithmus nicht so einfach ist, wie er scheint. Aber mithilfe der CStrategy Engine und des Objekts CSymbol können wir den Rechenaufwand für den Expert Advisor wesentlich reduzieren. Unser Code wird als ein Expert Advisor implementiert, der Expert Advisor selbst wird aber keine Operationen ausführen. Stattdessen wird er einfach Zinssätze auf das Panel ausgeben. Betrachten wir den resultierenden Code:
//+------------------------------------------------------------------+ //| EventListener.mqh | //| Copyright 2017, Vasiliy Sokolov, St-Petersburg, Russia | //| https://www.mql5.com/de/users/c-4 | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Vasiliy Sokolov." #property link "https://www.mql5.com/de/users/c-4" #include <Strategy\Strategy.mqh> #include <Arrays\ArrayObj.mqh> #include "Panel.mqh" //+------------------------------------------------------------------+ //| Profil des Zinssatzes | //+------------------------------------------------------------------+ class CIntRate : public CStrategy { CArrayObj Symbols; // Liste der Symbole CPercentPanel Panel; // Panel der Zeichnung der Zinssätze double BaseRate(CSymbol* fut); public: virtual void OnEvent(const MarketEvent& event); virtual bool OnInit(); }; //+----------------------------------------------------------------------------------+ //| Fügt die benötigten Futures für die Berechnung des Profils des Zinssatzes hinzu | //+----------------------------------------------------------------------------------+ bool CIntRate::OnInit(void) { string basis = WS.NameBasisSymbol(); for(int i = 0; i < SymbolsTotal(false); i++) { string name = SymbolName(i, false); int index = StringFind(name, basis, 0); if(index != 0) continue; CSymbol* Fut = new CSymbol(name, Timeframe()); if(Fut.ExpirationDate() == 0 || Fut.ExpirationDate() < TimeCurrent()) { delete Fut; continue; } string text = "Add new symbol " + Fut.Name() + " in symbols list"; CMessage* msg = new CMessage(MESSAGE_INFO, __FUNCTION__, text); Log.AddMessage(msg); Symbols.Add(Fut); } string text = "Total add symbols " + (string)Symbols.Total(); CMessage* msg = new CMessage(MESSAGE_INFO, __FUNCTION__, text); Log.AddMessage(msg); if(Symbols.Total() > 0) { Panel.Show(); } return true; } //+------------------------------------------------------------------+ //| Berechnet das Profil und gibt es in die Tabelle aus | //+------------------------------------------------------------------+ void CIntRate::OnEvent(const MarketEvent &event) { double sec_one_day = 60*60*24; //86 400 for(int i = 0; i < Symbols.Total(); i++) { CSymbol* Fut = Symbols.At(i); double brate = BaseRate(Fut); double days = (Fut.ExpirationDate()-TimeCurrent())/sec_one_day; if(Fut.Last() == 0.0) continue; double per = (Fut.Last() - brate)/brate*100.0; double per_in_year = per/days*365; Panel.SetLine(i, Fut.NameBasisSymbol() + " " + DoubleToString(days, 0) + " Days:", DoubleToString(per_in_year, 2)+"%"); } } //+------------------------------------------------------------------+ //| Gibt den Spotkurs des Futures zurück | //+------------------------------------------------------------------+ double CIntRate::BaseRate(CSymbol* fut) { string name = fut.NameBasisSymbol(); if(StringFind(name, "Si", 0) == 0) return SymbolInfoDouble("USDRUB_TOD", SYMBOL_LAST)*fut.ContractSize(); return SymbolInfoDouble(name, SYMBOL_LAST)*fut.ContractSize(); } //+------------------------------------------------------------------+
Die wichtigsten Funktionen beinhaltet die Methode OnInit. Sie erhält den Namen eines Basis-Symbols über WS.NameBasisSymbol(), durchläuft alle Symbole und legt alle Futures fest, die dem Basis-Symbol entsprechen. Jeder Future wird ins Objekt CSymbol umgewandelt und in die Liste der Symbole CArrayObj platziert. Aber zuerst wird überprüft, ob dieser Future gültig ist, und wenn sein Verfallstag in der Zukunft liegt, dann ist es der Future, den wir brauchen.
In der Methode OnEvent wird der Zinssatz für jeden Futures berechnet, der in der Sammlung "Symbols" platziert ist. Es wird die Anzahl der Tage bis zum Verfallstag, das Delta zwischen dem Future und dem Spotpreis berechnet. Die Differenz zwischen den Preisen wird in Prozent umgerechnet, und das Prozent wird entsprechend der jährlichen Rendite normiert. Der erhaltene Wert wird in die Tabelle Panel (Methode SetLine) eingetragen.
Die Tabelle selbst ist ganz einfach und basiert auf dem gleichen Set grafischer Klassen, wie das CStrategy Panel, das zusammen mit dem Expert Advisor erscheint. Der Code der grafischen Komponente des Expert Advisors ist unten angeführt:
//+------------------------------------------------------------------+ //| Panel.mqh | //| Copyright 2017, Vasiliy Sokolov. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Vasiliy Sokolov." #property link "https://www.mql5.com" #include <Panel\ElChart.mqh> class CPercentPanel : public CElChart { private: CArrayObj m_fields; CArrayObj m_values; public: CPercentPanel(void); void SetLine(int index, string field, string value); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CPercentPanel::CPercentPanel(void) : CElChart(OBJ_RECTANGLE_LABEL) { Width(200); Height(200); } //+------------------------------------------------------------------+ //| Setzt die Linie | //+------------------------------------------------------------------+ void CPercentPanel::SetLine(int index,string field,string value) { if(m_fields.Total() <= index) { CElChart* sfield = new CElChart(OBJ_LABEL); sfield.XCoord(XCoord()+10); sfield.YCoord(YCoord()+21*index+10); sfield.Text(field); m_fields.Add(sfield); m_elements.Add(sfield); CElChart* svalue = new CElChart(OBJ_LABEL); svalue.YCoord(YCoord()+21*index+10); svalue.XCoord(XCoord()+132); svalue.Text(value); svalue.TextColor(clrGreen); m_values.Add(svalue); m_elements.Add(svalue); if(IsShowed()) { sfield.Show(); svalue.Show(); } Height(m_fields.Total()*20 + m_fields.Total()*2 + 10); } else { CElChart* el = m_fields.At(index); el.Text(field); el = m_values.At(index); el.Text(value); } ChartRedraw(); }
Nachdem dieser Expert Advisor kompiliert und auf einem der Charts des Si Futures gestartet wird, erscheint die folgende Tabelle:
Profil des Zinssatzes Rubel/Dollar als Tabelle
Wie man anhand der Tabelle sieht, sind die Zinssätze quasi auf allen Timeframes gleich und belaufen sich auf 7% jährlich. Einen höheren Zinssatz weist der nächste Future auf.
Wichtiger Hinweis: vor dem Start des Experten vergewissern Sie sich, dass die Kurse aller benötigten Futures verfügbar sind und im Voraus geladen wurden. Andernfalls kann das Ergebnis unbestimmt sein.
Fazit
Wir haben die neue Klasse CSymbol im Rahmen der Klassen CStrategy betrachtet. Dank dieser Klasse ist es einfacher geworden, mit Symbolen zu arbeiten und ihre Eigenschaften zu erhalten. Dank CSymbol haben wir einen interessanten und unkonventionellen Indikator des Profils des Zinssatzes erstellt. Dieses Beispiel ist sehr repräsentativ. Es wurde eine Vielzahl von Eigenschaften aus CSymbol Objekten erhalten, und die Berechnung war nicht so kompliziert. Der Expert Advisor arbeitete gleichzeitig mit sechs Symbolen, dadurch wurde aber sein Code nicht länger. Da CStrategy von CObject abgeleitet wird, ist es einfach, Instanzen dieser Klasse in Standardsammlungen zu platzieren. Dadurch wird die Datenverarbeitung basierend auf dieser Klasse skalierbar und universell. Darüber hinaus wies CStrategy der CSymbol Klasse untypische Funktionen zu, dank denen die CStrategy Klasse leichter geworden ist und sich besser verwalten lässt.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/3270
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.