Methode der Flächeninhalte
Gliederung
- Einleitung
- 1. Allgemeine Auswertungsmethode für Werte des RSI-Indikators
- 2. Methode der Flächeninhalte
- 3. Indikator RSIAreaIndicator_v1
- 3.1. Erstellung eines Entwurfs des Indikators
- 3.2. Ausfüllung der Kopfzeile des Indikators
- 3.3. Bearbeitung der OnInit() Funktion des Indikators
- 3.4. Erstellung einer Hilfsfunktion des Indikators
- 3.5. Erstellung des Hauptcodes des Indikators
- 4. Expert Advisor RSIAreaExpert version 1.00
- 4.1. Bearbeitung der Kopfzeile des Expert Advisors
- 4.2. Hilfsfunktion RSIAreaFunc
- 4.3. Code für das Testen der CopyBuffer Funktion
- 4.4. Weitere Bearbeitung der Hilfsfunktion
- 4.5. Funktion OnTick() des Expert Advisors
- 5. Testen des Expert Advisors RSIAreaExpert version 1.00 für verschiedene Perioden und Symbole
- Fazit
- Literaturverzeichnis
Einleitung
Wie man die Indikatoren und Expert Advisors aus den Zip-Dateien am Ende des Artikels richtig installiert: die Zip-Dateien "Indicators.zip" und "Experts.zip" müssen im <Dateiordner>\MQL5\ entpackt werden
2004 erschien die Beschreibung der Methode zum ersten Mal [1]. Die Methode zeichnet sich dadurch aus, dass sie die Daten des RSI-Indikators aus einer ungewöhnlichen Perspektive betrachtet: es wird vorgeschlagen, den Flächeninhalt abzuschätzen, den der Oszillator über/unter der Linie 50 seit dem letzten Moment zeichnet, wo diese durchgekreuzt wurde. Seit 2004 haben sich die Märkte stark verändert, die MQL5-Sprache wurde entwickelt, und dies bedeutet, es ist höchste Zeit, die Strategie in der MQL5-Sprache auf dem aktuellen Markt zu überprüfen.
1. Allgemeine Auswertungsmethode für Werte des RSI-Indikators
Die gewöhnliche Methode des Handels nach den Signalen des RSI-Indikators beinhaltet die Auswertung der Werte des Indikators im Hinblick auf das überkaufte/überverkaufte Niveau, die Suche nach der Divergenz zwischen den Werten des Indikators und dem Preis, Umkehrung nachdem der Indikator in den überkauften/überverkauften Bereichen war, und das Muster Failure Swing. Auf diese Weise werden für die technische Analyse des RSI-Oszillators mindestens vier Signale verwendet, was das Enscheidungssystem erschwert.
Aber wir wissen Bescheid, dass der RSI-Indikator sich nicht in der überkauften (über der Linie 70)/überverkauften Zone (unter der Linie 30) lange befinden kann – er kehrt unter allen Umständen zurück und durchkreuzt die Linie 50:
Abb. 1. Der RSI-Oszillator kehrt immer aus der überkauften/überverkauften Zone zurück
Auf der Abbildung 1 sieht man, dass die Zeit, die der Oszillator in den überkauften/überverkauften Zonen verbringt im Vergleich zur restlichen Zeit sehr kurz ist. Nachdem der RSI in den überkauften/überverkauften Zonen gewesen ist, durchkreuzt er die Linie 50. Gerade das Wissen darüber, dass der RSI-Oszillator immer zurückkehrt und die Linie 50 durchkreuzt, sowie die Notwendigkeit, die technische Analyse von Werten des RSI-Oszillators zu vereinfachen, bildeten die Grundlage für die Entwicklung der Methode der Flächeninhalte.
2. Methode der Flächeninhalte
Nach der Methode der Flächeninhalte werden die Werte des RSI-Oszillators nach einer Größe ausgewertet nämlich nach dem Flächeninhalt, den der Oszillator über/unter der Linie 50 bildet. Dieser Wert beschreibt das überkaufte/überverkaufte Niveau:
Abb. 2. Die Methode der Flächeninhalte — Abschätzung der Fläche über/unter der Linie 50
Als Signal zur Eröffnung einer Position dient in diesem Fall die Größe des Inhalts über/unter der Linie 50 seit dem letzten Moment, als sie und der RSI-Indikator sich gekreuzt haben.
- Wenn sich der RSI-Indikator lange über der Linie 50 befindet und einen bestimmten Wert des Inhalts überschreitet (z.B. 300) wird eine SELL-Position eröffnet:
Abb. 3. Signal zur Eröffnung einer SELL-Position, wenn der Bereich gleich 300 ist
-
Wenn sich der RSI lange unter der Linie 50 befindet und dann einen bestimmten Wert des Inhalts überschreitet, wird eine BUY-Position eröffnet.
Das Signal zum Schließen einer Position wird in dem Moment generiert, wenn der RSI-Oszillator die Linie 50 durchkreuzt, mit anschließender Bildung des lokalen Maximums/Minimums und dem Rollback von 4 %.
- Z.B., wenn sich der RSI-Indikator während einer langen Zeit über der Linie 50 befindet, bekommen wir irgendwann eine offene SELL-Position. Dann verringert sich der Wert des Indikators und erreicht sagen wir die Linie 40, dann nimmt der Wert wieder zu (d.h. der lokale Minimum wird gebildet). Wenn der Wert des Indikators die Linie 44 erreicht, ist dies das Signal zum Schließen der Position:
Abb. 4. Signal zum Schließen einer SELL-Position nach der Bildung des lokalen Minimums und dem anschließenden Rollback von 4%
- Die gleiche Logik entsteht, wenn sich der Indikator lange unter der Linie 50 befindet, in diesem Fall warten wir aber, bis das lokale Maximum gebildet wird.
Bei der Veranschaulichung des Flächeninhalts über/unter der Linie 50 hilft uns der RSIAreaIndicator Indikator.
3. Indikator RSIAreaIndicator_v1
Der RSIAreaIndicator Indikator basiert auf dem RSI Oszillator. Der grundlegende Unterschied besteht darin, dass der RSIAreaIndicator zwei Puffer hat. Ein Puffer hat den Stil DRAW_HISTOGRAM und der zweite DRAW_LINE. Die Werte der Puffer werden nach der folgenden Formel berechnet:
So sieht der Indikator RSIAreaIndicator Version 1.00 aus:
Abb. 5. RSIAreaIndicator _v1 Indikator
3.1. Erstellung eines Entwurfs des Indikators
Ich empfehle, die von Ihnen erstellen Kundenindikatoren in einem separaten Ordner abzulegen. In meinem Fall heißt dieser Ordner "MyInd". Vor dem Schreiben des Indikators ist es notwendig, einen Entwurf für ihn im MetaEditor unter Verwendung von MQL5 Wizard zu erstellen. Die ersten Schritte der Erstellung eines Entwurfs finden Sie in diesem Video:
Den Entwurf können Sie sich am Ende des Beitrag anschauen, der Indikator wurde unter dem Namen "RSIAreaIndicatorStep1.mq5" gespeichert.
3.2. Ausfüllung der Kopfzeile des Indikators
Der nächste Schritt ist das Hinzufügen der Beschreibung des Indikators. Später kann man die Beschreibung immer im Allgemeines-Tab in den Einstellungen des Indikators sehen. Der ganze hinzugefügte Code wird für die visuelle Wahrnehmung gefärbt:
#property version "1.00" #property description "The indicator displays area RSI over/under line 50" #property indicator_separate_window
Wir wissen, dass RSIAreaIndicator über zwei Puffer verfügt. Neben diesen zwei brauchen wir einen zusätzlichen Hilfspuffer. Somit beläuft sich die Zahl der Puffer, die im Indikator verwendet werden, auf drei. Fangen wir mit der Bearbeitung der Kopfzeile des Codes des Indikators an:
#property indicator_separate_window #property indicator_buffers 3 #property indicator_plots 2 #property indicator_type1 DRAW_HISTOGRAM #property indicator_type2 DRAW_LINE #property indicator_color1 clrGray #property indicator_color2 clrGray //--- input parameters input int ExtRSIPeriod=13;
Nun müssen wir drei Arrays deklarieren, in denen die Werte der Indikator-Puffer und des Hilfspuffers gespeichert werden:
//--- input parameters input int ExtRSIPeriod=13; //---- buffers double ExtMapBuffer1[]; double ExtMapBuffer2[]; double ExtMapBuffer3[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function |
Da unser Indikator RSIAreaIndicator anhand des standardmäßigen RSI-Indikators berechnet wird, und wir die Werte des Indikators erhalten müssen, wird eine Variable benötigt, in der der Bezeichner (Handle) des Relative Strength Index Indikators gespeichert wird:
double ExtMapBuffer3[]; //--- variable for storing the handle of the iRSI indicator int handle; //+------------------------------------------------------------------+ //| Custom indicator initialization function |
Nun müssen drei Variablen in der Kopfzeile deklariert werden. In der Variablen name wird der Name des Symbols gespeichert, auf dem der Indikator gestartet wurde, in der Variablen short_name — der Kurzname des Indikators und in der Variablen bars_calculated — die Anzahl berechneter Balken im RSI-Indikator:
int handle; //--- variable for storing string name=Symbol(); //--- name of the indicator on a chart string short_name; //--- we will keep the number of values in the Relative Strength Index indicator int bars_calculated=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function |
Die Kopfzeile des Indikators ist ausgefüllt, nun können wir die OnInit() Funktion bearbeiten.
3.3. Bearbeitung der OnInit() Funktion des Indikators
Da wir einen Indikator schreiben, müssen wir die Indikatorpuffer mit den früher deklariereten dynamischen Arrays vom Typ double verbinden:
int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,ExtMapBuffer1,INDICATOR_DATA); SetIndexBuffer(1,ExtMapBuffer2,INDICATOR_DATA); SetIndexBuffer(2,ExtMapBuffer3,INDICATOR_CALCULATIONS); //--- return(INIT_SUCCEEDED);
Nachdem wir die Puffer mit den Arrays verbunden haben, setzen wir die Indexierung der Elemente des Arrays wie in Timeserien (empfehlenswert ist, sich das Beispiel in der Dokumentation über ArraySetAsSeries anzuschauen). Das ganz rechte Element der Arrays hat den Index "0":
SetIndexBuffer(1,ExtMapBuffer2,INDICATOR_DATA); SetIndexBuffer(2,ExtMapBuffer3,INDICATOR_CALCULATIONS); ArraySetAsSeries(ExtMapBuffer1,true); ArraySetAsSeries(ExtMapBuffer2,true); ArraySetAsSeries(ExtMapBuffer3,true); //--- return(INIT_SUCCEEDED);
Setzen wir die Genauigkeit der Wiedergabe — der Indikator wird mit zwei Zeichen nach dem Komma angezeigt:
ArraySetAsSeries(ExtMapBuffer3,true); //--- set accuracy IndicatorSetInteger(INDICATOR_DIGITS,2); //--- return(INIT_SUCCEEDED);
In der OnInit() Funktion müssen wir noch den Bezeichner (Handle) des RSIndex Indikators erhalten, die Variable short_name ausfüllen und dem Indikator einen Kurznamen zuweisen:
ArraySetAsSeries(ExtMapBuffer2,true); ArraySetAsSeries(ExtMapBuffer3,true); //--- set accuracy IndicatorSetInteger(INDICATOR_DIGITS,2); handle=iRSI(name,0,ExtRSIPeriod,PRICE_CLOSE); //--- if the handle is not created if(handle==INVALID_HANDLE) { //--- notify about failure and output error code PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d", name, EnumToString(PERIOD_CURRENT), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } //--- show the symbol/timeframe the RSI Area Indicator is calculated for short_name=StringFormat("RSIArea(%d)",ExtRSIPeriod); IndicatorSetString(INDICATOR_SHORTNAME,short_name); //--- normal initialization of the indicator return(INIT_SUCCEEDED);Die Kopfzeile des Indikators und die OnInit() Funktion sind nun ausgefüllt. Sie können den bearbeiteten Code am Ende des Beitrags finden: der Indikator wurde unter dem Namen "RSIAreaIndicatorStep2.mq5" gespeichert.
3.4. Erstellung einer Hilfsfunktion des Indikators
Für die Arbeit des Indikators RSIAreaIndicator muss man bei jeder Eingabe der OnCalculate() Funktion Daten des RSI-Indikators erhalten. Genauso wichtig ist es, die Bedingungen für ein einfaches Lesen des Codes zu sichern, und die Funktionen des Programms zu teilen. Der Hilfscode für das Erhalten von RSI-Werten und das Kopieren dieser Werte in einen der Puffer von RSIAreaIndicator wurden aus diesem Grund in eine separate Funktion FillArrayFromBuffer() verschoben. Wir platzieren diese nach der OnCalculate() Funktion. Die Werte werden mit der Funktion CopyBuffer kopiert.
//--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Filling indicator buffers from the iRSI indicator | //+------------------------------------------------------------------+ bool FillArrayFromBuffer(double &rsi_buffer[], // indicator buffer of Relative Strength Index values int ind_handle, // handle of the iRSI indicator int amount // number of copied values ) { //--- reset error code ResetLastError(); //--- fill a part of the iRSIBuffer array with values from the indicator buffer that has 0 index if(CopyBuffer(ind_handle,0,0,amount,rsi_buffer)<0) { //--- output error code if copying fails PrintFormat("Failed to copy data from the iRSI indicator, error code %d",GetLastError()); //--- quit with zero result - it means that the indicator is considered as not calculated return(false); } //--- all in order return(true); } //+------------------------------------------------------------------+
3.5. Erstellung des Hauptcodes des Indikators
Der Hauptcode (oder Logik) des RSIAreaIndicator Indikators befindet sich in der OnCalculate() Funktion. Hier wird die Hauptvariable values_to_copy deklariert. Später wird die Variable values_to_copy die Anzahl der Werte speichern, die aus dem RSI-Indikator kopiert werden muss.
const int &spread[]) { //--- number of values copied from the iRSI indicator int values_to_copy; //--- determine the number of values calculated in the indicator int calculated=BarsCalculated(handle); if(calculated<=0) { PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError()); return(0); } //--- return value of prev_calculated for next call return(rates_total); }
Berechnung des Wertes values_to_copy:
PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError()); return(0); } //--- if it is the first calculation of the indicator or if the number of values in the iRSI indicator changed //---or if it is necessary to calculate the indicator for two or more bars (it means something has changed in the price history) if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1) { //--- if the iRSIBuffer array is greater than the number of values in the iRSI indicator for symbol/period, then we don't copy everything //--- otherwise, we copy less than the size of indicator buffers if(calculated>rates_total) values_to_copy=rates_total; else values_to_copy=calculated; } else { //--- it means that the indicator is calculated not for the first time, but since the last call of OnCalculate() //--- not more than one bar is added for calculation values_to_copy=(rates_total-prev_calculated)+1; } //--- return value of prev_calculated for next call return(rates_total);
Warum wird die Variable values_to_copy auf solche Weise berechnet? Die Elemente der Arrays (time[], open[], high[], low[], close[], tick_volume[], volume[] und spread[]), die an die OnCalculate() Funktion übergeben werden, werden in einem MQL5-Indikator vom Anfang des Arrays zum Ende indexiert. So sieht das auf dem Beispiel aus:
Abb. 6. Indexierung der Elemente des Arrays, wenn Array keine Timeserie ist
D.h. im Array, der nicht als Timeserie gilt, hat das Element ganz rechts den höchsten Index. Dies muss bei mathematischen Berechnungen berücksichtigt werden.
Nun wenn der Wert der Variablen values_to_copy berechnet ist, kann man die Hilfsfunktion FillArrayFromBuffer() aufrufen und die Indikatorpuffer ExtMapBuffer1[] und ExtMapBuffer2[] ausfüllen:
//--- not more than one bar is added for calculation values_to_copy=(rates_total-prev_calculated)+1; } //--- fill the array with values of the iRSI indicator //--- if FillArrayFromBuffer returns false, it means the information is not ready yet, quit operation if(!FillArrayFromBuffer(ExtMapBuffer3,handle,values_to_copy)) return(0); //--- for(int i=0;i<values_to_copy;i++) { ExtMapBuffer1[i]=ExtMapBuffer2[i]=ExtMapBuffer3[i]-50.0; } //--- memorize the number of values in the Relative Strength Index indicator bars_calculated=calculated; //--- return value of prev_calculated for next call return(rates_total);
Der Indikator RSIAreaIndicator version 1.00 ist fertig. Man kann ihn am Ende des Artikels unter dem Namen "RSIAreaIndicatorv1.mq5" herunterladen. Nun kann man mit dem Schreiben des Expert Advisors RSIAreaEA version 1.00 anfangen, der nach der Methode der Flächeninhalte handeln wird.
4. Expert Advisor RSIAreaExpert version 1.00
Auch wie bei der Arbeit mit Indikatoren empfehle ich die erstellten Expert Advisors in einem separaten Ordner abzulegen. Mein Ordner für Expert Advisors heißt z.B. "MyExp". Analog zum Indikator erstellen wir einen Entwurf für den RSIAreaExpert_v1 Expert Advisor. Eine wichtige Anmerkung: auf einem der Schritte muss man alle Häkchen entfernen:
Abb. 7. Einstellungen für die Erstellung des Expert Advisors
Den Entwurf können Sie am Ende des Beitrags finden, der Expert Advisor wurde unter dem Namen "RSIAreaExpert_v1_Step1.mq5" gespeichert.
4.1. Bearbeitung der Kopfzeile des Expert Advisors
Fügen wir die Beschreibung des Expert Advisors hinzu. Sie ist im Allgemeines-Tab des Expert Advisors zu sehen:
#property version "1.00" #property description "EA trades on \"Method areas\"" //+------------------------------------------------------------------+ //| Expert initialization function |
Man hat nicht immer die Lust, die Beschreibung direkt ausfüllen, aber später wird es uns helfen, wenn wir uns an die eiserne Regel halten werden: "Bei der Erstellung eines Programms muss man als allererste eine Beschreibung verfassen".
Der Expert Advisor verwendet die Standardbibliothek (die CTrade Klasse) für die Ausführung von Trades. Dafür müssen wir die CTrade Klasse einfügen und die my_trade Variable deklarieren:
#property description "EA trades on \"Method areas\"" #include <Trade\Trade.mqh> //--- global variables CTrade my_trade; //+------------------------------------------------------------------+ //| Expert initialization function |
Fügen wir drei Variablen hinzu (um den Handle des RSI-Indikators, den aktuellen berechneten Flächeninhalt und eine Hilfsvareable zu speichern):
//--- global variables CTrade my_trade; int handle; // variable for storing the handle of the iRSI indicator double RSIArea; // the calculated area double RSIOpen; // the auxiliary variable //+------------------------------------------------------------------+ //| Expert initialization function |
Der letzte Schritt in der Bearbeitung der Kopfzeile des EAs ist die Input-Parameter hinzuzufügen:
double RSIOpen; // the auxiliary variable //--- input parametres input int ExtRSIPeriod=13; // period of RSI input int AreaCondition=300; // area input ENUM_TIMEFRAMES period=PERIOD_M15; //+------------------------------------------------------------------+ //| Expert initialization function |
Die Variable period wurde nur für ein einfaches Testen im Strategietester eingeführt. So kann man unterschiedliche Testperioden setzen:
Abb. 8. Die period Variable erlaubt den Expert Advisor in unterschiedlichen Perioden zu testen
Die Kopfzeile des Expert Advisors ist ausgefüllt, nun ist die OnInit() Funktion an der Reihe. Die OnInit() Funktion enthält eine einzige Operation, und zwar das Erhalten des Handles des Indikators auf dem laufenden Symbol und in der vorgegebenen Periode (period):
int OnInit() { //--- handle=iRSI(Symbol(),period,ExtRSIPeriod,PRICE_CLOSE); //--- if the handle is not created if(handle==INVALID_HANDLE) { //--- notify about failure and output error code PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d", Symbol(), EnumToString(period), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); }
Diese Änderungen im Prozess der Bearbeitung des Expert Advisors sind in der Datei "RSIAreaExpert_v1_Step2.mq5" zu sehen.
4.2. Hilfsfunktion RSIAreaFunc
Die Funktion der Bestimmung des Flächeninhalts RSIAreaFunc() besteht aus mehreren Teilen. Wir werden das Funktional Schritt für Schritt hinzufügen. Der erste Block (Erläuterungen nach dem Code):
void OnTick() { //--- } //+------------------------------------------------------------------+ //| Area calculation | //+------------------------------------------------------------------+ double RSIAreaFunc(int &RSIAreaShift,int BeginShift) { int shift,limit; double rsivalue,result; //--- get current RSI limit=Bars(Symbol(),period)-ExtRSIPeriod; if(limit>100) limit=100; double arr_rsi[]; ArrayResize(arr_rsi,limit); ArraySetAsSeries(arr_rsi,true); if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1) { Print("CopyBuffer from iRSI failed, no data"); return(0); } return(result); }
Die limit Variable ist dafür zuständig, wie viele Werte des iRSI Indikators wir ins arr_rsi[] Array mithilfe von CopyBuffer kopieren werden. Begrenzen wir die limit Variable durch "100", d.h. wir werden immer die letzten 100 Werte des iRSI-Indikators kopieren. Diese Änderungen des Expert Advisors sind in der Datei "RSIAreaExpert_v1_Step3.mq5" zu sehen.
4.3 Code für das Testen der CopyBuffer Funktion
Wenn es Ihnen nicht ganz klar ist, wie die CopyBuffer Funktion funktioniert und welche Werte das Array mit dem Index "0" enthält, dann kann man einen einfachen Code zur Überprüfung schreiben: schreiben wir den Aufruf der Hilfsfunktion RSIAreaFunc() in OnTick() Funktion.
void OnTick() { //--- static int RSIAreaShift=0; RSIAreaFunc(RSIAreaShift,0); } //+------------------------------------------------------------------+ //| Area calculation | //+------------------------------------------------------------------+ double RSIAreaFunc(int &RSIAreaShift,int BeginShift)
Am Ende des ersten Blocks der RSIAreaFunc() Funktion schreiben wir die Ausgabe des Kommentars — des ersten und des letzten Wertes des arr_rsi[] Arrays:
if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1) { Print("CopyBuffer from iRSI failed, no data"); return(0); } //--- Comment("arr_rsi[",limit-1,"]=",DoubleToString(arr_rsi[limit-1],2), "; arr_rsi[0]=",DoubleToString(arr_rsi[0],2)); return(result); }
Das ist ein Prüfcode, er ist nur in der Datei RSIAreaExpert_v1_Step3_check.mq5, enthalten und im Hauptexperten nicht vorhanden. Für die Überprüfung machen wir das folgende:
- die Datei des Expert Advisors RSIAreaExpert_v1_Step3_check.mq5 kompilieren (wenn man dies noch nicht getan hat);
- neuen Chart eines Symbols öffnen und den Zeitrahmen zu M15 ändern (denn in den Standard-Input-Parameter period=PERIOD_M15);
- den RSI-Indikator auf den Chart einfügen ("Einfügen" -> "Indikatoren" -> "Oszillatoren" -> "Relative Strength Index" mit den Einstellungen: "Periode" 13 und "Anwenden auf" Close);
- den Experten RSIAreaExpert_v1_Step3_check.mq5 einfügen.
Auf dem Chart sieht man sofort, dass der Wert des Elemets mit dem Index "0" im arr_rsi Array dem Wert des RSI-Indikators auf dem Balken ganz rechts entspricht:
Abb. 9. Überprüfung der CopyBuffer Funktion
4.4. Weitere Bearbeitung der Hilfsfunktion
Der nächste Block der RSIAreaFunc() Funktion:
if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1) { Print("CopyBuffer from iRSI failed, no data"); return(0); } result=arr_rsi[0]-50.0; // values from the bar that has 0 index for(shift=BeginShift+1;shift<limit;shift++) { rsivalue=arr_rsi[shift]-50; if((result>0 && rsivalue<-3) || (result<0 && rsivalue>3)) { RSIAreaShift=shift; break; } result+=rsivalue; } return(result); }
Zuerst wird der result Variablen der Wert des RSI-Indikators auf dem ganz rechten Balken minus 50 zugewiesen. Dann folgt der Loop des arr_rsi Arrays, vom Element mit dem Index "1" bis zum Element mit dem Index limit-1. In diesem Loop wird die Bedingung geprüft: "Ob die Nulllinie gekreuzt wurde". Wenn sie sich gekreuzt haben, wird der Index des Balkens (von rechts nach links) in der RSIAreaShift Variablen gespeichert.
4.5. Funktion OnTick() des Expert Advisors
Wir sind mit der Bearbeitung der Hilfsfunktion RSIAreaFunc() fertig. Nun ist die Hauptfunktion OnTick() an der Reihe. Fügen wir der OnTick() den folgenden Code hinzu:
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- static int RSIAreaShift=0; int shift; double RSICurrent,RSILocalMin,RSILocalMax,value; double arr_rsi[1],rsi; MqlTick last_tick; //--- if(CopyBuffer(handle,0,0,1,arr_rsi)==-1) { Print("CopyBuffer from iRSI failed, no data"); return; } rsi=arr_rsi[0]; //--- if(!SymbolInfoTick(Symbol(),last_tick)) Print("SymbolInfoTick() failed, error = ",GetLastError()); //--- }
Mithilfe der bereits bekannten Funktion CopyBuffer erhalten wir den Wert des RSI-Indikators auf dem Balken ganz rechts und weisen diesen Wert der rsi Variablen zu. Ferner werden wir häufig auf diese Variable im Code Bezug nehmen. Dann erhalten wir die laufenden Preise für dieses Symbol und speichern diese in der last_tick Variable.
Der nächste Block des Codes wird unter der Voraussetzung bearbeitet, dass eine offene Position für dieses Symbol vorhanden ist:
if(!SymbolInfoTick(Symbol(),last_tick)) Print("SymbolInfoTick() failed, error = ",GetLastError()); //--- check the conditions for opening a position if(!PositionSelect(Symbol())) { RSIArea=RSIAreaFunc(RSIAreaShift,0); //--- check for a chance to take a long position if(RSIArea<-AreaCondition) { my_trade.Buy(1.0,NULL,last_tick.ask,0.0,0.0,NULL); RSIOpen=rsi; return; } //--- check for a chance to take a short position if(RSIArea>AreaCondition) { my_trade.Sell(1.0,NULL,last_tick.bid,0.0,0.0,NULL); RSIOpen=rsi; return; } RSIAreaShift=0; } //--- } //+------------------------------------------------------------------+ //| Area calculation |
Die Bedingungen für das Eröffnen einer Position werden im Code übergeprüft: wenn der zum jetzigen Zeitpunkt berechnete Flächeninhalt (Variable RSIArea) kleiner/größer als der Input-Parameter (AreaCondition) ist, dann wird eine Buy/Sell Position eröffnete.
Weiter wird der RSICurrent Variablen der Wert der rsi Variablen zugewiesen (Hinweis: in der Variable wurde der Werte des RSI-Indikators auf dem ganz rechten Balken gespeichert) und die Bedingung für die Beendigung der OnTick() Funktion:
- wenn die Position über der Linie "50" (RSIOpen>50) eröffnet wurde und wir momentan über die Linie "50" (RSICurrent>50) sind;
- wenn die Position unter der Linie "50" (RSIOpen<50) eröffnet wurde und wir momentan unter der "50" (RSICurrent<50) sind:
RSIAreaShift=0; } RSICurrent=rsi; if(RSIOpen>50 && RSICurrent>50) return; if(RSIOpen<50 && RSICurrent<50) return; RSILocalMin = RSICurrent; RSILocalMax = RSICurrent; //--- } //+------------------------------------------------------------------+ //| Area calculation |
Der nächste Block des Codes findet lokale Minima und Maxima und weist diese Werte den Variablen RSILocalMin und RSILocalMax zu:
RSILocalMin = RSICurrent; RSILocalMax = RSICurrent; //--- search local minimum/maximum if(RSIAreaShift>1) { double arr_rsi_1[]; ArrayResize(arr_rsi_1,RSIAreaShift); ArraySetAsSeries(arr_rsi_1,true); if(CopyBuffer(handle,0,0,RSIAreaShift,arr_rsi_1)==-1) { Print("CopyBuffer from iRSI failed, no data"); return; } for(shift=1; shift<RSIAreaShift; shift++) { value=arr_rsi_1[shift]; if(value<RSILocalMin && RSIArea>0) RSILocalMin=value; if(value>RSILocalMax && RSIArea<0) RSILocalMax=value; } } //--- } //+------------------------------------------------------------------+ //| Area calculation |
Und schließlich der letzte Block des Codes:
if(value>RSILocalMax && RSIArea<0) RSILocalMax=value; } } //--- check for rollback if(PositionSelect(Symbol())) { if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) { //--- check if it is time for closing if(RSILocalMax>=RSICurrent+4 && RSILocalMax>50) my_trade.PositionClose(Symbol(),20); } if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) { //--- check if it is time for closing if(RSILocalMin<=RSICurrent-4 && RSILocalMin<50) my_trade.PositionClose(Symbol(),20); } } //--- return; } //+------------------------------------------------------------------+ //| Area calculation |
Hier (wenn eine offene Position vorhanden ist) wird die Bedingung für die Schließung nach der folgenden Regel überprüft:
Der RSI-Oszillator durchkreuzt die Linie 50 mit der anschließenden Bildung des lokalen Maximums/Minimums und dem Rollback von 4% der Skala.
Z.B. wenn sich der RSI lange über der Linie 50 befindet, haben wir zu einem Zeitpunkt eine offene SELL-Position. Dann nimmt der Wert des Indikators ab und erreicht, z.B. die Linie 40, dann beginnt der Wert des Indikators zuzunehmen (d.h. das lokale Minimum wird gebildet). Als Signal zum Schließen der Position dient der Moment, in dem der Wert des Indikators die Linie 44 erreicht.
Damit ist die Erstellung von RSIAreaExpert_v1 abgeschlossen. Die Datei "RSIAreaExpert_v1.mq5" kann man am Ende des Beitrags herunterladen.
5. Testen des Expert Advisors RSIAreaExpert version 1.00 für verschiedene Perioden und Symbole
Der RSIAreaExpert Expert Advisor wurde ursprünglich im H1-Chart [1] getestet, aber seit 2004 haben sich Finanzmärkte stark verändert und sind volatiler geworden, aus diesem Grund haben wir uns entschieden, die Funktionsfähigkeit der Methode der Flächeninhalte anhand einer größeren Anzahl an Zeitrahmen - von M10 bis H6 - zu testen. Der Bereich der Flächeninhalte wurde für das Testen erheblich erweitert: von 100 bis 800. Testperiode — von 2015.01.05 bis 2016.01.05.
Testergebnisse des Expert Advisors RSIAreaExpert version 1 für AUDCAD:
Abb. 10. Testergebnisse des Expert Advisors RSIAreaExpert version 1. Symbol AUDCAD. Intervall der Flächeninhalte 100-800. Perioden M10-H6
In der H2-Periode ist eine gute Dichte der Ergebnisse zu sehen. Die H3-Periode kann auch in Betracht gezogen werden. Nun schauen wir uns die Grafik unten an und evaluieren, wie viele Trades auf AUDCAD pro Jahr beim Testen von RSIAreaExpert version 1 ausgeführt wurden:
Abb. 11. Testergebnisse von RSIAreaExpert version 1. Symbol AUDCAD. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Die Anzahl der Trades in den Perioden H2 und H3 schwankt und beläuft sich auf ca.50 Trades. Das ist nicht viel, und die Abweichung ist groß. Daraus ziehen wir die Schlußfolgerung, dass die Methode der Flächeninhalte auf AUDCAD schlecht funktioniert.
Testergebnisse des Expert Advisors RSIAreaExpert version 1 für AUDUSD:
Abb. 12. Testergebnisse von RSIAreaExpert version 1. AUDUSD Symbol. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Wenn es um die Profitabilität der Strategie auf dem AUDUSD Symbol geht, kann man den Handel in H2 und H3 analysieren. In diesen Perioden schwankt der Parameter AreaCondition von 250 bis 400. Um die Zweckmäßigkeit des Handels mit H2 und H3 zu begründen, muss man sich die Anzahl der Trades in diesen Perioden pro Jahr anschauen:
Abb. 13. Testergebnisse von RSIAreaExpert version 1. AUDUSD Symbol. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Wie Sie sehen können, ist ihre Zahl extrem klein. Dies bedeutet, dass es nicht empfehlenswert ist, auf AUDUSD mithilfe der Methode der Flächeninhalte zu handeln.
Testergebnisse von RSIAreaExpert version 1 für EURUSD:
Abb. 14. Testergebnisse des RSIAreaExpert Expert Advisors. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Auf der Abbildung 4 sieht man, dass für die M10-Periode eine 'gute' Dichte der Profit-Ergebnisse beim Schwanken der Flächeninhalte von 400 bis 550, für M12 — von 300 bis 400 und für M15 — von 300 bis 400 zu verzeichnen ist. Höhere Perioden werden nicht in Betracht gezogen, denn die Anzahl an Trades auf diesen Perioden pro Jahr zu klein ist (sieh Abb. 5).
Auf der Abbildung 5 ist ein Diagramm zu sehen, das die Abhängigkeit zwischen der Anzahl an Trades und dem Profit für EURUSD darstellt:
Abb. 15. Testergebnisse des RSIAreaExpert Expert Advisors. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Hier sieht man, dass die Anzahl an Trades auf höheren Perioden (von H1 bis H6) sehr klein ist, und somit die Anwendung der Methode auf solchen Perioden in Frage stellt. Die Anzahl an Trades in M10, M12 und M15 spricht hingegen für die Anwendung der Methode der Flächeninhalte in diesen Zeitrahmen. Das Symbol EURUSD passt ganz sicher für den Handel nach der Methode der Flächeninhalte.
Testergebnisse des Expert Advisors RSIAreaExpert version 1 für GBPUSD:
Abb. 16. Testergebnisse von RSIAreaExpert version 1. GBPUSD Symbol. Intervall der Flächeninhalte 100-800. Perioden M10-H6
GBPUSD weist eine gute Dichte der profitablen Trades in M20 auf. Der AreaCondition Parameter variiert von 300 bis 500.
Abb. 17. Testergebnisse von RSIAreaExpert version 1. GBPUSD Symbol. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Für GBPUSD mit der Periode M20 beläuft sich die Anzahl an Trades von 140 bis 250 für das ganze Jahr. Das ist natürlich kein fantastischer Wert, man kann ihn sich trotzdem merken. Mit anderen Worten ist der Handel mithilfe der Methode der Flächeninhalte auf GBPUSD nicht für jedermann.
Testergebnisse des Expert Advisors RSIAreaExpert version 1 für USDCAD:
Abb. 18. Testergebnisse von RSIAreaExpert version 1. USDCAD Symbol. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Für USDCAD würde ich nur M30 in Betracht ziehen, denn nur diese Periode weist Profite auf. Dabei ändert sich der AreaCondition Parameter von 280 bis 550.
Abb. 19. Testergebnisse von RSIAreaExpert version 1. USDCAD Symbol. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Die Anzahl an Trades variiert auf diesem Währungspaar mit dem Zeitrahmen M30 pro Jahr von 90 bis 200. Das ist nicht viel, aus diesem Grund würde ich die Methode der Flächeninhalte für USDCAD nicht empfehlen.
Testergebnisse des Expert Advisors RSIAreaExpert version 1 für USDJPY:
Abb. 20. Testergebnisse von RSIAreaExpert version 1. USDJPY Symbol. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Zwei Perioden auf dem USDJPY Symbol: M10 und M30. Der AreaCondition Parameter für M10 liegt zwischen 320 und 650, für M30 — zwischen 550 und 600.
Abb. 21. Testergebnisse von RSIAreaExpert version 1. USDJPY Symbol. Intervall der Flächeninhalte 100-800. Perioden M10-H6
Für USDJPY variiert die Anzahl der Trades für die M10 Periode nach der Methode der Flächeninhalte pro Jahr von 150 bis 200, und für die Periode M30 von 50 bis 150. Wir sehen, dass die Empfehlungen für das Trading auch ziemlich unklar sind.
Fazit
Es ist noch nicht die Zeit, den Handel nach der Methode der Flächeninhalte zu außer Acht zu lassen. Unter aktuellen Bedingungen auf dem Markt zeigte das System Verluste im Zeitrahmen H1, obwohl früher [1] der Hauptprofit gerade in diesem Zeitrahmen erzielt wurde. Der Handel nach der Methode der Flächeninhalte hat sich auf dem Symbol EURUSD in den Zeitrahmen M10, M12 und M15 als besonders erfolgreich erwiesen. Das Testen gerade auf diesem Währungspaar und in diesen Zeitrahmen hat eine ausreichende Anzahl an Trades pro Jahr gezeigt.
Literaturverzeichnis
- I.V. Morosov., R.R. Fatkhullin. FOREX: from simple to compex. New opportunities of MetaTrader client terminal. - M: Teletrade Ltd, 2004. - 448 S.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/2249
- 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.