MetaTrader 5 herunterladen

Schutz vor Falschauslöser bei Handelsroboter

30 August 2016, 15:12
Aleksandr Masterskikh
0
897

Einführung

In diesem Artikel beschreiben wir Wege der Verbesserung der Stabilität eines Handelsroboters durch die Beseitigung von möglichen Mehrfachauslösungen (Geknatter) auf unterschiedliche Weise: beide verwenden die Ein- und Ausstiegsalgorithmen sowohl separat wie in Verbindung.


Die Natur des Problems

Das Problem von Falschauslösungen entsteht häufig bei Kurseinbrüchen oder heftigen Kursanstiegen des Marktes, wenn eine Kerze sehr lang wird und es keine Vorkehrung gegen Mehrfachauslösungen im Algorithmus des Handelsroboters gibt. Das verursacht sich wiederholende Positions-Eröffnungen und -Schließungen während der aktuellen Kerze.

Die finanziellen Auswirkungen können unterschiedlich sein und hängen von der speziellen Behandlung der Marktparameter durch den Handelsroboter ab. In jedem Fall steigen die Ausgaben für die Spreads proportional mit der Zahl Auslöser durch die Mehrfachauslösungen.

In diesem Artikel werde ich mich nicht mit der Analyse der finanziellen Instrumente (sein es technische oder fundamentale) beschäftigen, die die Stabilität der Arbeitsweise des Expert Advisors beeinflussen und die Mehrfachauslösungen vermeiden könnten (das ist ein anderes Thema — ich bin der Autor der Theorie von Impuls und Gleichgewicht und eines Systems auf dessen Basis). Hier konzentrieren wir uns auf das Messen der Software, die nicht direkt von den Methoden der Marktanalyse abhängt.

Schreiten wir zur Lösung des Problems. Als Beispiel verwende ich den Expert Adviser "MACD Sample" aus der Grundausstattung des Nutzerterminal des МetaТrader 4.

So schaut das Problem der Mehrfachauslösung aus, am Beispiel des EURUSD, der am 2. Okt. 2015 (М15 Zeitrahmen, "MACD Sample" EA mit seiner Standardeinstellung):

Das Bild zeigt deutlich 8 Auslöser, nacheinander (Kaufaufträge), während einer einzigen Kerze. Aber nur einer wäre richtig gewesen (bezogen auf die Handelslogik), die anderen 7 sind "Geknatter"

Die Gründe für die falschen Auslöser in diesem speziellen Fall sind:

  • Der kleine Wert des Take-Profit ist in der Standardeinstellung (Schließalgorithmus) und daher wird jede Position sofort wieder geschlossen;
  • ebenso löst der Eröffnungsalgorithmus des "MACD Sample"-EA nach dem Schließen der vorherigen Position aus und das führt zur nächsten Positionseröffnung unabhängig von der Anzahl der Positionen während derselben Kerze.

Wir haben uns darauf festgelegt, die Schwankungen des Marktes selbst nicht zu filtern (jeder Händler hat ja seine eigenen Ein- und Ausstiegsalgorithmen), wir müssen uns daher für die Lösung des Problems auf folgende Faktoren beschränken:

  • Zeit (Dauer der Kerze),
  • Anzahl der Auslösungen (Zähler),
  • die Amplitude der Bewegung (Höhe der Kerze).


Der Eröffnungsalgorithmus

Die einfachste und zugleich die zuverlässigste Methode zur Behebung des Eröffnungsproblems ist der Faktor Zeit, aus folgenden Gründen:

  • Ein Zähler der Auslöser bedingt eine Schleife im Programm, die nicht nur den Algorithmus verkompliziert, sondern auch die Ausführungsgeschwindigkeit des Expert Advisor reduziert.
  • Die Amplitudenhöhe und das damit verbundene Preisniveau kann sich während der Kerzendauer drehen und führt so zu keinem eindeutigen Kriterium.
  • Die Zeit ist unumkehrbar, sie bewegt sich nur in eine Richtung (Zeitwert steigt), und ist damit das genaueste und ein eindeutiges Kriterium für die Lösung unseres Problems durch einen Einmal-Auslöser oder dem Entfernen des "Geknatters".

So ist der Hauptfaktor nur die Positionseröffnung (OrderSend) und nicht der Auslöser des Algorithmus, da er abweichen kann, falls z.B. eine Wartezeit existiert.

Wir speichern daher den Zeitpunkt (Serverzeit) der Positionseröffnung. Aber wie verwenden wir jetzt diesen Wert, um eine zweite Positionseröffnung während dieser Kerze zu verhindern? Wir wissen diesen Wert nicht im Vorhinein (seinen Absolutwert), er kann daher nicht Teil des Eröffnungsalgorithmus sein. Der Algorithmus sollte bestimmte, allgemeine Bedingungen beachten (beinhalten), die die erste Position der Kerze betreffen, aber alle weiteren verhindert ohne die Auslöser zu berechnen (die Möglichkeit eines Zähler hatten wir ja bereits verworfen).

Die Lösung ist ziemlich einfach. Schreiben wir zuerst den Code mit Kommentaren und erläutern ihn dann im Detail. Die ist ein Hilfscode (gelb hervorgehoben), der in den Algorithmus des Expert Advisor kopiert werden muss (siehe MACD_Sample_plus1.mq4):

//+------------------------------------------------------------------+
//|                                                  MACD Sample.mq4 |
//|                   Copyright 2005-2014, MetaQuotes Software Corp. |
//|                                              https://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2005-2014, MetaQuotes Software Corp."
#property link        "https://www.mql4.com"

input double TakeProfit    =50;
input double Lots          =0.1;
input double TrailingStop  =30;
input double MACDOpenLevel =3;
input double MACDCloseLevel=2;
input int    MATrendPeriod =26;
//--- Einfügen einer neuen Variablen (Wert in Sekunden für eine Kerze dieses Zeitrahmens, für М15 wäre es 60 sec. * 15 = 900 sec)
datetime Time_open=900;
//--- Einfügen einer neuen Variablen (Eröffnungszeitpunkt der Kerze des 1. Position)
datetime Time_bar = 0;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick(void)
  {
   double MacdCurrent,MacdPrevious;
   double SignalCurrent,SignalPrevious;
   double MaCurrent,MaPrevious;
   int    cnt,ticket,total;
//---
// initial data checks
// it is important to make sure that the expert works with a normal
// chart and the user did not make any mistakes setting external 
// variables (Lots, StopLoss, TakeProfit, 
// TrailingStop) in our case, we check TakeProfit
// on a chart of less than 100 bars
//---
   if(Bars<100)
     {
      Print("bars less than 100");
      return;
     }
   if(TakeProfit<10)
     {
      Print("TakeProfit less than 10");
      return;
     }
//--- to simplify the coding and speed up access data are put into internal variables
   MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
   MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
   SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
   SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
   MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
   MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);

   total=OrdersTotal();
   if(total<1)
     {
      //--- no opened orders identified
      if(AccountFreeMargin()<(1000*Lots))
        {
         Print("We have no money. Free Margin = ",AccountFreeMargin());
         return;
        }
      //--- check for long position (BUY) possibility
      
      //--- Einfügen einer neuen Zeile (entfernt das Verbot des Wiedereröffnung, wenn eine neue Kerze erscheint)
      if( (TimeCurrent() - Time_bar) > 900 ) Time_open = 900; 
      
      if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious && 
         MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious && 
         (TimeCurrent()-Time[0])<Time_open) //einfügen einer neuen Zeile in den Algorithmus (wird nur einmal ausgeführt, diese Bedingung kann nach dieser Zeile nicht mehr erfüllt werden)
        {
         ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
         if(ticket>0)
           {
            if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
             {
              Print("BUY order opened : ",OrderOpenPrice());
              Time_open = TimeCurrent()-Time[0]; //neue Zeile (speichert das Zeitintervall zwischen Kerzeneröffnung und Positionseröffnung)
              Time_bar = Time[0]; //neue Zeile (speichert den Eröffnungszeitpunkt der Kerze der ersten Position)
             }
           }
         else
            Print("Error opening BUY order : ",GetLastError());
         return;
        }

Mehr dazu:

Statt dem Zeitpunkt (der Eröffnung) verwenden wir den Zeitabstand zwischen Eröffnung der Kerze und der Position. Diesen Wert vergleichen wir mit dem vorher gespeicherten Dauer einer Kerze und das erlaubt uns die erste Position als solche zu erkennen. Im Moment der Eröffnung einer Position ändern (verringern) wir den Wert der Variablen Time_open durch das Überschreiben mit dem Zeitintervall zwischen der Eröffnung der Kerzen und der Eröffnung. Ab jetzt würde jeder Wert von (TimeCurrent() - Time[0]) größer sein als der, den wir gespeichert haben und die Bedingung (TimeCurrent() - Time[0]) < Time_open kann nicht mehr erfüllt werden und blockiert so die Eröffnung weiterer Positionen.

So konnten wir ohne Zähler und ohne Analyse der Kerzengröße das Problem der Mehrfachauslösung lösen.

Unten ist das Ergebnis dieser einfachen Verbesserung des Algorithmus des EAs ("MACD Sample_plus1"):

Wir sehen nur eine Position während der Kerze, keine falschen Auslöser und kein "Geknatter". Die Standardeinstellung wurden nicht geändert, damit ist klar, das Problem wurde ohne Änderungen der Einstellungen des EAs erreicht.

Jetzt, da wir das Problem des "Geknatters" gelöst haben, verbessern wir den Algorithmus der Positionseröffnung, um ein mögliches "Geknatter" durch ein zu schnelles Schließen der Position auszuschließen und in diesem Fall auch noch den Gewinn zu erhöhen (gute Dynamik, aber vorzeitiges Positionsende).


Lösung des Exit-Algorithmus'

Da das ursprüngliche Problem die Beseitigung eines möglichen "Geknatters" ist und nicht der Erhöhung des Gewinns, werde ich nicht die Dynamik des Marktes berücksichtigen, sondern mich auf eine Verbesserung der Parameter beschränken.

Bisher haben wir einen zuverlässigen Parameter, den Faktor Zeit, verwendet, und den werden wir wieder verwenden für die Bestimmung des Zeitpunktes die Position zu schließen, um genau zu sein, zum Zeitpunkt der Eröffnung der neuen Kerze (nach der Positionseröffnung). Dieser Moment des Algorithmus für das Schließen sieht so aus:

if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))
         continue;
      if(OrderType()<=OP_SELL &&   // check for opened position 
         OrderSymbol()==Symbol())  // check for symbol
        {
         //--- long position is opened
         if(OrderType()==OP_BUY)
           {
            //--- should it be closed?
            if(/* MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && // entfernter Code, der das Schließen durch den MACD auslöst, um die neuen Bedingungen nicht zu beeinflussen (siehe unten)
               MacdCurrent>(MACDCloseLevel*Point) &&
             */
               Bid > OrderOpenPrice() &&  // neue Zeile - optional (Position ist im Gewinn)
               TimeCurrent() == Time[0] ) // neue Zeile (simple Verbesserung des Algorithmus: Schließen nur beim Erscheinen der neuen Kerze)
              {
               //--- close order and exit
               if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet))
                  Print("OrderClose error ",GetLastError());

               return;
              }

Mit diese keinen Änderungen funktioniert der Algorithmus für die Eröffnung (Positionseröffnung, kein Bedingungen für das Schließen), die Position bleibt bis TimeCurrent() == Time[0] und schließt zugleich mit dem Beginn der neuen Kerze nach dem Impuls. Gelegentlich macht auch der Schutz vor dem "Geknatter" einen schönen Gewinn (siehe Bild "MACD Sample_plus2"):

Dafür mussten wir den Auslöser, die Position durch den MACD zu schließen, entfernen, da sonst die notwendigen Bedingungen nicht gegriffen hätten.

Daher konnte das Problem des "Geknatters" durch die Algorithmen jeweils für Eröffnung und Schließen gelöst werden. Diskutieren wir nun die gegenseitige Abstimmung dieser beiden Algorithmen.


Verknüpfung der Algorithmen für das Eröffnen und Schließen von Positionen

Ein Verbinden impliziert bestimmte vorbereitende Schritte des Gesamtprozesses: Positionseröffnung — Kontrolle — Positionsschließung. Das spiegelt sich auch im Versatz der Indikatoren und der Funktionen, die im Algorithmus für das Eröffnen und Schließen verwendet werden.

Zum Beispiel, wenn Sie die Bedingung TimeCurrent() == Time[0] zum Schließen verwenden, ist das Ende der Position strikt an den Beginn einer neuen Kerze gebunden, aber dann sollte die Eröffnung während der vorherigen Kerze ausgeführt werde, damit die Bedingung wahr werden kann. Daher, um eine Position unter der Bedingung TimeCurrent() == Time[0] ohne zusätzliche Bedingungen zu schließen, muss der gesamte Vergleichsalgorithmus (beim Schließen) während der vorherigen Kerze durchgeführt (beendet) werden. Es sollten daher alle für den Vergleich relevanten Indikatoren um 1 (offset) versetzt werden. In diesem Fall ist der Vergleich der Werte korrekt und der Beginn einer neuen Kerze wird zum logischen Ende einer Position.

Auf diese Weise verbindet sich die Eröffnung und das Schließen einer Position mit dem Zeitfaktor.


Schlussfolgerung

Das Problem falscher Auslöser eines Expert Advisors wurde elegant gelöst durch einen Zeitfaktor im Algorithmus für die Positionseröffnung. Zusätzliche operative Stabilität eines EA kann durch eine Bestimmung des Momentes des Schließens einer Position (zum Beispiel, zeitlich) und durch eine Verbindung der beiden Algorithmen durch vorbereitende Bearbeitung der Hauptlogik der Auslösung und des Versatzes (offset) erreicht werden (die Kerze der Berechnung der Indikator- oder Funktionsberechnung).

Nachfolgend finden Sie die Codes der EAs: der ursprüngliche (MACD_Sample.mq4), mit verbesserter Positionseröffnung (MACD_Sample_plus1.mq4) und mit verbessertem Ausstieg (MACD_Sample_plus2.mq4). Nur Kauforders wurden verbessert, Verkauforders wurden bewusst nicht verändert, um einen Vergleich der beiden zu ermöglichen.

Und, natürlich gilt, alle angebenden EAs sind nur zu Demonstrationszwecken und sind nicht gedacht für den Einsatz auf realen Konten in den Finanzmärkten.

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

Beigefügte Dateien |
MACD_Sample.mq4 (6.1 KB)
Fuzzy-Logik für eine manuelle Handelsstrategie Fuzzy-Logik für eine manuelle Handelsstrategie

Dieser Artikel zeigt die Möglichkeiten der Verbesserung einer manuelle Handelsstrategie durch die Verwendung der Theorie der unscharfen Mengen (fuzzy sets). Als Beispiel bieten wir eine Schritt-für-Schritt-Beschreibung der Suche nach einer Strategie und die Auswahl der Parameter, gefolgt von der Anwendung der Fuzzy-Logik, um allzu formale Kriterien für den Markteintritt zu verwischen. So erhalten wir nach einer Strategie-Modifikation flexible Bedingungen für die Eröffnung einer Position als eine angemessene Reaktion auf eine Marktsituation.

Verwendung von Textdateien zum Speichern von Eingabeparametern von Expert Advisors, Indikatoren und Skripts Verwendung von Textdateien zum Speichern von Eingabeparametern von Expert Advisors, Indikatoren und Skripts

Der Artikel beschreibt die Anwendung von Textdateien zum Speichern von dynamischen Objekten, Arrays und anderen Variablen die als Eigenschaften für Expert Advisors, Indikatoren und Skripts verwendet werden. Die Dateien dienen als eine bequeme Erweiterung der Funktionalität der Standardtools, die von der MQL-Sprache angeboten werden.

Thomas DeMarks Beitrag zur technischen Analyse Thomas DeMarks Beitrag zur technischen Analyse

Die Artikel beschreibt die TD-Punkte und TD-Linien, entdeckt von Thomas DeMark. Ihre praktische Verwendung wird gezeigt. Darüber hinaus wird demonstriert, wie drei Indikatoren und zwei Expert Advisors nach dem Konzepten von Thomas DeMark geschrieben werden.

Tiefes Neuronales Netzwerk mit geschichtetem RBM. Selbsttraining, Selbstkontrolle Tiefes Neuronales Netzwerk mit geschichtetem RBM. Selbsttraining, Selbstkontrolle

Dieser Artikel ist eine Fortsetzung des vorherigen Artikels über über tiefe Neuronale Netzwerke und Prädikatorauswahl. Wir besprechen hier die Eigenschaften der Neuronalen Netzwerke in Form des "Stacked RMB" (geschichtete Restricted Boltzmann Maschine) und deren Umsetzung durch das Paket "darch".