Liquid-Chart

13 Juni 2016, 10:40
Serhii Shevchuk
0
356

Einleitung

Ich habe einmal bemerkt, dass Charts mit einem H4-Zeitrahmen und höher bei jedem Broker anders aussehen. Der Grund: Die Broker befinden sich in verschiedenen Zeitzonen. In einigen Fällen waren Teile der Charts sehr verschieden, trotz nahezu identischer Zeitzonen. Auf einem Chart gab es einmal ein ausgeprägtes Reversal-Muster und auf dem anderen repräsentierte derselbe Teil kein spezifisches Muster.

Und dann fiel es mir wie Schuppen von den Augen: Ich schreibe einen Indikator, der den H1-Chart neu zeichnet, damit sich auf der rechten Seite immer ein vollständiger Schließungsbalken befindet. Dabei wählte ich die Periode M1 als Quelle des Preises. Und das Ergebnis: Jede Minute wurde ein stündlicher Chart gezeichnet, wodurch ich nach einer Stunde 60 Variationen des selben stündlichen Charts in den Händen hielt. Dessen Form änderte sich auf glatte und fließende Weise, wodurch unsichtbare Muster sichtbar wurden - Muster, auf deren Existenz sich seitens des Ursprungsmusters keinerlei Hinweise finden ließen.

Ich habe diesen Indikator daraufhin „Liquid-Chart“ getauft, um seiner sehr speziellen Erscheinungsform Rechnung zu tragen. Abhängig vom Modus des Zeichnens wird der Chart „fließen“ (es erfolgt ein Neuentwurf), wenn entweder einer neuer Balken der Grundperiode erscheint oder aber wenn der statische Shiftwert geändert wird. In diesem Artikel werden wir uns ein wenig die Prinzipien des Zeichnens von „Liquid-Charts“ genauer ansehen, daraufhin einen Indikator schreiben und die Effektivität folgender beider Methoden vergleichen: die Anwendung dieser Technologie für EA-Trading mittels Indikatoren und mittels Muster.



1. Prinzipien des Zeichnens

Bevor wir beginnen, müssen wir zunächst einige Termini definieren.

Shift soll die Differenz zwischen den Öffnungspreisen der resultierenden Chartbalken und den Öffnungspreisen des Balken des Ursprungcharts sein.

Aktueller Zeitrahmen ist der Zeitrahmen des ursprünglichen Charts.

Grundzeitrahmen ist ein Zeitrahmen mit Preisen, die wir zur Formung der Balken des resultierenden Charts benötigen.

Die Grund- bzw. Ursprungsperiode kann die aktuelle nicht überschreiten. Ferner muss die aktuelle Periode durch die Grundperiode ohne einen entstehenden Rest teilbar sein. Je größer das Verhältnis zwischen aktuellem Zeitrahmen und Grundzeitrahmen, desto mehr verschiedene Variationen des resultierenden Charts können wir erhalten. Wenn allerdings das Verhältnis zu groß wird, könnten die historischen Daten des Grundzeitrahmens nicht mehr länger ausreichend sein, um die notwendige Zahl der Balken des resultierenden Charts zu zeichnen.

Es gibt drei Arten des Zeichnens eines Charts:

  • Charts mit statischem Shift (auch: Static Shift oder SS).
  • Charts mit dynamischem Shift im Öffnungsmodus (auch: Dynamic Shift, just Open oder DSO).
  • Charts mit dynamischem Shift im Schließungsmodus (auch: Dynamic Shift, expected Close oder DSC).

Im statischen Shiftmodus verschieben sich die Öffnungszeiten von Balken um die eingestellte Zeit. Ein dynamischer Shift führt dazu, dass ein Balken im Öffnungsmodus so aussieht, als sei er gerade geöffnet worden, und im Schließungsmodus so aussieht, als ob er bald geschlossen werden wird.

Sehen wir uns das Ganze ein wenig genauer an.


1.1 Charts mit statischem Shift

Bei dieser Methode wird die Öffnungszeit jedes Balkens durch genau die Anzahl an Minuten verändert, die der eingestellten Zahl des Grundzeitrahmens entspricht. Wir nennen diese Veränderung einen Shift. Falls der eingestellte Shift null beträgt, dann ist der Chart mit dem ursprünglichen absolut identisch. Shift 1 ist gleichbedeutend mit 15 Minuten - vorausgesetzt dass der Grundzeitrahmen 15 Minuten entspricht. Shift 2 ist dann gleichbedeutend mit 30 Minuten und immer so weiter.

Der Shift kann (k-1) nicht überschritten, wobei k das Verhältnis zwischen aktuellem Zeitrahmen und Grundzeitrahmen darstellt. Das bedeutet, dass mit dem aktuellen Zeitrahmen H1 und dem Grundzeitrahmen M1 der maximale, zulässige Shift 60/1 - 1 = 59 der Grundzeitrahmen beträgt, also 59 Minuten. Falls der Grundzeitrahmen M5 sein sollte, dann ist der maximale, zulässige Shift 60/5 - 1 = 11 der Grundzeitrahmen, also 55 Minuten.

Die Öffnungszeit der Balken des aktuellen Zeitrahmens H1 und des Shifts von 15 Minuten ist 00:15, 01:15, 02:15 und immer so weiter. Für den aktuellen Zeitrahmen M15 und den Shift von 1 Minute ist die Öffnungszeit wiederum 00:16, 00:31, 00:46, 01:01 und so weiter und so fort.

Wenn Shifts sehr nahe an den Limitwerten liegen sollten, dann ist solch ein Chart kaum vom Ursprungschart zu unterschieden. Signifikante Unterschiede treten immer dann auf, wenn ein Shiftwert der Mitte eines zulässigen Bereichs sehr nahe ist.

Chart mit statischem Shift

Abb. 1 Beispiele für stündliche Balkenformierungen für einen Grundzeitrahmen von M15 mit einem Shift, der gleich 1 ist


1.2 Charts mit dynamischem Shift im Öffnungsmodus

In diesem Modus wird der Shift jedes Mal neu berechnet, wenn ein neuer Balken im Grundzeitrahmen erscheint. Zur gleichen Zeit gilt: Der Shift wird genau so kalkuliert, dass die Zeit, für die der Balken am Ende des Charts (letzter Preis) existiert, niemals den Wert des Grundzeitrahmens übersteigt. Falls der aktuelle Zeitrahmen H1 und der Grundzeitrahmen M5 sein sollte, dann wird es so aussehen, als ob der äußerste rechte Balken vor nicht weniger als 5 Minuten geöffnet worden ist.

Chart mit dynamischem Shift, Anfang des Balkens

Abb. 2 Beispiele für stündliche Balkenformierungen für einen Grundzeitrahmen von M15 mit einem dynamischen Shift im Öffnungsmodus


1.3 Charts mit dynamischem Shift im Schließungsmodus

In diesem Modus wird der Shift jedes Mal neu berechnet, wenn ein neuer Balken im Grundzeitrahmen erscheint, genauso wie im Öffnungsmodus. Der einzige Unterschied besteht darin, dass der Shift derart vonstattengeht, als dass die Zeit, für die der Balken am Ende des Charts (letzter Preis) existiert, größer als die Differenz zwischen aktuellem Zeitrahmen und Grundzeitrahmen ist oder dieser genau entspricht. Was den aktuellen Zeitrahmen von H1 und den Grundzeitrahmen von M5 betrifft, so sieht es so aus, als ob der äußerste rechte Balken in nicht mehr als 5 Minuten geschlossen werden wird.

Chart mit dynamischem Shift, vollständige Balken

Abb. 3 Beispiele für stündliche Balkenformierungen für einen Grundzeitrahmen von M15 mit einem dynamischen Shift im Öffnungsmodus


2. Datentransformation

Die Funktion GetRatesLC() wurde speziell dafür geschrieben, historische Daten unter Berücksichtigung eines eingestellten Shifts zu konvertieren. Sie schreibt modifizierte, historische Daten in das Array von Strukturen des Typs MqlRates, ähnlich so wie die Funktion CopyRates().

int GetRatesLC(
   int             start_pos    // source for copying
   int             len,         // amount to copy
   MqlRates&       rates[],     // target array
   ENUM_TIMEFRAMES base_period, // basic timeframe
   int&            shift        // shift
   );

Parameter

  start_pos

   [in]  Index des ersten Elements des aktuellen Zeitrahmens. Dies ist der Startpunkt der Datenkonvertierung und des Kopierens in den Puffer.

  len

   [in]  Zahl der kopierten Elemente.

  rates[]

   [out]  Array des Typs MqlRates.

  base_period

   [in]  Grundzeitrahmen. 

  shift

   [in] [out] Shift. Hier können folgende Werte angenommen werden:

WertBeschreibung
 -2
 Kalkulation des Shifts im Öffnungsmodus (Beginn der Balkenbildung)
 -1
 Kalkulation des Shifts im Schließungsmodus (Ende der Balkenbildung)
 0 ... N
 Wenden Sie den eingestellten Shift an. Kann Werte von 0 bis N akzeptieren.
 N = Tcur/Tbase - 1. Wobei Tcur den aktuellen Zeitrahmen und Tbase den Grundzeitrahmen verkörpert.

Tabelle 1. Zulässige Werte des Shiftparameters

Wenn die Funktion erfolgreich umgesetzt wird, wird Shift den Wert des kalkulierten Shifts empfangen, falls die Werte -2 oder -1 passiert wurden.

Gelieferter Wert

Zahl der kopierten Elemente oder des Fehlercodes:

CodeBeschreibung
 -1
 Grundzeitrahmen nicht korrekt spezifiziert
 -2
 Shift nicht korrekt spezifiziert

Tabelle 2. Zurückgegebene Fehlercodes

Nachfolgend sehen sie den Code der Funktion GetRatesLC() der Datei liquidchart.mqh.

int GetRatesLC(int start_pos,int len,MqlRates &rates[],ENUM_TIMEFRAMES base_period,int& shift)
  {
   //--- number of basic timeframes contained in the current one  
   int k=PeriodSeconds()/PeriodSeconds(base_period);
   if(k==0)
      return(-1);//basic timeframe specified incorrectly
   //---
   MqlRates r0[];
   ArrayResize(rates,len);
   if(CopyRates(_Symbol,_Period,start_pos,1,r0)<1)
      return(0);// no data
   //---
   int sh;
   if(shift>=0)
     {
      //--- fixed shift
      if(shift<k)
         sh=shift;
      else
         return(-2);//--- shift specified incorrectly   
     }
   else if(shift==-1)
     {
      //--- shift to be calculated (dynamic, beginning of the bar formation)
      sh=int((TimeCurrent()-r0[0].time)/PeriodSeconds(base_period));
     }
   else if(shift==-2)
     {
      //--- shift to be calculated (dynamic, end of the bar formation)
      sh=1+int((TimeCurrent()-r0[0].time)/PeriodSeconds(base_period));
      if(sh>=k)
         sh = 0;
     }
   else
      return(-2);//shift specified incorrectly       
   //--- opening time of the basic period bar, which is the beginning of the current period bar formation
   //--- synchronization of the time of opening bars takes place relative to the tO time
   datetime tO;
   //--- closing time of the bar under formation, i.e. opening time of the last bar of basic timeframe in the series
   datetime tC;
   tO=r0[0].time+sh*PeriodSeconds(base_period);
   if(tO>TimeCurrent())
      tO-=PeriodSeconds();
   tC=tO+PeriodSeconds()-PeriodSeconds(base_period);
   if(tC>TimeCurrent())
      tC=TimeCurrent();
   int cnt=0;
   while(cnt<len)
     {
      ArrayFree(r0);
      int l=CopyRates(_Symbol,base_period,tC,k,r0);
      if(l<1)
         break;
      //--- time of the bar with the (l-1) index does not have to be equal to tC
      //--- if there is no bar with the tC time, it can be the nearest bar
      //--- in any case its time is assigned to the tC time
      tC=r0[l-1].time;
      //--- check if tO has the correct value and modify if needed.
      while(tO>tC)
         tO-=PeriodSeconds();
      //--- the time values of tO and tC have actual meaning for the bar under formation  
      int index=len-1-cnt;
      rates[index].close=0;
      rates[index].open=0;
      rates[index].high=0;
      rates[index].low=0;
      rates[index].time=tO;
      for(int i=0; i<l; i++)
         if(r0[i].time>=tO && r0[i].time<=tC)
           {
            if(rates[index].open==0)
              {
               rates[index].open= r0[i].open;
               rates[index].low = r0[i].low;
               rates[index].high= r0[i].high;
                 }else{
               if(rates[index].low > r0[i].low)
                  rates[index].low=r0[i].low;
               if(rates[index].high < r0[i].high)
                  rates[index].high=r0[i].high;
              }
            rates[index].close=r0[i].close;
           }
      //--- specifying closing time of the next bar in the loop
      tC=tO-PeriodSeconds(base_period);
      //
      cnt++;
     }
   if(cnt<len)
     {
      //-- less data than required, move to the beginning of the buffer
      int d=len-cnt;
      for(int j=0; j<cnt; j++)
         rates[j]=rates[j+d];
      for(int j=cnt;j<len;j++)
        {
         //--- fill unused array elements with zeros
         rates[j].close=0;
         rates[j].open=0;
         rates[j].high=0;
         rates[j].low=0;
         rates[j].time=0;
        }
     }
   shift = sh;  
   return(cnt);
  }

An dieser Stelle sollten einige wichtige Punkte hervorgehoben werden.

  • Die Funktion gibt keine Tickvolumen zurück. Der Grund hierfür ist der, dass die Funktion im DSC-Modus niemals Volumen zurückgibt, die mit dem Balkenöffnung identisch sind. Eigentlich logisch, nicht wahr? Falls Ihr EA ein Tickvolumen verwendet, das einem entspricht, das ein Signal zur Formierung eines neuen Balkens darstellt, so wird er das Signal empfangen. Diese Methode wird bei Gleitenden-Durchschnitts- als Moving-Average-EAs angewendet. Sie können natürlich auch einen Zähler für das Tickvolumen zur Funktion hinzufügen. Allerdings würde das nicht richtig funktionieren. Um an dieser Stelle Missverständnisse zu vermeiden: Ich selbst führe keine Messung des Tickvolumens durch.
  • Die Funktion gibt zwar die angeforderte Zahl der Balken wieder aus, das bedeutet jedoch nicht, dass die Zeit zwischen dem ersten und dem letzten Balken dem korrespondierenden Zeitintervall des ursprünglichen Charts entspricht. Allerdings gibt es eine Übereinstimmung im Falle eines kontinuierlichen Segments historischer Daten. Falls das spezifizierte Segment Wochenenden enthalten sollte, könnten sich an der Grenzlinie sogenannte „Phantombalken“ bilden.

Die untere Abbildung stellt ein Beispiel für einen derartigen „Phantombalken“ dar. Der Balken wurde für die erste Minute des 27. Oktobers gebildet, die sich zusammen mit der Öffnungszeit 23:01 (26. Oktober) im Balken wiederfindet. Ich verweise darauf, dass sich nach derartigen Balken der Chart des Indikators nach links verschieben wird (in Relation zum ursprünglichen Chart. Die Balken, die eine Zeit aufweisen, die mit der Anfangszeit korrespondiert (z.B. 21:00 -> 21:01), werden andere Indexe aufweisen.

Phantombalken

Abb. 4 Phantombalken vom 26.10.2014, 23:01



3. Indikatorumsetzung

Lassen Sie uns einen Indikator schreiben, der einen Liquid-Chart in einem separaten Fenster anzeigt. Der Indikator sollte in allen drei Modi funktionieren: im statischen Shiftmodus, im dynamischen Shift im Balkenöffnungsmodus und im dynamischen Shift im Balkenschließungsmodus. Der Indikator muss Kontrollelemente zum Ändern des Modus und des Shiftwerts aufweisen, ohne dass die Notwendigkeit besteht, den Indikatorparameterdialog aufzurufen.

Für den Anfang wollen wir die Funktion GetRatesLC() der Datei liquidchart.mqh benutzen. Wir werden Sie von der Funktion RefreshBuffers() aufrufen, die ihrerseits von der Funktion OnCalculate aufgerufen wird. Sie könnte ferner durch OnChartEvent aufgerufen werden, allerdings sind hierfür einige Änderungen im Modus oder dem Shift & eine Neukalkulation der Indikatorpuffer notwendig. Die Funktion OnChartEvent wird das Knopfdrücken sowie die Veränderung der Shiftwerte und des Modus verarbeiten.

Eingangsparameter des Indikators:

input ENUM_TIMEFRAMES   BaseTF=PERIOD_M1;       // LC Base Period
input int               Depth=100;              // Depth, bars
input ENUM_LC_MODE      inp_LC_mode=LC_MODE_SS; // LC mode
input int               inp_LC_shift=0;         // LC shift

wobei Tiefe die Zahl der Balken des resultierenden Charts und ENUM_LC_MODE den Typ darstellt, der die Modi zum Zeichnen des Indikators beschreibt.

enum ENUM_LC_MODE
  {//plotting mode
   LC_MODE_SS=0,  // Static Shift
   LC_MODE_DSO=1, // Dynamic Shift, just Open
   LC_MODE_DSC=2  // Dynamic Shift, expected Close
  };
Die beiden Parameter inp_LC_mode und inp_LC_shift werden durch LC_mode und LC_shift entsprechend dupliziert. Dieses Design erlaubt eine Änderung ihrer Werte durch das Drücken eines Buttons. Das Ziehen von Buttons als auch die Behandlung des Drückens von Buttons werden dabei nicht berücksichtigt werden, da sie nicht zum Thema dieses Artikels gehören. Wenden wir uns der RefreshBuffers()-Funktion im Detail zu.
bool RefreshBuffers(int total,
                    double &buff1[],
                    double &buff2[],
                    double &buff3[],
                    double &buff4[],
                    double &col_buffer[])
  {
   MqlRates rates[];
   ArrayResize(rates,Depth);
//---
   int copied=0;
   int shift=0;
   if(LC_mode==LC_MODE_SS)
      shift = LC_shift; //static shift
   else if(LC_mode==LC_MODE_DSO)
      shift = -1;       //calculate shift (beginning of the bar formation)
   else if(LC_mode==LC_MODE_DSC)
      shift = -2;       //calculate shift (end of the bar formation)
   else
      return(false);
//---
   copied=GetRatesLC(0,Depth,rates,BaseTF,shift);
//---
   if(copied<=0)
     {
      Print("No data");
      return(false);
     }
   LC_shift = shift;
   refr_keys();
//--- initialize buffers with empty values
   ArrayInitialize(buff1,0.0);
   ArrayInitialize(buff2,0.0);
   ArrayInitialize(buff3,0.0);
   ArrayInitialize(buff4,0.0);
//---
   int buffer_index=total-copied;
   for(int i=0;i<copied;i++)
     {
      buff1[buffer_index]=rates[i].open;
      buff2[buffer_index]=rates[i].high;
      buff3[buffer_index]=rates[i].low;
      buff4[buffer_index]=rates[i].close;
      //---
      if(rates[i].open<=rates[i].close)
         col_buffer[buffer_index]=1;//bullish or doji
      else
         col_buffer[buffer_index]=0;//bearish
      //
      buffer_index++;
     }
//
   return(true);
  }

Zunächst muss ein relevanter Wert der Shift-Variable an die Funktion GetRatesLC() weitergereicht werden - d.h., abhängig vom Modus. Im statischen Modus wird es sich um eine Kopie des Parameters LC_shift und im Falle des Öffnungs- bzw. Schließungsmodus des Balkens um -1 bzw. -2 handeln. Nach einer erfolgreichen Ausführung der Funktion wird GetRatesLC() den aktuellen Wert von Shift an die Shift-Variable zurückgeben. Dabei erfolgt entweder eine Neukalkulation oder er bleibt so, wie er ist. Wie dem auch sei, wir werden der Variable LC_shift den Wert zuweisen und dann ein erneutes Zeichnen der grafischen Elemente durch die Funktion refr_keys() aufrufen.

Danach erneuern wir die OHLC-Werte und die Balkenfarben in den Indikatorpuffern.

Der vollständige Code des Indikators befindet sich in der Datei liquid_chart.mq5. Nach der Ausführung sieht der Indikator wie folgt aus:

Der Liquid-Chart-Indikator, Shift 0

Abb. 5 Der Liquid-Chart-Indikator

Einige wenige Worte über die die Kontrollelemente

  • Der Button SS veranlasst den Indikator dazu, in den statischen Shiftmodus zu wechseln. In diesem Modus sind Buttons mit Pfeilen aktiv, die dazu benutzt werden können, um den benötigten Shiftwert einzustellen.
  • Der DSO-Button veranlasst den Indikator in den dynamischen Shiftmodus zu wechseln. Dies stellt den Beginn der Balkenbildung dar. In diesem Modus wird der Shiftwert kalkuliert und kann nicht per Hand modifiziert werden.
  • Der DSC-Button veranlasst den Indikator in den dynamischen Shiftmodus zu wechseln. Dies stellt das Ende der Balkenbildung dar. In diesem Modus ist die manuelle Veränderung bzw. Modifizierung von Shift ebenfalls untersagt.

Im SS-Modus dupliziert der Indikator den Wert des Initialcharts, falls der Shiftwert gleich 0 ist. Wenn Sie Shift verändern, werden Sie sehen, wie der Chart neu gezeichnet wird. Ein auffälliger Unterschied erscheint dabei bereits beim Wert 28. Anstelle schwächlicher „Gleise“ gibt es nun einen ausgeprägten „Hammer“. Ist die Zeit zum Kaufen gekommen?

Der Liquid-Chart-Indikator, Shift 28

Abb. 6 Der Liquid-Chart-Indikator, Shift 28

Wenn Sie den Indikator in den DSO-Modus versetzen, werden Sie einen neu gebildete Balken stets auf der rechten Seite finden. Im DSC-Modus wird sich ein Balken in nicht mehr als dem Wert eines Grundzeitrahmens schließen.


4. Kreieren eines EAs

Wir werden insgesamt zwei Expert-Advisors generieren. Der erste wird mit einem gleitenden Durchschnittswert (Moving-Average) und der zweite mit einem „Pin-Bar“-Muster traden.

Lassen Sie uns den Moving-Average-EA aus dem Beispielordner (Experts\Examples\Moving Average) als Template verwenden. Auf diese Weise wird es uns möglich sein, die Optimierungsresultate zweier grundverschiedener Strategien zu verstehen - wenn der statische und der dynamische Shift relevant und von Bedeutung sind.


4.1 Expert-Trading mithilfe eines Moving-Averages

Zunächst müssen die Eingabeparameter definiert werden. Es gibt derer vier:

input double MaximumRisk    = 0.1// Maximum Risk in percentage
input double DecreaseFactor = 3;    // Decrease factor
input int    MovingPeriod   = 12;   // Moving Average period
input int    MovingShift    = 6;    // Moving Average shift

Drei weitere Parameter werden nach der Modernisierung hinzugefügt werden:

input ENUM_TIMEFRAMES  BaseTF=PERIOD_M1;  // LC Base Period
input bool             LC_on = true;      // LC mode ON
input int              LC_shift = 0;      // LC shift

Der LC_on Parameter wird sich bei Überprüfungen der korrekten Arbeitsweise von GetRatesLC() als nützlich erweisen. Die Kombination (LC_on == true && LC_shift == 0) muss dieselben Resultate wie (LC_on == false) aufweisen.

Zur Modernisierung des Moving-Average-Expert-Advisors samt Shift muss die Datei liquidchart.mqh involviert und die Funktionen CopyRates() durch die Funktionen GetRatesLC() ersetzt werden - und zwar für all jene Fälle, in denen das Shiftfeature aktiviert ist (d.h., der Eingabeparameter LC_on wahr ist):

   int copied;
   if(LC_on==true)
     {
      int shift = LC_shift;
      copied=GetRatesLC(0,2,rt,BaseTF,shift);
     }
   else
      copied = CopyRates(_Symbol,_Period,0,2,rt);
   if(copied!=2)
     {
      Print("CopyRates of ",_Symbol," failed, no history");
      return;
     }

Dies muss in beiden Funktionen, CheckForOpen() und CheckForClose(), durchgeführt werden. Wir müssen an dieser Stelle davon absehen, Indikatorbehandler zu verwenden, und werden die Moving-Averages stattdessen manuell kalkulieren. Genau hierfür haben wir die Funktion CopyMABuffer() hinzugefügt:

int CopyMABuffer(int len,double &ma[])
  {
   if(len<=0)
      return(0);
   MqlRates rates[];
   int l=len-1+MovingPeriod;
   int copied;
   if(LC_on==true)
     {
      int shift = LC_shift;
      ArrayResize(rates,l);
      copied=GetRatesLC(MovingShift,l,rates,BaseTF,shift);
     }
   else
      copied=CopyRates(_Symbol,_Period,MovingShift,l,rates);
//      
   if(copied<l)
      return(0);
//
   for(int i=0;i<len;i++)
     {
      double sum=0;
      for(int j=0;j<MovingPeriod;j++)
        {
         if(LC_on==true)
            sum+=rates[j+i].close;
         else
            sum+=rates[copied-1-j-i].close;
        }
      ma[i]=sum/MovingPeriod;
     }
   return(len);
  }

Sie gibt eine benötigte Zahl an Werten (oder 0) in den Puffer ma[] zurück, falls diese aus irgendeinem Grunde nicht erhalten worden sein sollten.

Die Kontrolle über das Öffnen von Balken ist ein weiterer wichtiger Punkt, den es zu bedenken gilt. In der Originalversion des Moving-Average-EAs wurde diese mithilfe von Tickwerten umgesetzt:

   if(rt[1].tick_volume>1)
      return;

In unserem Fall gibt es keine Tickvolumina. Folglich müssen wir die Funktion newbar() schreiben, um die Öffnung von Balken zu kontrollieren.

bool newbar(datetime t)
  {
   static datetime t_prev=0;
   if(t!=t_prev)
     {
      t_prev=t;
      return(true);
     }
   return(false);
  }

Das Operationsprinzip besteht dabei darin, die Öffnungszeit des Balkens mit seinem vorherigem Wert zu vergleichen. Lassen Sie uns die Überprüfung des Tickvolumens durch den Aufruf der Funktion newbar() in den Funktionen CheckForOpen() und CheckForClose() substituieren:

   if(newbar(rt[1].time)==false)
      return;

Den vollständigen Code des EAs finden Sie in der Datei moving_average_lc.mq5.


4.2 Expert-Advisor-Trading mittels eines „Pin-Bar“-Musters

Pin-Bar oder Pinocchio-Bar ist ein Muster, das aus drei Balken besteht. Der mittlere Balken muss einen langen Schatten bzw. eine lange „Nase“ aufweisen, wodurch eine wahrscheinliche Umkehrung der Kursbewegung kenntlich gemacht wird. Die Balken an der Seite werden auch als „Augen“ bezeichnet. Ihre Extrempunkte sollten nie außerhalb des Schattens des benachbarten Balkens anzutreffen sein. Das Muster ist vor allem bei Tradern beliebt, die mit Kerzenmodellen hantieren.

Unser Pin-Bar muss die folgenden Bedingungen einer nach unten gerichteten Preisumkehrung erfüllen:

  • Der r[0]-Balken muss ein Bulle sein.
  • Der r[2]-Balken muss ein Bär sein.
  • Der höchste Wert des Preises A und C sollte nicht B überschreiten, wobei A und C die Hoch-Werte der Balken r[0] und r[2] sind. B ist der Hoch-Preis des Balkens r[1].
  • Der Körper des mittleren Balkens, das heißt, der Modulunterschied zwischen Öffnen/Open und Schließen/Close (OC in der Figur) des Balkens r[1] sollte nicht die Zahl der externen Parameterpunkte übersteigen.
  • Der Schatten des mittleren Balkens, oder die Differenz des Hoch-Preises und der größten Werte von Open und Close des r[1]-Balkens, sollte nicht kleiner sein als die Anzahl der der externen Parameterpunkte.
  • Das Verhältnis des Schattens des mittleren Balkens zu dessen Körper sollte nicht weniger als die Anzahl der externen Parameterpunkte betragen.

Die Überprüfung des Musters wird zur selben Zeit wie das Öffnen des Balkens r[3] ausgeführt.

Pin-Bar

Abb. 7 Das „Pin-Bar“-Muster

Der Code, der die Präsenz eines Pin-Bars für eine nach unten gerichtete Umkehrung definiert, sollte wie folgt aussehen:

   if(r[0].open<r[0].close && r[2].open>r[2].close && r[1].high>MathMax(r[0].high,r[2].high))
     {
     //--- eyes of the upper pin bar
      double oc=MathAbs(r[1].open-r[1].close)/_Point;
      if(oc>inp_pb_max_OC)
         return(0);
      double shdw=(r[1].high-MathMax(r[1].open,r[1].close))/_Point;
      if(shdw<inp_pb_min_shdw)
         return(0);
      if(oc!=0)
        {
         if((shdw/oc)<inp_pb_min_ratio)
            return(0);
        }
      return(1);
     }

Und hier für eine nach oben gerichtete Umkehrung. Die Funktion zur Überprüfung der Präsenz des Pin-Bars müsste folgendermaßen aussehen:

int IsPinbar(MqlRates &r[])
  {
   //--- there must be 4 values in the r[] array
   if(ArraySize(r)<4)
      return(0);
   if(r[0].open<r[0].close && r[2].open>r[2].close && r[1].high>MathMax(r[0].high,r[2].high))
     {
      //--- eyes of the upper pin bar
      double oc=MathAbs(r[1].open-r[1].close)/_Point;
      if(oc>inp_pb_max_OC)
         return(0);
      double shdw=(r[1].high-MathMax(r[1].open,r[1].close))/_Point;
      if(shdw<inp_pb_min_shdw)
         return(0);
      if(oc!=0)
        {
         if((shdw/oc)<inp_pb_min_ratio)
            return(0);
        }
      return(1);
     }
   else if(r[0].open>r[0].close && r[2].open<r[2].close && r[1].low<MathMin(r[0].low,r[2].low))
     {
      //--- eyes of the lower pin bar
      double oc=MathAbs(r[1].open-r[1].close)/_Point;
      if(oc>inp_pb_max_OC)
         return(0);
      double shdw=(MathMin(r[1].open,r[1].close)-r[1].low)/_Point;
      if(shdw<inp_pb_min_shdw)
         return(0);
      if(oc!=0)
        {
         if((shdw/oc)<inp_pb_min_ratio)
            return(0);
        }
      return(-1);
     }
   return(0);
  }

Das durchlaufene Array mit den historischen Daten sollte nicht weniger als vier Elemente aufweisen. Falls der obere Pin-Bar entdeckt wird (wenn der Pin-Bar auf die nach unten gerichtete Umkehrung verweist), wird die Funktion den Wert 1 zurückgeben. Falls es einen niedrigeren Pin-Bar gibt (wahrscheinlich samt nach oben gerichteter Umkehrung), wird die Funktion den Wert -1 ausgeben. Wenn es gar keine Pin-Bars gibt, so gibt die Funktion den Wert 0 wieder aus. Die Funktion wird außerdem die folgenden Eingabeparameter verwenden:

input uint   inp_pb_min_shdw     = 40;    // Pin bar min shadow, point
input uint   inp_pb_max_OC       = 20;    // Pin bar max OC, point
input double inp_pb_min_ratio    = 2.0;   // Pin bar shadow to OC min ratio

Wir werden mit der simpelsten Handelsstrategie samt Pin-Bar traden. Wir werden verkaufen, wenn wir eine nach unten gerichtete Umkehrung erwarten, und kaufen, wenn wir eine nach oben gerichtete Umkehrung erwarten. Normalerweise sind Indikatorbestätigungen von Nöten. Wir können allerdings dieses eine Mal auf sie verzichten. Ferner werden wir nur einen Pin-Bar verwenden.

Der EA , der mit dem „Pin-Bar“-Muster tradet wird auf Expert-Traiding via Moving-Average basieren. Die Funktion CopyMABuffer() muss ebenso wie ihr Aufruf durch die beiden Funktionen CheckForOpen() und CheckForClose() von Letztgenanntem entfernt werden. Auch muss die Zahl der erforderlichen Historiendaten von zwei auf vier erhöht werden. Die Zeit des r[3]-Balkens wird während der Überprüfung der Öffnung des neuen Balkens verwendet werden.

   int copied;
   if(LC_on==true)
   {
      int shift = LC_shift;
      copied=GetRatesLC(0,4,rt,BaseTF,shift);
   }
   else
      copied = CopyRates(_Symbol,_Period,0,4,rt);
   if(copied!=4)
     {
      Print("CopyRates of ",_Symbol," failed, no history");
      return;
     }
   if(newbar(rt[3].time)==false)
      return;

Die Überprüfung der Positionsöffnung wird dabei wie folgt aussehen:

   int pb=IsPinbar(rt);
   if(pb==1)       // upper pin bar
      signal=ORDER_TYPE_SELL; // sell conditions
   else if(pb==-1) // lower pin bar
      signal=ORDER_TYPE_BUY// buy conditions

Um eine Position mittels eines gegensätzlichen Pin-Bars zu schließen:

   if(type==(long)POSITION_TYPE_BUY && pb==1)
      signal=true;
   if(type==(long)POSITION_TYPE_SELL && pb==-1)
      signal=true;

Bitte nehmen Sie zur Kenntnis, dass im Falle von strengen Eingabeparameterbedingungen Pin Bars nur selten auftritt. Wenn also eine Position nur infolge eines gegensätzlichen Pin-Bars geschlossen wird, besteht die Chance, Gewinne zu verlieren bzw. zu schließen, während eines Loss.

In diesem Zusammenhang fügen wir die Take-Profit- und Stop-Loss-Levels hinzu. Diese werden durch die Verwendung der beiden externen Parameter inp_tp_pp und inp_sl_pp eingestellt.

   double sl=0,tp=0,p=0;
   double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
   if(signal==ORDER_TYPE_SELL)
   {
     p=bid;
     if(inp_sl_pp!=0)
       sl=NormalizeDouble(ask+inp_sl_pp*_Point,_Digits);
     if(inp_tp_pp!=0)
       tp=NormalizeDouble(ask-inp_sl_pp*_Point,_Digits);
   } else {
     p=ask;
     if(inp_sl_pp!=0)
       sl=NormalizeDouble(bid-inp_sl_pp*_Point,_Digits);
     if(inp_tp_pp!=0)
       tp=NormalizeDouble(bid+inp_sl_pp*_Point,_Digits);
   }
   CTrade trade;
   trade.PositionOpen(_Symbol,signal,TradeSizeOptimized(),p,sl,tp);

Falls der Wert von inp_tp_pp oder inp_sl_pp null sein sollte, so wird das korrespondierende Take-Profit- bzw. Stop-Loss-Level nicht eingestellt werden.

Die Modifikationen sind jetzt abgeschlossen. Der EA kann jetzt verwandt werden. Der vollständige Code findet sich in der Datei pinbar_lc.mq5.


5. Optimierung des EAs

Um die Effektivität von Charts mit Shift im Falle verschiedener Strategien zu bewerten, werden wir uns die EA-Optimierung zunutze machen, indem wir die besten Ergebnisse miteinander vergleichen werden. Die wichtigsten Parameter sind zweifellos: Gewinn, Drawdown und die Zahl der Trades. EA-Trading mit einem Moving-Average wird uns dabei als ein Beispiel einer Indikatorstrategie dienen. Ferner wird Expert-Trading mittels eines „Pin-Bar“-Musters als ein Beispiel für eine Nicht-Indikatorstrategie herhalten.

Die Optimierung wird durch Quotes für das letzte halbe Jahr ausgeführt werden - Quotes des Servers MetaQuotes-Demo. Das Experiment wird für EURUSD, GBPUSD und USDJPY durchgeführt werden. Das Startkapital soll 3000 USD samt eines Leverages von 1:100 betragen. Für den Testmodus gilt: „Alle Ticks“. Optimierungsmodus - schnell (er, generischer Algorithmus), Max. Balance.


5.1 Analyse der Optimierungsergebnisse betreffend Expert-Trading mithilfe eines Moving-Averages

Lassen Sie uns die Resultate eines optimierten Expert-Advisors vergleichen, wenn er in verschiedenen Modi operiert: Null-Shift-, statischer Shift- und dynamischer Shiftmodus (DSO und DSC).

Der Test wird für EURUSD, GBPUSD sowie USDJPY für die Periode 01.04.2014 - 25.10.2014 (letzten sechs Monate) durchgeführt werden. Zeitraum H1.

Eingabeparameter des Expert-Advisors.

Parameter
Wert
 Maximales Risiko in Prozent
 0,1
 Verminderungsfaktor
 3,0
 Moving-Average-Periode
 12
 Moving-Average-Shift
 6
 BaseTF
 eine Minute
 LC aktiv
 true
 LC-Shift
 0

Tabelle 3. Eingabeparameter des Moving-Average-LC-EAs

5.1.1 Optimierung des EAs bei deaktiviertem Shiftmodus

Zu optimierende Parameter:

Parameter
 Start StepStopp
 Moving-Average-Periode
 12
 1
 90
 Moving-Average-Shift
 6
 1
 30

Tabelle 4. Optimierte Parameter des Moving-Average-LC-EAs im Null-Shiftmodus

Graph, der die EA-Optimierung im deaktivierten Shiftmodus anzeigt, EURUSD:

Optimierung im Null-Shiftmodus, EURUSD

Abb. 8 Optimierung des Moving-Average-LC-EAs im Null-Shiftmodus, EURUSD

Beste Ergebnisse:

 Ergebnis
 ProfitDrawdown (%):
Zahl der Trades
MovingPeriod; MovingShift;
 3796,43 796,43 16,18 111 24 12
 3776,98 776,98 17,70 77 55
 22
 3767,45 767,45 16,10 74 59
 23
 3740,38 740,38 15,87 78 55
 17
 3641,16 641,16 15,97 105 12
 17

Tabelle 5. Beste Resultate des Moving-Average-LC-EAs im Null-Shiftmodus, EURUSD

Graph, der die EA-Optimierung im Null-Shiftmodus anzeigt, GBPUSD:

Optimierung im Null-Shiftmodus, GBPUSD

Abb. 9 Optimierung des Moving-Average-LC-EAs im Null-Shiftmodus, GBPUSD

Beste Ergebnisse:

 Ergebnis ProfitDrawdown (%):
 Zahl der Trades
 MovingPeriod;MovingShift;
 4025,75 1025,75 8,08 80 18
 22
 3857,90 857,90 15,04 74 55
 13
 3851,40 851,40 18,16 80 13
 24
 3849,48 849,48 13,05 69 34
 29
 3804,70 804,70 16,57 137 25
 8

Tabelle 6. Beste Resultate der Optimierung des Moving-Average-LC-EAs für GBPUSD im Null-Shiftmodus

Graph, der die EA-Optimierung im deaktivierten Shiftmodus anzeigt, USDJPY:

Optimierung im Null-Shiftmodus, USDJPY

Abb. 10 Optimierung des Moving-Average-LC-EAs im Null-Shiftmodus, USDJPY

Beste Ergebnisse:

Ergebnis
Profit
Drawdown (%):
Zahl der Trades
 MovingPeriod; MovingShift;
5801,632801,6311,5448
65
23
5789,172789,1714,0350
44
27
5539,062539,0617,1446
67
27
5331,342331,3415,0561
70
9
5045,192045,1912,6148
83
15

Tabelle 7. Beste Resultate des Moving-Average-LC-EAs für USDJPY im Null-Shiftmodus

5.1.2 Optimierung des EAs im statischen Shiftmodus

Zu optimierende Parameter:

Parameter
 Start StepStopp
 Moving-Average-Periode
 12
 1
 90
 Moving-Average-Shift
 6
 1
 30
 LC-Shift 1 1 59

Tabelle 8. Optimierte Parameter des Moving-Average-LC-EAs im statischen Shiftmodus

Graph, der die EA-Optimierung im statischen Shiftmodus anzeigt, EURUSD:

Optimierung im statischen Shiftmodus, EURUSD

Abb. 11 Optimierung des Moving-Average-LC-EAs im statischen Shiftmodus, EURUSD

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
MovingPeriod;
MovingShift;
LC_shift
 4385,06
 1385,06
 12,87 100 32 11 8
 4149,63
 1149,63
 14,22 66 77 25 23
 3984,92
 984,92
 21,52 122 12 11 26
 3969,35
 969,35
 16,08 111 32 11 24
 3922,95
 922,95
 12,29 57 77 25 10

Tabelle 9. Beste Resultate des Moving-Average-LC-EAs für EURUSD im statischen Shiftmodus

Graph, der die EA-Optimierung im statischen Shiftmodus anzeigt, GBPUSD:

Optimierung im statischen Shiftmodus, GPBUSD

Abb. 12 Optimierung des Moving-Average-LC-EAs im statischen Shiftmodus, GBPUSD

Beste Ergebnisse:

 Ergebnis ProfitDrawdown (%):
Zahl der Trades
 MovingPeriod; MovingShift;LC_shift
 4571,07 1571,07 14,90 79 12
 25
 42
 4488,90 1488,90 15,46 73 12
 25
 47
 4320,31 1320,31 9,59 107 12
 16
 27
 4113,47 1113,47 10,96 75 12
 25
 15
 4069,21 1069,21 15,27 74 12
 25
 50

Tabelle 10. Beste Resultate des Moving-Average-LC-EAs für GBPUSD im statischen Shiftmodus

Graph, der die EA-Optimierung im statischen Shiftmodus anzeigt, USDJPY:

Optimierung im statischen Shiftmodus, USDJPY

Abb. 13 Optimierung des Moving-Average-LC-EAs im statischen Shiftmodus, USDJPY

Beste Ergebnisse:

Ergebnis
Profit
Drawdown (%):
Zahl der Trades
MovingPeriod;
 MovingShift;LC-Shift
 6051,39 3051,39 15,94 53
 76
 12
 31
 5448,98 2448,98 10,71 54
 44
 30
 2
 5328,15 2328,15 11,90 50
 82
 13
 52
 5162,82 2162,82 10,46 71
 22
 26
 24
 5154,71 2154,71 14,34 54
 75
 14
 58

Tabelle 11. Beste Resultate des Moving-Average-LC-EAs für USDJPY im statischen Shiftmodus

5.1.3 Optimierung des EAs im dynamischen Shiftmodus

Zu optimierende Parameter:

Parameter
 Start StepStopp
 Moving-Average-Periode
 12
 1
 90
 Moving-Average-Shift
 6
 1
 30
 LC-Shift -2 1 -1

Tabelle 12. Optimierte Parameter des Moving-Average-LC-EAs im dynamischen Shiftmodus

Graph, der die EA-Optimierung im dynamischen Shiftmodus anzeigt, EURUSD:

Optimierung im dynamischen Shiftmodus, EURUSD

Abb. 14 Optimierung des Moving-Average-LC-EAs im dynamischen Shiftmodus, EURUSD

Beste Ergebnisse:

Ergebnis
Profit
Drawdown (%):
Zahl der Trades
MovingPeriod;
MovingShift;
LC-Shift
 3392,64 392,64 27,95 594 15 13 -2
 3140,26 140,26 23,35 514 12 17 -2
 2847,12 -152,88 17,04 390 79 23 -1
 2847,12 -152,88 17,04 390 79 12 -1
 2826,25 -173,75 20,12 350 85 22 -1

Tabelle 13. Beste Resultate des Moving-Average-LC-EAs für EURUSD im dynamischen Shiftmodus

Graph, der die EA-Optimierung im dynamischen Shiftmodus anzeigt, GBPUSD:

Optimierung im dynamischen Shiftmodus, GBPUSD

Abb. 15 Optimierung des Moving-Average-LC-EAs im dynamischen Shiftmodus, GBPUSD

Beste Ergebnisse:

 ErgebnisProfit
 Drawdown (%):
Zahl der Trades
MovingPeriod;
 MovingShift;LC_shift
 5377,58 2377,58 19,73 391 12
 26
 -2
 3865,50 865,50 18,18 380 23
 23
 -2
 3465,63 465,63 21,22 329 48
 21
 -2
 3428,99 428,99 24,55 574 51
 16
 -1
 3428,99 428,99 24,55 574 51
 15
 -1

Tabelle 14. Beste Resultate des Moving-Average-LC-EAs für GBPUSD im dynamischen Shiftmodus

Graph, der die EA-Optimierung im dynamischen Shiftmodus anzeigt, USDJPY:

Optimierung im dynamischen Shiftmodus, USDJYP

Abb. 16 Optimierung des Moving-Average-LC-EAs im dynamischen Shiftmodus, USDJPY

Beste Ergebnisse:

Ergebnis
Profit
Drawdown (%):
 Zahl der Trades
MovingPeriod;
MovingShift;
 LC-Shift
 6500,19 3500,19 17,45 244
 42
 28
 -2
 6374,18 3374,18 19,91 243
 54
 24
 -2
 6293,29 3293,29 19,30 235
 48
 27
 -2
 5427,69 2427,69 17,65 245
 90
 8
 -2
 5421,83 2421,83 16,30 301
 59
 12
 -2

Tabelle 15. Beste Resultate des Moving-Average-LC-EAs für USDJPY im dynamischen Shiftmodus

5.2 Analyse der Optimierungsergebnisse betreffend Expert-Trading unter Verwendung des „Pin-Bar“-Musters

Lassen Sie uns die Resultate eines optimierten Expert-Advisors vergleichen, wenn er in verschiedenen Modi operiert: Null-Shift-, statischer Shift- und dynamischer Shiftmodus (DSO und DSC). Der Test wird für EURUSD, GBPUSD sowie USDJPY für die Periode 01.04.2014 - 25.10.2014 durchgeführt werden. Zeitraum H1.

Eingabeparameter des Expert Advisors:

 ParameterWert
Maximales Risiko in Prozent
0,1
Verminderungsfaktor
3,0
Min. Pin-Bar-Schatten, Punkte
40
Max. Pin-Bar-OC, Punkte
110
Min. Pin-Bar-Schatten-OC-Verhältnis
1,4
SL, Punkte (0 für OFF/DEAKTIVIERT)
150
TP, Punkte (0 für OFF/DEAKTIVIERT)
300
LC Grundperiode
eine Minute
LC-Modus AKTIVIERT
true
LC-Shift
0

Tabelle 16. Eingabeparameter des Pin-Bar-LC-EAs

Wir werden nun die Parameter optimieren, die die Pin-Bar-Form definieren: die Länge der „Nase“, das Verhältnis von Länge der „Nase“ zum Körper des mittleren Balkens und die maximale Größe des Körpers. Außerdem müssen die Take-Profit- und Stop-Loss-Levels optimiert werden.


5.2.1 Optimierung des EAs bei deaktiviertem Shiftmodus

Zu optimierende Parameter:

 Parameter Start Step Stopp
Min. Pin-Bar-Schatten, Punkte
100
20
400
Max. Pin-Bar-OC, Punkte
20
20
100
Min. Pin-Bar-Schatten-OC-Verhältnis
1
0,2
3
SL, Punkte (0 für OFF/DEAKTIVIERT)
150
50
500
TP, Punkte (0 für OFF/DEAKTIVIERT)
150
50
500

Tabelle 17. Optimierte Parameter des Pin-Bar-LC-EAs im deaktivierten Shiftmodus

Graph, der die EA-Optimierung im deaktivierten Shiftmodus anzeigt, EURUSD:

Optimierung im Null-Shiftmodus, EURUSD

Abb. 17 Optimierung des Pin-Bar-LC-EAs im Null-Shiftmodus, EURUSD

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
 Min. Pin-Bar-Schatten
 Max. Pin-Bar-OC
 Min. Verhältnis von Pin-Bar-Schatten
zu OC
 SL TP
 3504,59
 504,59
 9,82
 33
 100
 60
 1,8
 450
 500
 3428,89
 428,89
 8,72
 21
 120
 60
 2,8
 450
 350
 3392,37
 392,37
 9,94
 30
 100
 60
 2,6
 450
 250
 3388,54
 388,54
 9,93
 31
 100
 80
 2,2
 450
 300
 3311,84
 311,84
 6,84
 13
 140
 60
 2,2
 300
 450

Tabelle 18. Beste Resultate des Pin-Bar-LC-EAs für EURUSD im Null-Shiftmodus

Graph, der die EA-Optimierung im Null-Shiftmodus anzeigt, GBPUSD:

Optimierung im Null-Shiftmodus, GBPUSD

Abb. 18 Optimierung des Pin-Bar-LC-EAs im Null-Shiftmodus, GBPUSD

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
 Min. Pin-Bar-Schatten
 Max. Pin-Bar-OC
 Min. Verhältnis von Pin-Bar-Schatten
zu OC
 SL TP
 3187,13
 187,13
 11,10
 13
 160
 60
 2,6
 500
 350
 3148,73
 148,73
 3,23
 4
 220
 40
 2,8
 400
 400
 3142,67
 142,67
 11,27
 17
 160
 100
 1,8
 500
 350
 3140,80
 140,80
 11,79
 13
 180
 100
 2
 500
 500
 3094,20
 94,20
 1,62
 1
 260
 60
 1,6
 500
 400

Tabelle 19. Beste Resultate des Pin-Bar-LC-EAs für GBPUSD im Null-Shiftmodus

Graph, der die EA-Optimierung im deaktivierten Shiftmodus anzeigt, USDJPY:

Optimierung im Null-Shiftmodus, USDJPY

Abb. 19 Optimierung des Pin-Bar-LC-EAs im Null-Shiftmodus, USDJPY

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
 Min. Pin-Bar-Schatten
 Max. Pin-Bar-OC
 Min. Verhältnis von Pin-Bar-Schatten
zu OC
 SL TP
 3531,99
 531,99
 9,00
 6
 160
 60
 2,2
 450
 500
 3355,91
 355,91
 18,25
 16
 120
 60
 1,6
 450
 400
 3241,93
 241,93
 9,11
 4
 160
 40
 2,8
 450
 500
 3180,43
 180,43
 6,05
 33
 100
 80
 1,8
 150
 450
 3152,97
 152,97
 3,14
 6
 160
 80
 2,8
 150
 500

Tabelle 20. Beste Resultate des Pin-Bar-LC-EAs für USDJPY im Null-Shiftmodus

5.2.2 Optimierung des EAs im statischen Shiftmodus

Zu optimierende Parameter:

 Parameter Start Step Stopp
 Min. Pin-Bar-Schatten, Punkte
 100
 20
 400
 Max. Pin-Bar-OC, Punkte
 20
 20
 100
 Min. Pin-Bar-Schatten-OC-Verhältnis
 1
 0,2
 3
 SL, Punkte (0 für OFF/DEAKTIVIERT)
 150
 50
 500
 TP, Punkte (0 für OFF/DEAKTIVIERT)
 150
 50
 500
 LC-Shift
 1 1 59

Tabelle 21. Optimierte Parameter des Pin-Bar-LC-EAs im statischen Shiftmodus

Graph, der die EA-Optimierung im statischen Shiftmodus anzeigt, EURUSD:

Optimierung im statischen Shiftmodus, EURUSD

Abb. 20 Optimierung des Pin-Bar-LC-EAs im statischen Shiftmodus, EURUSD

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
 Min. Pin-Bar-Schatten
 Max. Pin-Bar-OC
 Min. Verhältnis von Pin-Bar-Schatten
zu OC
 SL TP LC-Shift
 4843,54
 1843,54
 10,14
 19
 120
 80
 1,6
 500
 500
 23
 4714,81
 1714,81
 10,99
 28
 100
 100
 1,6
 500
 500
 23
 4672,12
 1672,12
 10,16
 18 120
 80
 1,8
 500
 500
 23
 4610,13
 1610,13
 9,43
 19
 120
 80
 1,6
 450
 450
 23
 4562,21
 1562,21
 13,94
 27
 100
 100
 1,6
 500
 400
 25

Tabelle 22. Beste Resultate des Pin-Bar-LC-EAs für EURUSD im statischen Shiftmodus

Graph, der die EA-Optimierung im statischen Shiftmodus anzeigt, GBPUSD:

Optimierung im statischen Shiftmodus, GPBUSD

Abb. 21 Optimierung des Pin-Bar-LC-EAs im statischen Shiftmodus, GBPUSD

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
 Min. Pin-Bar-Schatten
 Max. Pin-Bar-OC
 Min. Verhältnis von Pin-Bar-Schatten
zu OC
 SL TP LC-Shift
 4838,10
 1838,10
 5,60
 34
 100
 40
 2,4
 450
 500
 24
 4797,09
 1797,09
 5,43
 35
 100
 40
 2,6
 400
 500
 24
 4755,57
 1755,57
 7,36
 42
 100
 100
 2
 400
 500
 24
 4725,41
 1725,41
 8,35
 45
 100
 80
 1
 400
 500
 24
 4705,61
 1705,61
 8,32
 41
 100
 100
 2
 450
 500
 24

Tabelle 23. Beste Resultate des Pin-Bar-LC-EAs für GBPUSD im statischen Shiftmodus

Graph, der die EA-Optimierung im statischen Shiftmodus anzeigt, USDJPY:

Optimierung im statischen Shiftmodus, USDJPY

Abb. 22 Optimierung des Pin-Bar-LC-EAs im statischen Shiftmodus, USDJPY

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
 Min. Pin-Bar-Schatten
 Max. Pin-Bar-OC
 Min. Verhältnis von Pin-Bar-Schatten
zu OC
 SL TP LC-Shift
 4108,83
 1108,83
 6,45
 9
 140
 40
 1,4
 500
 450
 55
 3966,74
 966,74
 7,88
 12
 140
 60
 2,8
 450
 500
 45
 3955,32
 955,32
 9,91
 21
 120
 80
 2
 500
 500
 45
 3953,80
 953,80
 6,13
 10
 140
 60
 2,8
 450
 450
 47
 3944,33
 944,33
 6,42
 6
 160
 100
 2,6
 500
 400
 44

Tabelle 24. Beste Resultate des Pin-Bar-LC-EAs für USDJPY im statischen Shiftmodus

5.2.3 Optimierung des EAs im dynamischen Shiftmodus

Zu optimierende Parameter:

 Parameter Start Step Stopp
 Min. Pin-Bar-Schatten, Punkte
 100
 20
 400
 Max. Pin-Bar-OC, Punkte
 20
 20
 100
 Min. Pin-Bar-Schatten-OC-Verhältnis
 1
 0,2
 3
 SL, Punkte (0 für OFF/DEAKTIVIERT)
 150
 50
 500
 TP, Punkte (0 für OFF/DEAKTIVIERT)
 150
 50
 500
 LC-Shift
 -2 1 -1

Tabelle 25. Optimierte Parameter des Pin-Bar-LC-EAs im dynamischen Shiftmodus

Graph, der die EA-Optimierung im dynamischen Shiftmodus anzeigt, EURUSD:

Optimierung im dynamischen Shiftmodus, EURUSD

Abb. 23 Optimierung des Pin-Bar-LC-EAs im dynamischen Shiftmodus, EURUSD

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
 Min. Pin-Bar-Schatten
 Max. Pin-Bar-OC
 Min. Verhältnis von Pin-Bar-Schatten
zu OC
 SL TP LC-Shift
 4185,65
 1185,65
 13,22
 49
 200
 100
 1,8
 450
 500
 -2
 4011,80
 1011,80
 13,75
 49
 200
 100
 2
 400
 500
 -2
 3989,28
 989,28
 12,01
 76
 140
 20
 1,2
 350
 200
 -1
 3979,50
 979,50
 16,45
 157
 100
 20
 1
 450
 500
 -1
 3957,25
 957,25
 16,68
 162
 100
 20
 1
 400
 500
 -1

Tabelle 26. Beste Resultate des Pin-Bar-LC-EAs für EURUSD im dynamischen Shiftmodus

Graph, der die EA-Optimierung im dynamischen Shiftmodus für GBPUSD anzeigt:

Optimierung im dynamischen Shiftmodus, GBPUSD

Abb. 24 Optimierung des Pin-Bar-LC-EAs im dynamischen Shiftmodus, GBPUSD

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
 Min. Pin-Bar-Schatten
 Max. Pin-Bar-OC
 Min. Verhältnis von Pin-Bar-Schatten
zu OC
 SL TP LC-Shift
 4906,84
 1906,84
 10,10
 179
 120
 40
 1,8
 500
 500
 -2
 4316,46
 1316,46
 10,71
 151
 120
 20
 2,4
 450
 500
 -1
 4250,96
 1250,96
 12,40
 174
 120
 40
 1,8
 500
 500
 -1
 4040,82
 1040,82
 12,40
 194
 120
 60
 2
 500
 200
 -2
 4032,85
 1032,85
 11,70
 139
 140
 40
 2
 400
 200
 -1

Tabelle 27. Beste Resultate des Pin-Bar-LC-EAs für GBPUSD im dynamischen Shiftmodus

Graph, der die EA-Optimierung im dynamischen Shiftmodus anzeigt, USDJPY:

Optimierung im dynamischen Shiftmodus, USDJYP

Abb. 25 Optimierung des Pin-Bar-LC-EAs im dynamischen Shiftmodus, USDJPY

Beste Ergebnisse:

Ergebnis
Profit
 Drawdown (%):
 Zahl der Trades
 Min. Pin-Bar-Schatten
 Max. Pin-Bar-OC
 Min. Verhältnis von Pin-Bar-Schatten
zu OC
 SL TP LC-Shift
 5472,67
 2472,67
 13,01
 138
 100
 20
 2,4
 500
 500
 -1
 4319,84
 1319,84
 15,87
 146
 100
 20
 2,2
 400
 500
 -1
 4259,54
 1259,54
 19,71
 137
 100
 20
 2,4
 500
 500
 -2
 4197,57
 1197,57
 15,98
 152
 100
 20
 1
 350
 500
 -1
 3908,19
 908,19
 16,79
 110
 120
 40
 3
 400
 400
 -1

Tabelle 28. Beste Resultate des Pin-Bar-LC-EAs für USDJPY im dynamischen Shiftmodus


6 Vergleich der Optimierungsergebnisse

Um eine Vergleichstabelle zu erstellen, sollten wir die maximalen Werte für Gewinne, Drawdown und die Tradezahl von jeder „Beste-Ergebnisse“-Tabelle auswählen. Neben dem Wert, den wir im statischen und dynamischen Modus erhalten haben, werden wir die Änderung (in Prozent) oder aber diesen Wert in Relation zum selben Wert im Null-Shiftmodus notieren.


6.1 Expert-Trading mithilfe eines Moving-Averages

Gewinn:

 Kein Shift
 Statischer
Shift
Dynamischer
Shift
 EURUSD
 796,43
 1385,06 (+74%)
 392,64 (-51%)
 GBPUSD
 1025,75
 1571,07 (+53%)
 2377,58 (+132%)
 USDJPY
 2801,63
 3051,39 (+9%)
 3500,19 (+25%)

Tabelle 29. Vergleich der Werte des maximalen Gewinns des Moving-Average-LC-EAs (der Tabelle der besten Optimierungsergebnisses entnommen)

Drawdown:

 Kein Shift
 Statischer
Shift
Dynamischer
Shift
 EURUSD
 17,7
 21,52 (+22%)   
 27,95 (+58%)      
 GBPUSD
 18,16
 15,46 (-15%)
 24,55 (+35%)
 USDJPY
 17,14
 15,94 (-7%)
 19,91 (+16%)

Tabelle 30. Vergleich der Werte des maximalen Drawdowns des Moving-Average-LC-EAs (der Tabelle der besten Optimierungsergebnisses entnommen)

Zahl der Trades

 Kein Shift
 Statischer
Shift
Dynamischer
Shift
 EURUSD
 111
 122 (+10%)     
 594 (+435%)       
 GBPUSD
 137
 107 (-22%)
 574 (+319%)
 USDJPY
 61
 71 (+16%)
 301 (+393%)

Tabelle 31. Vergleich der Werte der maximalen Zahl der Trades des Moving-Average-LC-EAs (der Tabelle der besten Optimierungsergebnisses entnommen)

Der erste Punkt, der ins Auge sticht: eine signifikante Erhöhung der Eintrittspunkte im dynamischen Shiftmodus. Zur gleichen Zeit hat sich allerdings der Drawdown merklich erhöht. Auch hat sich der Gewinn für EURUSD zwei Mal reduziert.

Der statische Shiftmodus ist also zumindest für diesen EA profitabler. Hier können wir ein Sinken des Drawdowns für GBPUSD und USDJPY und einen signifikanten Anstieg des Profits für EURUSD und GBPUSD begutachten.


6.2 Expert-Trading unter Verwendung des „Pin-Bar“-Musters

Gewinn:

 Kein Shift
 Statischer
Shift
Dynamischer
Shift
 EURUSD
504,59
1843,54 (+265%)
1185,65 (+135%)
 GBPUSD
187,13
1838,10 (+882%)
1906,84 (+919%)
 USDJPY
531,99
1108,83 (+108%)2472,67 (+365%)

Tabelle 32. Vergleich der Werte des maximalen Gewinns des Pin-Bar-LC-EAs (der Tabelle der besten Optimierungsergebnisses entnommen)

Drawdown:

 Kein Shift
 Statischer
Shift
Dynamischer
Shift
 EURUSD
9,94
13,94 (+40%)
16,68 (+68%)
 GBPUSD
11,79
8,35 (-29%)
12,4 (+5%)
 USDJPY
18,25
9,91 (-46%)
19,71 (+8%)

Tabelle 33. Vergleich der Werte des maximalen Drawdowns des Pin-Bar-LC-EAs (der Tabelle der besten Optimierungsergebnisses entnommen)

Zahl der Trades

 Kein Shift
 Statischer
Shift
Dynamischer
Shift
 EURUSD
33
28 (-15%)
162 (+391%)
 GBPUSD
17
45 (+165%)
194 (+1041%)
 USDJPY
33
21 (-36%)
152 (+361%)

Tabelle 34. Vergleich der Werte der maximalen Anzahl an Trades des Pin-Bar-LC-EAs (der Tabelle der besten Optimierungsergebnisses entnommen)

Hier sehen wir einen erheblichen Anstieg der Anzahl der Trades im dynamischen Shiftmodus. Einen signifikanten Anstieg des Drawdowns gibt es in diesem Fall - wie im Falle des Moving-Average-LC-EAs - nur bei EURUSD. Für andere Paare erhöht sich der Drawdown nur unwesentlich, ungefähr um 5-8 Prozent.

Im statischen Shiftmodus bewirkte die Optimierung einen begrenzten Gewinn für GBPUSD als auch USDJPY. Aber wie dem auch sei, wir sehen auch ein signifikantes Absinken des Drawdowns für die gleichen Paare und einen Anstieg für EURUSD. Der statische Shiftmodus sieht für diesen EA also weniger profitabel aus.


Fazit

In diesem Artikel haben wir uns den Prinzipien des Zeichnens von „Liquid-Charts“ zugewendet und den Einfluss ihrer Operationsmethode auf die Optimierungsergebnisse des EAs basierend auf einer Indikatorstrategie und einer Nicht-Indikatorstrategie verglichen.

Die Schlussfolgerungen:

  • Für EAs, die auf einer Indikatorstrategie basieren (z.B. Moving-Average) ist der statische Shiftmodus besser. Er erlaubt einen präziseren Markteintritt, was sich in einem sinkenden Drawdown und einem steigenden Gewinn bemerkbar macht.
  • Der dynamische Shiftmodus ist hingegen für all jene EAs besser geeignet, die mit Mustern traden. Dieser Modus erhöht die Zahl der Eintrittspunkte, obwohl sich zur selben Zeit der Drawdown erhöht.
  • Der dynamische Shiftmodus kann in Verbindung mit einem soliden Money-Management beeindruckende Resultate erzielen.
  • Obgleich der statische Shiftmodus für Indikatorstrategien sehr verlockend aussieht, besitzt er dennoch einen signifikanten Nachteil. Ein Shiftwert, der gute Resultate verspricht, ist eine weitere Variable in der Liste der Eingabeparameter, die man richtig raten muss.

Übersetzt aus dem Russischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/ru/articles/1208

Beigefügte Dateien |
liquid_chart.mq5 (27.15 KB)
pinbar_lc.mq5 (18.61 KB)
liquidchart.mqh (8.32 KB)
Grundlagen der Programmierung in MQL5: Globale Variablen des Terminals Grundlagen der Programmierung in MQL5: Globale Variablen des Terminals

Dieser Beitrag beschäftigt sich mit den Objekt-orientierten Fähigkeiten der MQL5-Sprache zur Erzeugung von Objekten, die die Arbeit mit globalen Variablen des Terminals erleichtern. Als praktisches Beispiel betrachte ich einen Fall, wo die globalen Variablen als Kontrollpunkte zur Implementierung der Programmphasen eingesetzt werden.

Statistik-Cookbook für Händler: Hypothesen Statistik-Cookbook für Händler: Hypothesen

Dieser Beitrag beschäftigt sich mit Hypothesen - einem der Grundkonzepte mathematischer Statistik. Es werden dabei verschiedene Hypothesen untersucht und anhand von Beispielen mit Hilfe mathematischer Statistikmethoden überprüft. Die tatsächlichen Daten werden mittels nicht parametrischer Methoden verallgemeinert. Zur Verarbeitung der Daten werden das Statistica-Paket und die übertragene ALGLIB MQL5 numerische Analyse-Library verwendet.

Auf Fraktalen basiertes Zeichnen von Trendlinien mithilfe von MQL4 und MQL5 Auf Fraktalen basiertes Zeichnen von Trendlinien mithilfe von MQL4 und MQL5

Dieser Artikel widmet sich dem automatischen Zeichnen von Trendlinien via MQL4 und MQL5 basierend auf dem Fraktale-Indikator. Die Struktur des Artikels ist so angelegt, dass sie einen vergleichenden Blick auf zwei Sprachen werfen wird. Das Zeichnen von Trendlinien basiert dabei auf den beiden letzten bekannten Fraktalen.

MQL5-Kochbuch: Verarbeitung des Ereignisses BookEvent MQL5-Kochbuch: Verarbeitung des Ereignisses BookEvent

Dieser Artikel widmet sich BookEvent - einem Markttiefeereignis - und den Prinzipien seiner Verarbeitung. An dieser Stelle soll uns ein MQL-Programm, das Markttiefezustände verarbeitet, als Beispiel dienen. Das Programm basiert auf einem objektorientierten Ansatz. Die Verarbeitungsresultate werden auf dem Bildschirm in Form eines Panels und in Form von Levels der Markttiefe dargestellt.