Testen der Muster, die beim Handel mit Körben von Währungspaaren auftreten. Teil II

Andrei Novichkov | 12 Dezember, 2017


Einleitung

Wir setzen das Thema des Testens der Muster fort, die beim Handel mit Währungskörben auftreten. Im vorherigen Artikel beschäftigten wir uns mit einem Muster des Ausbruchs von Überkauft- und Überverkauft-Levels. Der Ausbruch dieser Levels wurde am Beispiel eines vereinigten WPR betrachtet. Diese Erfahrungen können auch auf andere vereinigte Indikatoren angewandt werden, die auf Oszillatoren basieren. Man kann vermuten, dass das Ergebnis gleich sein wird.

Im Laufe des Testens wurde die Lage der Überkauft- und Überverkauft-Levels ausgewertet. Für den Überkauft-Level liegt dieser Wert im Bereich 60% - 70%, der Überverkauft-Level zwischen -60% und -70%. Das Testen des Musters wies auf dem Zeitrahmen H4 auf allen Körben von Währungspaaren Profitabilität auf. Auf dem Zeitrahmen D1 wurde eine unbedeutende Anzahl von Trades verzeichnet. H1 zeigte erhebliche Verluste.

In dem vorliegenden Artikel versuchen wir, einen gleitenden Durchschnitt (МА) auf die Charts vereinigter Indikatoren anzuwenden und dies im Handel zu nutzen. Wir stützen uns nach wie vor auf die technische Analyse und auf die von uns entwickelten Methoden.

Tools der Untersuchung

Das Hauptwerkzeug für die Untersuchung ist der bereits vertraute Indikator — der vereinigte WPR mit der Periode 20. Ziehen wir einen MA mit der Periode 10 auf seinen Chart. Solche kurze Periode wurde ausgewählt, weil wir kein Ziel haben, globale Prozesse zu überwachen. Uns interessieren nur lokale Tendenzen. Aus diesem Grund werden lange Perioden nicht betrachtet.

Wie auch in dem vorherigen Artikel untersuchen wir drei Zeitrahmen — H1, H4 und D1. Wir wissen noch, wie sich das erste Muster auf diesen Zeitrahmen gezeigt hat. Es ist logisch, auch das nächste Muster anhand dieser Zeitrahmen zu betrachten. Vergessen wir nicht, dass die gesammelte Erfahrung für Untersuchungen mit anderen Zeitrahmen und Währungskörben verwendet werden kann.

Die Basisbegriffe und Grundlagen der Methoden wurden hier dargelegt.

Das zu untersuchende Muster

Dieses Muster ist in der klassischen technischen Analyse gut bekannt, wir haben ihn bereits beschrieben. Rufen wir uns die wichtigsten Momente ins Gedächtnis, die für den Handel mit Körben von Währungspaaren charakteristisch sind:

  • Der Trader bekommt ein Signal für den Einstieg in den Markt, wenn der vereinigte Indikator den gleitenden Durchschnitt kreuzt.

Es gibt nur zwei Signale:

  • Signal für den Kauf des Korbes eines Währungspaares — wenn der vereinigte Indikator die MA-Grafik von unten nach oben kreuzt.
  • Signal für den Verkauf des Korbes eines Währungspaares — wenn der vereinigte Indikator die MA-Grafik von oben nach unten kreuzt.
  • Der Trader eröffnet eine Kauf- oder Verkaufsposition, für welchen ein Signal empfangen wurde.
  • Der Trader steigt aus dem Markt aus, wenn er ein entgegengesetztes Signal erhält.

Darüber hinaus muss man immer im Hinterkopf behalten, dass sich die Signale von einem gleitenden Durchschnitt durch Verzögerungen gekennzeichnet sind.

Aus der Erfahrung der Anwendung des МА auf Währungspaare wissen wir, dass es für gleitende Durchschnitte immer eine große Anzahl von Einstiegssignalen gibt. Wir können erwarten, dass es in unserem Fall auch viele solche Signale geben wird. Um diese Behauptung zu prüfen, wurde der Indikator testWPR&MA.mq5 geschrieben. Er ist im Anhang zu finden.

//+------------------------------------------------------------------+
//|                                                      testWPR.mq5 |
//|                                        MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_minimum -100
#property indicator_maximum 100


#define LG 7

#property indicator_buffers 2
#property indicator_plots   2

input int WPR       = 20; //Period WPR
input int maperiod  = 10; //Period MA
input color   clr   = clrGreen;
input color   clrMA = clrMagenta;

string pair[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY"};
bool bDirect[]={false,false,false,false,true,true,true};

int h[LG];
double ind[],ma[];

int iUp,iDw;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   for(int i=0; i<LG; i++)
     {
      h[i]=iWPR(pair[i],0,WPR);
     }

   IndicatorSetString(INDICATOR_SHORTNAME,"testWPRusd");
   IndicatorSetInteger(INDICATOR_DIGITS,2);
   IndicatorSetInteger(INDICATOR_LEVELS,2);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE,0,STYLE_SOLID);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE,1,STYLE_SOLID);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR,0,clrRed);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR,1,clrRed);
   IndicatorSetInteger(INDICATOR_LEVELWIDTH,0,1);
   IndicatorSetInteger(INDICATOR_LEVELWIDTH,1,1);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,0,-60);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,1,60);

   ArraySetAsSeries(ind,true);
   SetIndexBuffer(0,ind);
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);
   PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,2);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,clr);
   PlotIndexSetString(0,PLOT_LABEL,"_tstWPRusd_");

   ArraySetAsSeries(ma,true);
   SetIndexBuffer(1,ma);
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE);
   PlotIndexSetInteger(1,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(1,PLOT_LINE_WIDTH,1);
   PlotIndexSetInteger(1,PLOT_LINE_COLOR,clrMA);
   PlotIndexSetString(1,PLOT_LABEL,"Middle_Basket_line_MA");

   iUp=iDw=0;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double GetValue(int shift)
  {
   double dBuf[1];
   double res=0.0;
   for(int i=0; i<LG; i++)
     {
      CopyBuffer(h[i],0,shift,1,dBuf);
      if(bDirect[i]==true)
         res+=dBuf[0];
      else
         res+=-(dBuf[0]+100);
     }//end for (int i = 0; i < iCount; i++)      
   res=res/LG;
   return (NormalizeDouble((res + 50) * 2, _Digits) );
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   if(prev_calculated==0 || rates_total>prev_calculated+1)
     {
      int rt=rates_total-WPR;
      for(int i=1; i<rt; i++)
        {
         ind[i]=GetValue(i);
        }
      rt-=maperiod;
      for(int i=1; i<rt; i++)
        {
         ma[i]=GetMA(ind,i,maperiod,_Digits);
        }
      rt--;
      for(int i=1; i<rt; i++)
        {
         if(ind[i] > ma[i] && ind[i+1] < ma[i+1]) {iUp++; continue;}
         if(ind[i] < ma[i] && ind[i+1] > ma[i+1]) {iDw++; continue;}
        }
      PrintFormat("BUY count: %d SELL count: %d",iUp,iDw);
     }
   else
     {
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

void OnDeinit(const int reason)
  {
   for(int i=0; i<LG; i++)
     {
      if(h[i]!=INVALID_HANDLE) IndicatorRelease(h[i]);
     }
   string text;
   switch(reason)
     {
      case REASON_PROGRAM:
         text="Indicator terminated its operation by calling the ExpertRemove() function";break;
      case REASON_INITFAILED:
         text="This value means that OnInit() handler "+__FILE__+" has returned a nonzero value";break;
      case REASON_CLOSE:
         text="Terminal has been closed"; break;
      case REASON_ACCOUNT:
         text="Account was changed";break;
      case REASON_CHARTCHANGE:
         text="Symbol or timeframe was changed";break;
      case REASON_CHARTCLOSE:
         text="Chart was closed";break;
      case REASON_PARAMETERS:
         text="Input-parameter was changed";break;
      case REASON_RECOMPILE:
         text="Program "+__FILE__+" was recompiled";break;
      case REASON_REMOVE:
         text="Program "+__FILE__+" was removed from chart";break;
      case REASON_TEMPLATE:
         text="New template was applied to chart";break;
      default:text="Another reason";
     }
   PrintFormat("%s",text);
  }
//+------------------------------------------------------------------+

double GetMA(const double &arr[],int index,int period,int digit) 
  {
   double m=0;
   for(int j=0; j<period; j++) m+=arr[index+j];
   m/=period;
   return (NormalizeDouble(m,digit));
  }
//+------------------------------------------------------------------+

Der Indikator zählt, wie oft der vereinigte Indikator den gleitenden Durchschnitt im Laufe der Historie kreuzt. Ziehen wir den Indikator auf den EURUSD Chart, und wir erhalten die Daten für den USD-Korb für die gewünschten Zeitrahmen:

  Die erhaltenen Signale
H1 H4 D1
Buy Sell Buy Sell Buy Sell
EURUSD 8992 8992 2448 2449 550 551
Tiefe der Historie 2005.09.08 2004.10.11 2000.02.28

Wie wir sehen, gibt es ausreichend Signale. Nehmen wir an, das trifft auch für die anderen Währungskörbe zu, und überprüfen wir diese nicht.

Demonstrieren wir die Arbeit des Indikators anhand eines Screenshots:

Eine Vielzahl potentieller Signale fällt sofort auf. Offensichtlich sind viele falsche darunter, aber es ist noch zu früh, davon zu sprechen. Markieren wir Kaufsignale blau und Verkaufssignale — rot.

Definieren wir die Arbeitslogik für unsere Untersuchungen:

  • Einsteigen, wenn ein Einstiegssignal erhalten wird. Aussteigen, wenn ein entgegengesetztes Signal erhalten wird. In die umgekehrte Richtung einsteigen. Beim Auftreten der entsprechenden Signale wiederholen wir die Reihenfolge der Aktionen.

Es ist offensichtlich, dass die Methode eine ständige Präsenz auf dem Markt voraussetzt, wenn es kein zusätzliches Filtern gibt. Höchstwahrscheinlich werden wir ein solches Filtern benötigen, mit dieser Frage beschäftigen wir uns aber später. Die unterschiedliche Qualität von Signalen fällt auf dem Screenshot sofort auf:

  • klare Signale in den Punkten 7 und 8 (blau);
  • ein gutes Signal im Punkt 5 (rot);
  • Anhäufung gegenläufiger Signale in den Punkten 2, 3, 4 (rot).

Definieren wir die Regeln, wie man "gute" Signale von den "schlechten" unterscheiden kann. Auf den zwei Abbildungen unten sehen wir die Merkmale, die die "guten" Signale ganz genau erkennen lassen:

Das gesuchte, "gute" Muster (Signal)
Kein Muster, "schlechtes" Signal





Auf diesen Abbildungen ist die Grafik des vereinigten WPR für USD in Grün, der gleitende Durchschnitt — in Himbeerrot, die Grenzen des Musters — mit vertikalen blauen Linien dargestellt.

Legen wir fest, dass für Einstiegsmuster Delta1 und Delta2 nicht kleiner als 5% sein dürfen.

Wir nutzen aber auch die "schlechten" Muster, wie auf der Abbildung rechts. Zwar geben sie keine Einstiegssignale, warnen aber vor möglicher Trendwende oder Verlangsamung des Trends. Auf diese Weise kann man sie für den Ausstieg aus dem Markt oder für das Filtern verwenden, was wir auch tun werden.

Beginn des Testens

Für die weitere Arbeit benötigen wir den Expert Advisor, der in der angehängten Datei testEAbasket.mq5 zu finden ist:

//+------------------------------------------------------------------+
//|                                                 testEAbasket.mq5 |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade\\Trade.mqh>

#define LG 7

enum BSTATE 
  {
   BCLOSE = 0,
   BBUY   = 1,
   BSELL  = 2
  };
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
input int wpr = 20;
input int ma  = 10;
input double lt = 0.01; //lot

string pair[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY"};
bool bDirect[]={false,false,false,false,true,true,true};

int h;
ulong  Ticket[LG];

double m[1],ml;
double w[1],wl;

BSTATE g_state;

double g_dMinSize = 5.0;

int OnInit()
  {
   h = iCustom(NULL,0,"testWPR&MA",wpr,ma);
   if (h == INVALID_HANDLE) {
      Print("Error while creating testWPReur");
      return (INIT_FAILED);
   }
   
   g_state = BCLOSE;
   
   EventSetTimer(1);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(h);
   EventKillTimer();
      
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   if(IsNewCandle()) 
     {
         wl = w[0];
         CopyBuffer(h,0,1,1,w);
         ml = m[0];
         CopyBuffer(h,1,1,1,m);
         if ( w[0] > m[0] && wl < ml) {
            if (g_state != BCLOSE) CloseAllPos();
            if ( w[0] - m[0] >= g_dMinSize && ml - wl >= g_dMinSize) {
               EnterBuy(lt);
               g_state = BBUY;
            }   
         }     
         if ( w[0] < m[0] && wl > ml) {
            if (g_state != BCLOSE) CloseAllPos();
            if ( m[0] - w[0] >= g_dMinSize && wl - ml >= g_dMinSize) {
               EnterSell(lt);
               g_state = BSELL;
            }   
         }            
     }      
  }
//+------------------------------------------------------------------+
  
void CloseAllPos() 
  {

   CTrade Trade;
   Trade.LogLevel(LOG_LEVEL_NO);

   for(int i=0; i<LG; i++) 
     {

      Trade.PositionClose(Ticket[i]);
     }

     g_state = BCLOSE;

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void EnterBuy(double lot) 
  {

   CTrade Trade;
   Trade.LogLevel(LOG_LEVEL_NO);

   for(int i=0; i<LG; i++) 
     {
      if(bDirect[i]) 
        { //send buy
         Trade.Buy(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
      else 
        { //send sell
         Trade.Sell(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
     }
     g_state = BBUY;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void EnterSell(double lot) 
  {

   CTrade Trade;
   Trade.LogLevel(LOG_LEVEL_NO);

   for(int i=0; i<LG; i++) 
     {
      if(bDirect[i]) 
        { //send sell
         Trade.Sell(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
      else 
        { //send buy
         Trade.Buy(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
     }
     g_state = BSELL;
  }
  
bool IsNewCandle() 
  {

   static int candle=-1;

   int t1=0;
   switch(_Period)
     {
      case PERIOD_H1:  t1 = Hour();   break;
      case PERIOD_H4:  t1 = Hour4();  break;
      case PERIOD_D1:  t1 = Day();    break;
     }
   if(t1 != candle) {candle=t1; return(true);}
   return (false);
  }
int Hour4(){return((int)Hour()/4);}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int Day()
  {
   MqlDateTime tm;
   TimeCurrent(tm);
   return(tm.day);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int Hour()
  {
   MqlDateTime tm;
   TimeCurrent(tm);
   return(tm.hour);
  }  

Testen wir den Expert Advisor im Strategietester anhand der Daten für das letzte Jahr auf den Zeitrahmen H1, H4 und D1. Wir analysieren den USD-Währungskorb.

Die Ergebnisse der Analyse sind als Standardberichte in der angehängten Zip-Datei testEAbasket.zip enthalten. Man kann sofort sagen, dass die Testergebnisse negativ sind. Bei den aktuellen Einstellungen erzielt der Expert Advisor Verluste in allen drei Zeitrahmen. Das ist ein negatives, aber erwartetes Ergebnis. Es ist schwer zu glauben, dass man bei der großen Anzahl von Trades, die vorher festgestellt wurde, Profite erzielen kann. Folgende Umstände beeinflussten das Ergebnis:

  • Das Muster mit einem gleitendem Durchschnitt weist immer Verzögerungen auf (per definitionem).
  • In der technischen Analyse wird die Einstiegsentscheidung nicht basierend auf dem Verhalten eines einzigen schnellen gleitenden Durchschnitts getroffen.
  • Im Expert Advisor werden die Signale nur basierend auf der "Qualität" der Muster gefiltert. Das ist nicht ausreichend, umso mehr als das "Qualitätskriterium" dieses Musters nur vorläufig definiert wurde und falsch sein kann.

Trotz dem negativen Ergebnis gibt es auch erfolgsträchtige Resultate. Im ersten Teil des Artikels konnte man sehen, dass das zu betrachtende Muster positive Ergebnisse auf H4 liefert. Das Muster, um welches es jetzt geht, zeigte sich gut auf dem Zeitrahmen H1. Das Ergebnis ist negativ, aber es gab auch Gewinne, die Tendenz zur Senkung der Profitabilität ist nicht so steil:

Man kann vermuten, dass wir Erfolgsaussichten haben, wenn wir den Expert Advisor und seine Einstellungen ein wenig ändern. Wie wir sehen, wurden beim Testen Gewinne erzielt. Es gab ausreichend Trades, aber die Kurve weist relativ tiefe Rückgänge auf, was von Folgen negativer Ergebnisse spricht. Allerdings sind auch Folgen positiver Ergebnisse zu verzeichnen! Versuchen wir die Profitabilität des Musters in diesem Zeitrahmen zu steigern, indem wir Änderungen im Code des Expert Advisors vornehmen.

Korrektur der Form des Musters

Das erste, was einem einfällt, ist die Änderung der Form des Musters, und zwar der Werte der Parameter Delta1 und Delta2. Ursprünglich wählten wir 5% aus. Vielleicht versuchen wir, diesen Wert zu ändern? Wenn wir ihn verkleinern, wird die Anzahl der Einstiege in den Markt erhöht. Wenn wir ihn erhöhen, sinkt die Anzahl der Einstiege, aber gleichzeitig steigt die "Stärke" des Musters, die Geschwindigkeit seiner Bewegung, und demzufolge auch der "Impuls zur Trendänderung".

Daraus folgt: man darf diesen Wert weder vergrößern noch verkleinern! Aber es ist auch falsch zu denken, dass der ausgewählte Wert optimal ist. Wenn wir ihn bereits in dieser Phase optimieren, riskieren wir einen Wert zu bekommen, der gute Ergebnisse auf einem bestimmten Zeitintervall, bestimmten Zeitrahmen und einem bestimmten Währungspaar erzielt. Mit anderen Worten, gibt es keine Garantien dafür, dass der erhaltene Wert universell sein wird.

Es ist aber sinnvoll, einen anderen Schritt in dieser Richtung zu machen. Die Werte Delta1 und Delta2 sollten "von oben" begrenzt werden, man muss einen Höchstwert setzen. Das wird damit rechtfertigt, dass ein zu "großes" Muster die Dynamik der Bewegung in sich selbst ausschöpfen kann. Dann wartet der Trader nach dem Einstieg in den Markt nicht auf die Fortsetzung der Bewegung, sondern auf einen Seitwärtsmarkt oder auf eine Trendänderung. Darüber hinaus kann sich das "große" Muster neben der Grenze der entgegengesetzten Seite des Bereichs des vereinigten WPR zu Ende sein, was auch sehr schlecht für den Einstieg bei der Fortsetzung eines existierenden Trends ist.

Legen wir aus diesem Grund fest, dass der Höchstwert für Delta1 und Delta2 10% ist. Dann beträgt die "Größe" des Musters Delta1 + Delta2 = 20%. Das ist nicht zu viel. Nehmen wir einige Änderungen im Expert Advisor vor:

1. Fügen wir eine globale Variable hinzu:

double g_dMaxSize = 10.0;

2. Ändern wir die Funktion für die Verarbeitung der Ereignisse des Timers:

void OnTimer()
  {
   if(IsNewCandle())
     {
      wl=w[0];
      CopyBuffer(h,0,1,1,w);
      ml=m[0];
      CopyBuffer(h,1,1,1,m);
      double d1 = MathAbs(w[0] - m[0]);
      double d2 = MathAbs(ml - wl);
      if(w[0]>m[0] && wl<ml) 
        {
         if(g_state!=BCLOSE) CloseAllPos();
         if(d1 >= g_dMinSize && d2 >= g_dMinSize &&
            d1 <= g_dMaxSize && d2 <= g_dMaxSize) 
           {
            EnterBuy(lt);
            g_state=BBUY;
           }
        }
      if(w[0]<m[0] && wl>ml) 
        {
         if(g_state!=BCLOSE) CloseAllPos();
         if(d1 >= g_dMinSize && d2 >= g_dMinSize &&
            d1 <= g_dMaxSize && d2 <= g_dMaxSize) 
           {
            EnterSell(lt);
            g_state=BSELL;
           }
        }
     }
  }


Setzen wir das Testen mit dem geänderten Expert Advisor auf dem Zeitrahmen H1 fort. Das Testergebnis ist in der angehängten Zip-Datei testEAbasket1.zip zu finden. Das Ergebnis:


Die positiven Veränderungen fallen sofort auf. Das Ergebnis ist immer noch negativ, aber in absoluten Zahlen ist der Verlust viel kleiner. Die Tendenz zum Verlust der Einlage wird durch eine schwankende Seitwärtsbewegung abgelöst. Es sind tiefe Rückgänge, danach ist aber auch Erholung zu verzeichnen. Natürlich reicht dieser Test für finale Schlussfolgerungen nicht aus, man kann aber die Anwendung des Filters nach maximalen Werten von Delta1 und Delta2 als sinnvoll und positiv bezeichnen. Speichern wir die vorgenommenen Änderungen im Code des Expert Advisors.

Weiter werden wir die erhaltenen Werte für Delta1 und Delta2 nicht ändern. Ich möchte noch einmal wiederholen, man darf nicht behaupten, dass die angeführten Werte optimal sind. Behalten wir im Hinterkopf, dass wir diese auf andere Zeitrahmen und Körbe übertragen müssen, und finden wir uns fürs Erste mit dem erhaltenen Ergebnis ab.

Zweiter Filter

Der nächste Schritt ist offensichtlich:

  • Man sollte vorsichtig in den Markt nach einem Trend einsteigen, wenn sich die Grafik des vereinigten WPR (sowie jedes anderen Oszillators) an ihre Grenzen nähert.

Das ist eine bekannte Regel der Verwendung technischer Indikatoren, die auch auf vereinigte Indikatoren zutrifft. In den vorherigen Artikeln haben wir davon gesprochen, dass es in diesem Fall eine Trendwende, eine deutliche Verlangsamung oder eine Seitwärtsbewegung möglich ist. Es bleibt nun diese Annahmen im zweiten Filter des Expert Advisors umzusetzen.

Der vereinigte WPR schwankt in einem Bereich von -100% bis +100%. Wir können uns nicht auf diese Zahlen orientieren, denn der Indikator nähert sich diesen Grenzen, aber erreicht sie nie. Uns sind bereits die Grenzen für Überkauft/Überverkauft bekannt. Im vorherigen Artikel haben wir den Ausbruch dieser Grenzen betrachtet und wir wissen, wo sie sind. Verwenden wir sie.

Definieren wir die Aufgabe genauer.

  • Der Trader kauft den Korb NICHT, wenn der vereinigte WPR die Überkauft-Grenze berührte oder diesen von unten nach oben durchbrochen hat.
  • Der Trader verkauft den Korb NICHT, wenn der vereinigte WPR die Überverkauft-Grenze berührt oder von oben durchbrochen hat.

Die Grenzen für Überkauft haben wir bei 60% - 70% und für Überverkauft bei -60% ... -70% definiert. Für den neuen Filter nehmen wir die unteren Werte der Grenzen: 60% und -60%. Legen wir fest, dass für die Eröffnung einer Kauf-Position die Kurve des vereinigten WPR unterhalb der Grenze des Filters liegen muss, für die Eröffnung einer Verkaufsposition — oberhalb dieser Grenze. Mit anderen Worten versuchen wir nicht ein "vollständiges" Muster der Kreuzung des gleitenden Durchschnitts zu ermitteln, sondern beschränken wir uns auf eine Filterung, die in der technischen Analyse verwendet wird:

  • Berücksichtigt wird nur die gegenseitige Lage des gleitenden Durchschnitts und der Grafik des Indikators in Bezug auf "höher — tiefer".

Nehmen wir minimale Veränderungen im Codeblock mit den Bedingungen für den Einstieg vor:

       if(w[0]>m[0] && wl<ml) 
        {
         if(g_state!=BCLOSE) CloseAllPos();
         if(d1 >= g_dMinSize && d2 >= g_dMinSize &&
            d1 <= g_dMaxSize && d2 <= g_dMaxSize && w[0] < 60) 
           {
            EnterBuy(lt);
            g_state=BBUY;
           }
        }
      if(w[0]<m[0] && wl>ml) 
        {
         if(g_state!=BCLOSE) CloseAllPos();
         if(d1 >= g_dMinSize && d2 >= g_dMinSize &&
            d1 <= g_dMaxSize && d2 <= g_dMaxSize && w[0] > -60) 
           {
            EnterSell(lt);
            g_state=BSELL;
           }
        }


Testen wir den Expert Advisor im vorher ausgewählten Zeitintervall und auf H1. Das Testergebnis:


Eine vollständige Zip-Datei ist in testEAbasket2.zip zu finden. Wie wir sehen, unterscheiden sich die Ergebnisse nicht wesentlich von den vorher erzielten, obwohl eine kleine Tendenz zur Verbesserung der Situation zu verzeichnen ist.

Woran liegt das? Vielleicht daran, dass die Überkauft/Überverkauft-Levels nicht genau genug festgelegt wurden. Vielleicht an der kleinen Anzahl der gefilterten Trades. Vielleicht auch an beidem.

Bedeutet das erhaltene Ergebnis, dass die Anwendung des Filters sinnlos war? Nein. Diese Schlussfolgerung kann man erst nach der Anwendung des Filters auf allen Körben, auf allen ausgewählten Zeitrahmen und auf größeren Zeitintervallen (größer als ein Jahr) ziehen. Deswegen lassen wir diesen Filter im Code des Expert Advisors, aber dessen Anwendung steht in Frage.

Abschluss der Arbeit mit dem Muster

Wir haben den Arbeitsplan mit dem oben beschriebenen Muster anhand des USD-Korbes umgesetzt. Die finale Version des Expert Advisors ist in der angehängten Datei testEAbasketFinal.mq5 zu finden. Auf Basis der durchgeführten Tests kann man die wichtigste Schlussfolgerung ziehen:

  • Als Einstiegssignal sollte dieses Muster nicht verwendet werden.

Es stellt sich die Frage: sollten die Tests mit anderen Körben durchgeführt werden? Man kann das Ergebnis mit einer hohen Wahrscheinlichkeit vorhersagen.

Die Grundannahme, die es uns erlaubt, keine Tests auf anderen Körben durchzuführen, besteht darin, dass Muster basierend auf dem Ausbruch eines einzelnen MA fast nie als ein eigenständiges Signal für den Einstieg in der technischen Analyse beim echten Handel verwendet werden. Nun versuchen wir das Muster, bei welchem der vereinigte WPR einen gleitenden Durchschnitt kreuzt, als Filter zu verwenden. Als Hauptsignal für den Einstieg betrachten wir das Muster des Ausbruchs der Überkauft/Überverkauft-Levels durch denselben vereinigten Indikator. Unser Ziel besteht darin, herauszufinden, wie ein solcher Filter die Profitabilität beeinflusst.

Verwendung des Musters als Filter

Formulieren wir die Aufgabe.

  • Der vereinigte WPR durchbricht den Überkauft-Level von unten nach oben. Der Ausbruch wird beim Schließen der Kerze überprüft. Der Trader eröffnet eine Kaufposition nur in dem Fall, wenn der gleitende Durchschnitt "unterhalb" des vereinigten Indikators liegt.
  • Um eine Verkaufsposition zu eröffnen, muss eine Situation vorhanden sein, die der im vorherigen Punkt beschriebenen entgegengesetzt ist.
  • Für den Ausstieg muss die Grafik des vereinigten WPR den Bereich bei 0% erreichen.

Es fällt auf, dass es wieder nicht das "vollständige" Muster, sondern eine "vereinfachte" Version verwendet wird, und zwar der Filter "höher — tiefer", angewandt auf die gegenseitige Lage des gleitenden Durchschnitts und der Grafik des vereinigten WPR.

Ändern wir den Expert Advisor testEAbasket.mq5 für das Testen. Fügen wir ihm die Inputdaten für die Beschreibung des Überkauft/Überverkauft-Levels und die Bedingungen der Anwendung des Musters als Filter hinzu:

input int SELLPROFIT =   0;
input int SELL1LIMIT =  70;
input int SELL2FROM  =  60;
input int SELL2TO    =  50;

input int BUYPROFIT  =   0;
input int BUY1LIMIT  = -70;
input int BUY2FROM   = -60;
input int BUY2TO     = -50;

//...................................................................

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   if(IsNewCandle())
     {
      wl=w[0];
      CopyBuffer(h,0,1,1,w);
      ml=m[0];
      CopyBuffer(h,1,1,1,m);

      if(g_state==BBUY && (w[0]>=BUYPROFIT))
        {
         CloseAllPos();
        }
      if(g_state==BSELL && (w[0]<=SELLPROFIT))
        {
         CloseAllPos();
        }
      if(g_state==BCLOSE && w[0]>=BUY2FROM && w[0]<=BUY2TO && wl<=BUY1LIMIT && w[0] > m[0])
        {
            EnterBuy(lt);
            return;        
        }
        
       
      if(g_state==BCLOSE && w[0]<=SELL2FROM && w[0]>=SELL2TO && wl>=SELL1LIMIT && w[0] < m[0])
        {
            EnterSell(lt);
            return;        
        }
    }
  }

Der komplette Code des Expert Advisors ist in der agehängten Datei testEAbasket1.mq5 zu finden.

Für das Testen wird der Zeitrahmen H1 verwendet. Auf diesem Zeitrahmen wurde die maximale Anzahl von Trades festgestellt, dabei war das Ergebnis sehr negativ. Dieses Ergebnis kann man im vorherigen Artikel sehen, hier werden wir den Test nicht wiederholen.

Führen wir einen Test durch und verwenden wir das Musters aus diesem Artikel als Filter für ein Jahr. Wir erhalten das folgende Ergebnis:

Die Verwendung des Musters aus diesem Artikel als Filter hat offentsichtlich positive Ergebnisse geliefert! Wir haben eine glatte Kurve erhalten mit einer Tendenz zur Erhöhung des Profits. Leider gibt es nicht so viele Trades, wie wir wollten. Bei der Anwendung des Expert Advisors auf höheren Zeitrahmen geht diese Anzahl noch zurück.

Der komplette Testbericht ist in der Zip-Datei Tester_EURUSD_Filter.zip beinhaltet.

Fazit

Wie haben das Testen der Muster abgeschlossen, die bei der Anwendung vereinigter Indikatoren basierend auf Oszillatoren für ein separates Währungskorb auftreten. Als Grundlage wurde ein vereinigter WPR genommen, aber die Ergebnisse gelten auch für RSI und Stoch.

Man muss zugeben, es ist noch weit bis zur praktischen Anwendung der Muster. Die erhaltene Statistik ist deutlich nicht ausreichend. Dies gilt sowohl für Zeitintervalle des Testens als auch für Parameter der Muster. Strittig bleibt auch die Frage der Auswahl der МА-Periode aus diesem Artikel.

Wir haben auch interessante Ergebnisse erhalten.

  1. Wir haben die Lage der Überkauft/Überverkauft-Levels ausgewertet und die Aussichten der Arbeit mit diesen Levels überprüft.
  2. Wir haben die Aussichten der Anwendung des Musters betrachtet, in welchem die Grafik eines vereinigten Indikators einen gleitenden Durchschnitt kreuzt.
  3. Wir haben die Möglichkeit einer gemeinsamen Anwendung der Muster aus den zwei vorherigen Punkten geprüft.

Man kann sagen, dass wir den ersten Schritt auf dem Weg zur Anwendung dieser Methode gemacht haben.

Die im Artikel verwendeten Programme:

 # Name
Typ
 Beschreibung
1 testWPR&MA.mq5 Indikator
Indikator für die Prüfung, wie oft der vereinigte Indikator den gleitenden Durchschnitt kreuzt.
2
testEAbasket.mq5 Expert Advisor
Expert Advisor für das Testen.
3
testEAbasket.zip Zip-Datei Standardberichte über die Ausführung des Expert Advisors testEABasket.mq5 mit dem USD-Korb im HTML-Format.
 4 testEAbasket1.zip Zip-Datei Standardbericht über die Ausführung des Expert Advisors testEABasket.mq5 mit dem USD-Korb und dem ersten Filter im HTML-Format.
5
testEAbasket2.zip Expert Advisor Standardbericht über die Ausführung des Expert Advisors testEABasket.mq5 mit dem USD-Korb und zwei Filtern im HTML-Format.
 6  testEAbasketFinal.mq5 Expert Advisor
Finale Version des Expert Advisors testEAbasket.mq5.
7 testEAbasket1.mq5
Expert Advisor Expert Advisor für das Testen.
 8  Tester_EURUSD_Filter.zip Zip-Datei Zip-Datei mit Testberichten des Expert Advisors testEAbasket1.mq5.