English Русский 中文 Español 日本語 Português
preview
Testen und Optimieren von Strategien für binäre Optionen in MetaTrader 5

Testen und Optimieren von Strategien für binäre Optionen in MetaTrader 5

MetaTrader 5Tester | 29 März 2023, 10:34
211 0
Roman Poshtar
Roman Poshtar

Einführung

Vor Kurzem begann ich mich für binäre Optionen zu interessieren. Nachdem ich im Internet gesurft und mir die Broker angesehen hatte, stellte sich heraus, dass fast alle ihre Plattformen für den Handel nutzen. Diese Plattformen sind nicht in der Lage, Strategien zu testen, und verfügen bestenfalls über einen mageren Satz von Standardindikatoren. Nachdem ich mir eine große Anzahl verschiedener Strategien für binäre Optionen angesehen hatte, begann ich mich zu fragen, wie man diese Strategien und ihre Optimierung überprüfen kann. Wie immer kam mir unser geliebter MetaTrader 5 zu Hilfe. Uns auch wie immer werde ich versuchen, meine Experimente so einfach wie möglich zu gestalten und das Material ohne komplexe Gleichungen und Codes zu präsentieren. Doch zunächst ein wenig Theorie und Argumente, ob es sich lohnt, sich mit binären Optionen zu beschäftigen oder nicht.


Theorie

Eine binäre Option ist ein digitaler Vertrag, dessen Gegenstand die Vorhersage der Kursrichtung eines Vermögenswertes in einem bestimmten Zeitraum ist. Die Aufgabe besteht darin, eines der beiden möglichen Szenarien für die Entwicklung der Marktsituation richtig zu bestimmen: ob der Vermögenswert steigen oder fallen wird. Heute haben wir eine große Auswahl an Online-Optionen für Währungen, Wertpapiere und Rohstoffe. Praktisch alles (einschließlich einer Wettervorhersage) kann ein Handelsgegenstand sein. Der Handel erfordert keine großen Investitionen und kein tiefes finanzielles und wirtschaftliches Wissen im Bereich der Börsenprozesse.


Arten von binären Optionen

High/Low ist die einfachste Art von binären Optionen , da der Händler nur bestimmen muss, in welche Richtung der Preis gehen wird. Bei einem Aufwärtstrend ist es ratsam, High (Call) zu kaufen. Während Low (Put) gekauft wird, wenn eine Abwärtsbewegung des Vermögenswerts erwartet wird. Der Gewinn von High/Low-Optionen schwankt zwischen 10% und 80% des Einsatzes.

Ein „touch“ stellt eine Vereinbarung dar, in der es darum geht, die Erreichung des gewünschten Preisniveaus zu bestimmen. Es spielt keine Rolle, wo die Notierungen während eines Abschlusses stattfinden. Das Berühren eines bestimmten Levels ist ausreichend. Die Rentabilität von „One touch“ ist höher als üblich und kann bis zu 95 % erreichen, da es in den meisten Fällen sehr schwierig ist, sie vorherzusagen, aber Sie können Ihre ganzen 100 % verlieren.

Range bestimmt einen Preiskorridor, innerhalb dessen sich der Wert des Vermögenswerts zum Zeitpunkt des Verfalls befindet. Auch das ist schwer zu verstehen und vorherzusagen. Die Rentabilität beträgt bis zu 95 %.

Im Folgenden werde ich Strategien für High/Low-Optionen testen und optimieren, da diese meiner Meinung nach am beliebtesten sind.


Vorteile und Nachteile

Die Vorteile sind wie folgt:

  • Einfachheit - Sie legen die Höhe der potenziellen Verluste oder Gewinne fest und müssen keine komplexen Berechnungen der Stop-Loss- und Take-Profit-Preise vornehmen, was besonders für Anfänger nützlich ist.
  • Einfache Registrierung auf der Website des Optionsmaklers - kein Paket von Dokumenten erforderlich.
  • Die größte Vielfalt an Ressourcen - Unternehmensaktien, Aktienindizes, Öl, Gold, Kryptowährungen mit dem Anfangskapital ab $100 oder sogar weniger. Der Handel an den Aktien- oder Futures-Märkten erfordert einen höheren Betrag als Ersteinlage.

Nachteile

  • Hohe Risiken und negative Erwartungen. Zweimal gewinnen ist nötig, um einmal verlieren auszugleichen. Gewinnmöglichkeit bis zu 80 %. Eine verlustbringende Operation wird mehr kosten als eine gewinnbringende.
  • Der „Casino“-Modus bringt auf lange Sicht Verluste. Manche versuchen, beim Handel Tricks aus dem Casino oder Durchschnittsmethoden wie Martingale anzuwenden, was gegen die Regeln des korrekten Handels verstößt und letztlich zur Vernichtung der Einlage führt.
  • Große Provisionen,

    Währungspaar, Optimierung und Vorwärtstestbereich, Einstellungen

    Nachstehend finden Sie alle Optimierungs- und Testparameter:

    • Forex;
    • EURUSD;
    • M5, M15, M30, H1;
    • Verfallszeit 5, 15, 30 Minuten und 1 Stunde.
    • Optimierungsbereich 1 Jahr. 2021.01.28 - 2022.01.28 .
    • Vorwärtstestlänge beträgt 1 Jahr. 2022.01.28 - 2023.01.28;
    • Ersteinlage 10.000;
    • Rate 10;
    • Zinssatz 80%.

      Technische Aspekte

      Wir brauchen Eingaben für Tests und Optimierung:

      1. StartDepo - Ersteinlage;
      2. OptionRate - Kurs;
      3. ExpirationTime - Verfallszeit;
      4. ProfitPercent - Rentabilitätsprozentsatz;
      5. TimeFrame - Indikator Zeitrahmen;
      6. Optimierung - Optimierungsschalter;
      7. OptimizationFileName – Dateiname für die Speicherung der Optimierungsergebnisse.
      input string N0 = "------------Open settings----------------";
      input double StartDepo = 10000;
      input int OptionRate = 10;
      input string N1 = "------------Close settings---------------";
      input int ExpirationTime = 1; //ExpirationTime 1=5 min, 2=15 min, 3=30 min, 4=60 min
      input double ProfitPercent = 80;
      input string N2 = "------------Optimization settings--------";
      input int TimeFrame = 1; //TimeFrame 1=5 min, 2=15 min, 3=30 min, 4=60 min
      input bool Optimization = false;
      input string OptimizationFileName = "Optimization.csv";
      input string N3 = "------------Other settings---------------";
      input int Slippage = 10;
      input int Magic = 111111;
      input string EAComment = "2Ma+RSI+Stochastic Oscillator";

      Wir werden auch Variablen benötigen, um Änderungen in der Einlage und in der Anzahl der profitablen und unprofitablen Optionskäufe zu speichern und zu verfolgen:

      1. XStartDepo - zum Speichern der aktuellen Einzahlung;
      2. Profit - zum Speichern der Anzahl der profitablen Optionskäufe;
      3. Loss - zur Speicherung der Anzahl der Optionen mit Verlust;
      double XStartDepo = StartDepo;
      int Profit=0;
      int Loss=0;

      Um den Zeitpunkt der Positionseröffnung zu kontrollieren und die Position nach der Verfallszeit im MetaTrader 5 zu schließen, verwenden wir die Funktion, die den Zeitpunkt der Positionseröffnung zurückgibt.

      //+------------------------------------------------------------------+
      //| Get open time in positions                                       |
      //+------------------------------------------------------------------+
      datetime GetTime(string symb="0", int type=-1, int mg=-1,int index=0) {
       datetime p[];
       int c=-1, pr=0;
        if(symb=="0") { symb=Symbol();}
         for(int i=PositionsTotal()-1;i>=0;i--){
            if(position.SelectByIndex(i)) {
           if(position.PositionType()==POSITION_TYPE_BUY || position.PositionType()==POSITION_TYPE_SELL) {
            if((position.Symbol()==symb||symb=="")&&(type<0||position.PositionType()==type)&&(mg<0||position.Magic()==mg)) {
             c++;
             ArrayResize(p, c+1);
             p[c]=position.Time();
             pr=c>=index?index:c;
             
       }}}}
        return(c==-1?0:p[pr]);
       }

      Um die Rentabilität einer Position zu verfolgen und zu entscheiden, ob wir eine Wette gewonnen haben oder nicht, werden wir eine Funktion verwenden, die den Gewinn einer offenen Position zum aktuellen Zeitpunkt zurückgibt. Provisionen und Swaps werden nicht berücksichtigt.

      //+------------------------------------------------------------------+
      //| Get profit in positions                                          |
      //+------------------------------------------------------------------+
      double GetProfit(string symb="0", int type=-1, int mg=-1,int index=0) {
       double p[];
       int c=-1, pr=0;
        if(symb=="0") { symb=Symbol();}
         for(int i=PositionsTotal()-1;i>=0;i--){
            if(position.SelectByIndex(i)) {
           if(position.PositionType()==POSITION_TYPE_BUY || position.PositionType()==POSITION_TYPE_SELL) {
            if((position.Symbol()==symb||symb=="")&&(type<0||position.PositionType()==type)&&(mg<0||position.Magic()==mg)) {
             c++;
             ArrayResize(p, c+1);
             p[c]=position.Profit();
             pr=c>=index?index:c;
             
       }}}}
        return(c==-1?0:p[pr]);
       }

      Wenden Sie mehrere Auslöser an, um nur ein neu eingehendes Signal zu verarbeiten. Mit anderen Worten, die Erlaubnis zum Eröffnen erfolgt erst mit einem neuen Signal. Wiederholte Einträge zum selben Signal werden ignoriert:

      1. TrigerSell - Put-Option kaufen;
      2. TrigerBuy - Call-Option kaufen;
      int TrigerSell=0;
      int TrigerBuy=0;

      Das Verlassen einer Position, das Hinzufügen und Abziehen von Geldmitteln von der anfänglichen Einlage sowie die Berechnung der profitablen und unprofitablen Käufe von Optionen erfolgt durch die Verfolgung der aktuellen Zeit im Verhältnis zur Eröffnung der Position und der Verfallszeit.

      //Sell (Put)
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Verwenden Sie zur Optimierung Variablen, um den gewünschten Zeitrahmen und die Verfallszeit zu bestimmen. Der Optimierungsmodus wird durch die Optimierungsvariable aktiviert. Der Kern der Optimierung liegt in der Verwendung von Dateien wie CSV. Bei der Optimierung erstellen Expert Advisors eine CSV-Datei mit dem Ergebnis unter „C:\Users\Ihr Nutzername\AppData\Roaming\MetaQuotes\Terminal\Common\Files“.

      1. Letzter Saldo;
      2. Anzahl der profitablen Geschäfte;
      3. Anzahl der Verlustgeschäfte;
      4. Zeitrahmen;
      5. Verfallszeit.
      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      
      if (Optimization==true){
       if (FileIsExist(OptimizationFileName)==false){
         filehandle = FileOpen(OptimizationFileName,FILE_WRITE|FILE_READ|FILE_CSV|FILE_COMMON|FILE_ANSI, ";");
          if(filehandle!=INVALID_HANDLE)
           {
            FileSeek(filehandle, 0, SEEK_END);
            FileWrite(filehandle,DoubleToString(XStartDepo),IntegerToString(Profit),IntegerToString(Loss),IntegerToString(XTimeFrame),IntegerToString(XExpirationTime));
            FileClose(filehandle);
           }
       }
      }
      
        }

      Sie können die Tests im Visualisierungsmodus beobachten. Der Einfachheit halber lassen wir uns das aktuelle Ergebnis mit Comment() anzeigen.

      Aktuelles Ergebnis


      Strategien

      Die Strategie mit 2Ma+RSI+Stochastischem Oszillator

      Die Strategie wird von einem bekannten Broker als Scalping-Strategie für binäre Optionen angeboten. Der empfohlene Zeitrahmen beträgt 5 Minuten. Die Verfallszeit beträgt 5 Minuten.

      Indikatoren:

      1. Ein Paar exponentiell gleitender Durchschnitte mit Perioden von 5 und 10;
      2. RSI, Standardeinstellungen;
      3. Stochastischer Oszillator mit den Einstellwerten 14, 3, 3.

      Das „Aufwärts“-Signal (zum Kauf einer Call-Option), wenn eine Reihe von Bedingungen erfüllt sind:

      1. Der rote gleitende Durchschnitt hat den blauen gleitenden Durchschnitt nach oben gekreuzt;
      2. Der RSI liegt über 50;
      3. Die schnelle Stochastik-Linie kreuzte die langsame (gepunktete) Linie nach oben.

      Aufwärtsstrategie 1

      Das „Abwärts“-Signal (zum Kauf einer Put-Option) wird gebildet, wenn bestimmte Faktoren vorhanden sind:
      1. Der rote MA kreuzte den blauen nach unten;
      2. Der RSI liegt unter 50;
      3. Die schnelle Linie des Stochastik-Oszillators kreuzt die langsame Linie nach unten.

      Abwärtsstrategie 1

      Ich habe den Schnittpunkt der MA in der entgegengesetzten Richtung als Auslöser für diese neue Signalstrategie gewählt. Der Strategiecode wird unten angezeigt.

      //Sell (Put)
      
      if((ind_In1S1[1]>ind_In2S1[1]) && (ind_In1S1[2]>ind_In2S1[2])){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (ind_In1S1[1]<ind_In2S1[1]) && (ind_In1S1[0]<ind_In2S1[0]) && (ind_In4S1[1]<50) && (ind_In4S1[0]<50) && (ind_In3S1_1[1]<ind_In3S1_2[1])){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if((ind_In1S1[1]<ind_In2S1[1]) && (ind_In1S1[2]<ind_In2S1[2])){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (ind_In1S1[1]>ind_In2S1[1]) && (ind_In1S1[0]>ind_In2S1[0]) && (ind_In4S1[1]>50) && (ind_In4S1[0]>50) && (ind_In3S1_1[1]>ind_In3S1_2[1])){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Der Test führt zu den folgenden Ergebnissen:

      • Letzter Saldo 1.964;
      • Gewinner 1.273;
      • Verlustgeschäfte 1.822.

      Ergebnis

      Nach der Optimierung erhalten wir das Ergebnis. Wie wir sehen können, haben wir in keinem der Zeitrahmen und Verfallszeiten eine Erhöhung unserer Einlage erhalten.

      Ergebnis der Optimierung


      Maverick Strategie

      Dies ist eine interessante und einfache Optionsstrategie namens Maverick. Sie basiert auf zwei Indikatoren der technischen Analyse. Es wird gesagt, dass es die Einstiegs- und Ausstiegspunkte für den Handel ziemlich genau bestimmt. Der Handel wird in einem Zeitrahmen von 1-5 Minuten angeboten. Um mehr Signale zu erhalten, können wir mehrere Charts mit verschiedenen Vermögenswerten gleichzeitig öffnen.

      Indikatoren:

      1. Bollinger Bands 20 und StDev (Standardabweichung) 2;
      2. RSI-Indikator. RSI-Parameter – 4 mit den Grenzen von 80 und 20.

      Prognose einer Kursaufwärtsbewegung. Kauf einer Call-Option:

      Sobald die Linie des RSI-Indikators in den überverkauften Bereich unter 20 eintritt, während die Kurslinie die Bollinger Bands berührt oder überschreitet, warten Sie auf die erste Aufwärtskerze und eröffnen Sie eine Kaufposition.

      Aufwärtskauf

      Prognose einer Kursabwärtsbewegung. Kauf einer Put-Option:

      Nachdem der RSI-Indikator in den überkauften Bereich über 80 eingetreten ist und die Kurslinie die oberen Bollinger-Grenzen überschritten hat, warten Sie auf die erste Abwärtskerze und eröffnen Sie Verkaufsposition.

      Abwärtskauf

      Ich habe den Abschluss der vorherigen Kerze innerhalb des Bollinger-Indikator-Kanals als neuen Signalauslöser gewählt. Der Strategiecode wird unten angezeigt.

      //Sell (Put)
      
      if(iClose(symbolS1.Name(),XTimeFrame,1)<ind_In1S1_1[1]){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (iClose(symbolS1.Name(),XTimeFrame,2)>ind_In1S1_1[2]) && (ind_In2S1[2]>80) && (iClose(symbolS1.Name(),XTimeFrame,1)<iOpen(symbolS1.Name(),XTimeFrame,1))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if(iClose(symbolS1.Name(),XTimeFrame,1)>ind_In1S1_2[1]){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (iClose(symbolS1.Name(),XTimeFrame,2)<ind_In1S1_2[2]) && (ind_In2S1[2]<20) && (iClose(symbolS1.Name(),XTimeFrame,1)>iOpen(symbolS1.Name(),XTimeFrame,1))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Beginnen wir mit den Tests. Führen wir einen Test auf der M5 durch. Wir erhalten dies Ergebnis:

      • Letzter Saldo 3.312;
      • Gewinner 1.589;
      • Verlustgeschäfte 1.940.

      Ergebnis

      Wir haben einen Verlust erlitten. Das Ergebnis ist allerdings etwas besser als bei der vorherigen Strategie. Führen wir eine Optimierung durch, in der Hoffnung auf positive Einzahlungswerte. Leider funktioniert diese Strategie nicht:

      Ergebnis der Optimierung


       Vortex+TSI-Strategie

      Die Strategie für binäre Optionen heißt Vortex aufgrund der Verwendung des gleichnamigen Indikators. Die Strategie umfasst nämlich zwei Indikatoren - den Hauptindikator und einen zweiten als Filter. Der vorgeschlagene Zeitrahmen beträgt 1-5 Minuten.

      Indikatoren:

      1. Vortex 14;
      2. True Strength Indicator (TSI) 25, 13, 5, Exponential.

      Für den Kauf einer Call-Option:

      1. Warten Sie auf den gleichzeitigen Schnittpunkt der Linien beider Indikatoren, wenn die blauen Linien oben sind und die roten nach unten fallen;
      2. Die Linien des Vortex-Indikators sollten divergieren.

      Aufwärts

      Für den Kauf einer Put-Option:

      1. Warten Sie auf den gleichzeitigen Schnittpunkt der Linien beider Indikatoren, wenn die roten Linien oben sind und die blauen nach unten gehen;
      2. Die Linien des Vortex-Indikators sollten divergieren.

      AbwärtstitlealtAbwärtsalt

      Ein umgekehrtes Kreuzen des True Strength Indicator dient als neuer Signalauslöser. Der Strategiecode wird unten angezeigt.
      //Sell (Put)
      
      if(ind_In1S1_1[1]>ind_In1S1_2[1]){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (ind_In1S1_1[0]<ind_In1S1_2[0]) && (ind_In1S1_1[1]<ind_In1S1_2[1]) && (ind_In2S1_1[0]<ind_In2S1_2[0]) && (ind_In2S1_1[1]<ind_In2S1_2[1]) && (ind_In2S1_1[0]<ind_In2S1_1[1]) && (ind_In2S1_2[0]>ind_In2S1_2[1]) && (ind_In2S1_1[1]<ind_In2S1_1[2]) && (ind_In2S1_2[1]>ind_In2S1_2[2])){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if(ind_In1S1_1[1]<ind_In1S1_2[1]){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (ind_In1S1_1[0]>ind_In1S1_2[0]) && (ind_In1S1_1[1]>ind_In1S1_2[1]) && (ind_In2S1_1[0]>ind_In2S1_2[0]) && (ind_In2S1_1[1]>ind_In2S1_2[1]) && (ind_In2S1_1[0]>ind_In2S1_1[1]) && (ind_In2S1_2[0]<ind_In2S1_2[1]) && (ind_In2S1_1[1]>ind_In2S1_1[2]) && (ind_In2S1_2[1]<ind_In2S1_2[2])){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Es ist nun an der Zeit, unsere Indikatorstrategie zu testen. Führen wir einen Test auf der M5 durch. Wir erhalten dies Ergebnis:

      • Letzter Saldo -3.118;
      • Gewinner 1.914;
      • Verlustgeschäfte 2.843.

      Die Zahl der Verlustgeschäfte ist größer. Der letzte Saldo war sogar negativ. Vielleicht hilft die Optimierung.

      Ergebnis

      Die Optimierungsergebnisse sprechen für sich:

      Ergebnis der Optimierung


      Nachdem ich etwa 10 weitere verschiedene Strategien ausprobiert hatte, ohne das gewünschte Ergebnis zu erzielen, beschloss ich, meine eigene Strategie zu entwickeln. Aufgrund der gewonnenen Erfahrungen beschloss ich, einen anderen Ansatz zu wählen. Die Strategie trägt den Namen New.

      New-Strategie

      Ich werde überverkaufte und überkaufte Situationen als zentralen Teil der Strategie verwenden. Ich habe auch beschlossen, die Mittelwertbildung hinzuzufügen. Obwohl ich gegen eine solche Entscheidung bin, ist es dennoch interessant, die Ergebnisse zu sehen.

      Indikatoren:

      Envelopes 14, 0, 0,1, für die Methode Simple wird Close verwendet.

      Aufwärtssignal oder Kauf einer Call-Option:

      1. Der Bid-Preis liegt unter der unteren Linie des Envelope-Indikators;
      2. Der Abstand in Punkten zwischen der unteren Linie des Envelope-Indikators und dem Briefkurs ist größer als der Wert von Distance.

      Aufwärtssignal alt

      Abwärtssignal oder Kauf einer Put-Option:

      1. Der Bid-Preis ist höher als die obere Linie des Envelope-Indikators;
      2. Der Abstand in Punkten zwischen dem Bid-Preis und der Linie des Envelope-Indikators ist größer als der Wert von Distance.

      Abwärtssignal

      In der Strategie wird kein Auslöser verwendet. Ein neues Einstiegssignal wird ständig überwacht, wenn die Bedingungen erfüllt sind und es keinen offenen Positionen gibt. Nachfolgend finden Sie den Strategiecode ohne Mittelwertbildung:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Testen wir auf der M5. Distance=150. Das Testergebnis ohne Mittelwertbildung ist in der folgenden Abbildung dargestellt:

      Ergebnis 1

      Endgültiger Saldo 8.952; Gewinner 874;

      Verlustgeschäfte 804.

      Es gibt mehr Gewinner als Verlierer, aber wir haben einen Teil der Ersteinlage verloren. Dies ist die negative Erwartung. Bei diesem Ansatz gab es maximal zwei Verluste in Folge, was uns bei der Mittelwertbildung in die Hände spielt. 

      Das Ergebnis der Optimierung ohne Mittelwertbildung ist in der folgenden Abbildung zu sehen. Der Einfachheit und Klarheit halber wurde beschlossen, nur die rentablen Situationen in den Bericht aufzunehmen:

      Optimierungsergebnis 1

      Fügen wir eine Mittelwertbildung hinzu. Ich habe beschlossen, die Anzahl der Mittelwertbildungen zu begrenzen. Zu diesem Zweck habe ich einen neuen Parameter Averaging eingeführt, der standardmäßig auf 4 gesetzt ist. Der Code für die Mittelwertbildungsstrategie ist unten aufgeführt:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+(((XOptionRate*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-(XOptionRate*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+(((XOptionRate*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-(XOptionRate*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Testergebnisse mit Mittelwertbildung. Und schließlich der Erfolg:

      Mittelwertbildung 1

      Optimierungsergebnisse mit Mittelwertbildung:

      Optimierungsergebnis 1

      Die Ergebnisse einer interessanteren Option mit Multiplikation der Rate nach Verlustgeschäften. Der Code ist unten angegeben:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((((XOptionRate*LossIn)*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-((XOptionRate*LossIn)*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((((XOptionRate*LossIn)*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-((XOptionRate*LossIn)*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Ergebnisse der Optimierung einer interessanten Variante:

      Optimierungsergebnis 2


      Schlussfolgerung

      Welche Schlussfolgerungen lassen sich aus all diesen Arbeiten ziehen? 99 % aller Indikatorstrategien funktionieren praktisch nicht. Wenn man den Ansatz ein wenig ändert, ist es möglich, eine gute und profitable Strategie zu entwickeln. Es ist notwendig, alles zu überprüfen, bevor man den Markt betritt. Wie immer hilft uns dabei MetaTrader 5. Übrigens gibt es bereits Optionen mit 100%iger Rentabilität, was zusätzliche Denkanstöße gibt. Sie können alle berücksichtigten Strategien in Form von Expert Advisors im angehängten Archiv herunterladen.


      Übersetzt aus dem Russischen von MetaQuotes Ltd.
      Originalartikel: https://www.mql5.com/ru/articles/12103

      Beigefügte Dateien |
      MQL5.zip (24.76 KB)
      MQL5 Kochbuch — Datenbank für makroökonomische Ereignisse MQL5 Kochbuch — Datenbank für makroökonomische Ereignisse
      Der Artikel behandelt die Möglichkeiten des Umgangs mit Datenbanken, die auf der SQLite-Engine basieren. Die Klasse CDatabase wurde aus Gründen der Bequemlichkeit und der effizienten Nutzung von OOP-Prinzipien entwickelt. Anschließend ist sie an der Erstellung und Verwaltung der Datenbank für makroökonomische Ereignisse beteiligt. Der Artikel enthält Beispiele für die Verwendung mehrerer Methoden der CDatabase-Klasse.
      Messen der Information von Indikatoren Messen der Information von Indikatoren
      Maschinelles Lernen hat sich zu einer beliebten Methode für die Strategieentwicklung entwickelt. Während die Maximierung der Rentabilität und der Vorhersagegenauigkeit stärker in den Vordergrund gerückt wurde, wurde der Bedeutung der Verarbeitung der Daten, die zur Erstellung von Vorhersagemodellen verwendet werden, nicht viel Aufmerksamkeit geschenkt. In diesem Artikel befassen wir uns mit der Verwendung des Konzepts der Entropie zur Bewertung der Eignung von Indikatoren für die Erstellung von Prognosemodellen, wie sie in dem Buch Testing and Tuning Market Trading Systems von Timothy Masters dokumentiert sind.
      Datenwissenschaft und maschinelles Lernen (Teil 10): Ridge-Regression Datenwissenschaft und maschinelles Lernen (Teil 10): Ridge-Regression
      Die Ridge-Regression ist ein einfaches Verfahren zur Reduzierung der Modellkomplexität und zur Vermeidung einer Überanpassung, die bei einer einfachen linearen Regression auftreten kann.
      Wie man einen Expert Advisor auswählt: Zwanzig starke Kriterien für die Ablehnung eines Handelsroboter Wie man einen Expert Advisor auswählt: Zwanzig starke Kriterien für die Ablehnung eines Handelsroboter
      Dieser Artikel versucht, die Frage zu beantworten: Wie kann man die richtigen Expert Advisor auswählen? Welche sind die besten für unser Portfolio, und wie können wir die große Liste der auf dem Markt erhältlichen Handelsroboter filtern? In diesem Artikel werden zwanzig klare und starke Kriterien für die Ablehnung eines Expert Advisors vorgestellt. Jedes Kriterium wird vorgestellt und gut erklärt, um Ihnen zu helfen, eine nachhaltigere Entscheidung zu treffen und eine profitablere Expert Advisor-Sammlung für Ihre Gewinne aufzubauen.