English Русский 中文 Español 日本語 Português Türkçe
preview
Brute-Force-Ansatz zur Mustersuche (Teil III): Neue Horizonte

Brute-Force-Ansatz zur Mustersuche (Teil III): Neue Horizonte

MetaTrader 5Tester | 19 Februar 2021, 09:52
616 0
Evgeniy Ilin
Evgeniy Ilin

Inhaltsverzeichnis


Einführung

Im vorherigen Artikel habe ich gezeigt, dass es möglich ist, profitable Expert Advisors mit dem einfachen Brute-Force-Mechanismus zu erstellen, da dieser Ansatz nicht schlechter ist als andere. Dieses Thema ist eigentlich sehr nah an meinem Artikel "Optimale Vorgehensweise für Entwicklung und Analyse von Handelssystemen", und insbesondere an dessen Abschnitt "Mathematik hinter einer optimalen Suche". Bei der Erstellung dieser Software habe ich hauptsächlich die Ideen verwendet, die in diesem Artikel formuliert wurden. Generell zielt der Artikel auf eine weitere Modernisierung meiner Programm-Algorithmen ab, mit dem Ziel, die Qualität der gefundenen Optionen zu verbessern, sowie für eine detailliertere Marktforschung an verschiedenen Wochentagen und in verschiedenen Zeitkorridoren.

Einige meiner Expert Advisors beweisen die Realisierbarkeit dieses Ansatzes. Es gibt unterschiedliche Muster bei verschiedenen Währungspaaren. Auch gibt es enge Zeitkorridore, die auf allen Paaren funktionieren. Was wir tun müssen, ist eine tiefgreifende Analyse durchzuführen. Das ist es, was wir in diesem Artikel tun werden. Eine solch umfassende Analyse kann nicht ohne zusätzliche Software durchgeführt werden. Bitte beachten Sie, dass ich meine Software nicht als die beste Lösung ansehe.

Das Programm ist als Forschungssoftware entstanden und diente als Hilfswerkzeug für die Analyse verschiedener Assets. Seine Möglichkeiten sind jedoch viel breiter geworden. Wir können also versuchen, das Beste aus diesem Ansatz herauszuholen. Lassen Sie uns dies versuchen. Um ehrlich zu sein, halte ich Ansätze wie neuronale Netzwerke, künstliche Intelligenz und Gradient Boosting für viel fortschrittlicher. Dennoch hat sich gezeigt, dass der Brute-Force-Ansatz mit diesen Analysemethoden mithalten kann. Vergessen Sie nicht, dass der Ansatz bis jetzt auf sehr einfacher Mathematik basiert. Ich denke, dass der Algorithmus noch mehr leisten kann.


Neue Ideen

Das Programm befand sich im Prototypenstadium und ich wollte das Maximum aus ihm herausholen, um zu sehen, wozu eine so einfache Brute-Force-Methode in der Lage ist. Das Hauptproblem war, dass eine zuverlässige globale Mustersuche die Analyse großer Kursintervalle erforderte, während die Kapazität eines Durchgangs sehr klein war. Bei der Analyse von M5-Kursen für ein beliebiges Währungspaar über einen Zeitraum von 10 Jahren produzierte das Programm beispielsweise etwa 700-2000 Varianten pro Stunde auf einem guten Kern (selbst mit milden Einstellungen).

Selbst wenn Sie, sagen wir, einen 30-Kern-Server nehmen, werden Sie tagelang warten müssen. Die einzige Lösung besteht darin, die Datenmenge für die Analyse zu reduzieren. Das kann man tun, indem man den gesamten Zeitraum in gleiche Intervalle aufteilt und einige davon unberechnet auslässt. Solche Intervalle sind Minuten, Stunden, Tage, Monate und Jahre. Darüber hinaus charakterisieren diese bedingten Bereiche bestimmte Handelsparameter. Mit anderen Worten, zusätzlich zur Beschleunigung können wir jeden Wochentag, jede Stunde und jede Minute im Hinblick auf Muster detailliert untersuchen. Wir müssen uns nicht darum kümmern, womit dieses Muster verbunden ist.

Im Allgemeinen ist es unmöglich, alle Muster zu klassifizieren, da ihre Anzahl unendlich ist, während das menschliche Gehirn nicht in der Lage ist, alle zu verstehen und zu beschreiben (was auch nicht wirklich notwendig ist, wenn man eine Arbeitsformel hat). Das ist Mathematik. Es ist möglich, einen festen Zeitraum und feste Tage zu untersuchen, oder alle Daten einmal zu untersuchen. Das kann man mit folgendem Fall vergleichen: Wir haben eine Funktion von einer Variablen, und dann stellt sich heraus, dass dies nur ein Spezialfall einer Funktion von mehreren Variablen ist, wir wussten es nur nicht.


Stichprobensegmentierung und Vorhersagefähigkeit von Stichproben

Ich denke, dass es interessant sein wird, diese Option zu analysieren, da sich die Modi für die Mustersuche in ihren oberen Möglichkeiten stark unterscheiden, da Samples unterschiedlicher Länge analysiert werden. Zusätzlich zu einer deutlichen Beschleunigung der Berechnungen kann eine nützlichere (kleinere) Stichprobe basierend auf der anfänglichen Stichprobe erhalten werden. Diese erhaltene Funktion kann mit einfachen Formeln oder Polynomen weiter analysiert werden. Der Grund dafür ist, dass der Markt streng an die Weltzeit gebunden ist.

Die Handelsaktivität wird größtenteils auf der Grundlage der täglichen Aktivität der Händler gebildet. Hier können wir auch auf Expert Advisors verweisen. Viele Expert Advisors können als vorhersehbare Spieler betrachtet werden, aber nicht alle. Zum Beispiel erstellen viele Entwickler zeitbasierte Nachtscalper. Es stellt sich heraus, dass die Art der Preisbewegung nicht nur durch vergangene Preise bestimmt wird, sondern auch durch bestimmte Tage, Wochen, Monate, möglicherweise sogar Jahre. Jeder dieser Werte ist quantisiert, d.h. er hat bestimmte feste Werte.

Natürlich können die Werte aufgeteilt werden. Zum Beispiel kann das Zeitfenster nicht in Stunden und Minuten gemessen werden, sondern in Sekunden, die seit dem Beginn eines neuen Tages vergangen sind. Es hängt alles davon ab, welche Größen einfacher zu messen sind. Diese quantisierten Größen können weiter bis ins Unendliche aufgeteilt werden. In meinem Programm erfolgt die Segmentierung nur innerhalb von Tagen und innerhalb von Wochen. Ich denke, die Segmentierung nach Jahren ist nicht so effizient. Was die Monate betrifft, werde ich die entsprechende Funktionalität vielleicht später hinzufügen. Das folgende Diagramm demonstriert die obigen Ideen:

Segmentierungs-Diagramm

Ich habe zwei beliebige Optionen für die Segmentierung der Originalprobe angezeigt. Unten sehen Sie, was passieren würde, wenn die Brute-Force-Methode unendlich lange andauert. Der erste Fall ist, wenn wir alle möglichen mathematischen Muster zur Beschreibung implementieren, und der zweite Fall zeigt, was wir mit der einzigen implementierten Brute-Force-Methode (mehrdimensionales Taylor-Polynom) erhalten. Es wird immer das vorhersagbarste Muster und das unvorhersagbarste Muster geben. Außerdem existiert für jeden Polynomtyp ein optimaler segmentierter Abschnitt. Solche Segmente können unzählig sein, aber wir können sie mit einer winzigen Genauigkeit erkennen. Ich berücksichtige keine Sekunden, da wir Balken analysieren.

So können wir für jede Kombination von Segmentierungsparametern eine Funktion für jeden Handelsparameter erstellen, die wir am Ausgang des vollen Entwicklungszyklus erhalten können. Zum Beispiel die erwartete Auszahlung und der Gewinnfaktor:

  • Ma=Ma(M,D,Ts,Te)
  • PrF=PrF(M,D,Ts,Te)
  • M - Monat des Jahres
  • D - Tag der Woche
  • Ts - Korridor-Startzeit
  • Te - Korridor-Endzeit (kann ein Übergang durch 0:00 sein, d.h. nächster Tag) 

Die Funktionen sind diskret. Die Argumente können also streng feste Werte annehmen. Durch die Festlegung der Variablen, die mit Monaten und Wochentagen verbunden sind, können wir uns grob vorstellen, wie diese beiden Funktionen aussehen werden. Die maximale Anzahl von Änderungen ist drei, deshalb kann ein informativer Graph mit nur zwei freien Variablen erstellt werden. Ich verwende "Ts" und "Te":

3D-Diagramm

Jede Formel oder jeder Algorithmus, mit dem wir versuchen werden, die Zukunft vorherzusagen, wird solche einzigartigen Graphen für alle quantitativen Eigenschaften des zukünftigen Handelssystems haben. Ich habe nur zwei davon gezeigt, um zu demonstrieren, dass dort, wo es einen maximalen Gewinnfaktor gibt, nicht unbedingt auch ein maximaler erwarteter Auszahlungsbetrag zu finden ist. In den meisten Fällen müssen Sie zwischen dem erwarteten Payoff und dem Gewinnfaktor abwägen, da es Spreads, Kommissionen und Swaps gibt. Die Anzahl dieser Extrema und deren Werte sind für jede Formel unterschiedlich. Wir können eine mehrdimensionale Extremsuche nicht manuell durchführen, aber sie kann mit unserem Programm durchgeführt werden.

Eine Sache möchte ich noch erwähnen. Während ich den Markt mit meiner Software untersucht habe, ist mir ein interessanter Abschnitt aufgefallen, in dem viele Währungspaare überschätzte Vorhersagewerte haben. Es ist ein Intervall ungefähr zwischen 23:30 und 0:30. Dies hängt definitiv mit dem Zeitpunkt des Datumswechsels zusammen. Die Profitabilität der Strategien, die im MetaTrader 4 hervorragende Gewinnfaktoren zeigten, wurde jedoch beim Test im MetaTrader 5 nicht bestätigt. Der Grund liegt im Spread. Prüfen Sie immer zweimal die Muster, die innerhalb des Spreads liegen. Die meisten der gefundenen Muster werden innerhalb des Spreads liegen.


Letzte Modifikationen des Suchalgorithmus

Der Zweck der letzten Modifikationen war die Beschleunigung des Programmablaufs sowie die Maximierung der Suchvariabilität und -effizienz. Liste der Änderungen:

  1. Hinzufügen der Möglichkeit, nach Mustern in einem festen Zeitintervall zu suchen.
  2. Hinzufügen der Möglichkeit, nur an ausgewählten Tagen zu handeln.
  3. Es wurde die Möglichkeit zugefügt, zufällige Sätze von Tagen für jede neue Variante zu generieren, basierend auf den ausgewählten. Tagen
  4. Es wurde die Möglichkeit hinzugefügt, zufällige Server-Zeitfenster zu generieren, indem die mögliche minimale und maximale Fensterdauer in Minuten angegeben wird.
  5. Möglichkeit, diese Einstellungen beliebig zu kombinieren.
  6. Die zweite Optimierungs-Registerkarte kann nun im Multithreading-Modus arbeiten.
  7. Der Optimierungsmodus wurde optimiert.

Das aktualisierte Fenster sieht wie folgt aus:

Registerkarte "WAIT"

Die zweite Registerkarte hat sich nicht geändert:

Registerkarte "WAIT AGAIN"

Darunter befindet sich die dritte Registerkarte:

Registerkarte "GENERATE AND WAIT"

Die Oberfläche ist noch sehr roh, so dass die Einstellungen kaum in die Form passen. Ich werde die Oberfläche in der nächsten Programmversion komplett überarbeiten, die ich im nächsten Artikel vorstellen werde. Ich werde auch ein Video mit dem gesamten Prozess der Erstellung eines Expert Advisors mit meinem Programm aufnehmen. Sie werden sehen, wie einfach und schnell es ist. Sie müssen nur die Einstellungen der Schnittstelle verstehen und ein wenig Übung haben.


Optimierung von Vorlagen und behelfsmäßigen Expert Advisor

Um die neue Aufgabe zu implementieren, musste ich auch die Expert Advisor Vorlagen anpassen. Diese generieren einen Kurs im gewünschten Format, der vom Programm bequem eingelesen werden kann. Der Code des EA, der einen Kurs für MetaTrader 5 generiert, sieht nun wie folgt aus:

string FileNameString;
uint Handle0x;
datetime Time0=0;

double Open[];
double Close[];
double High[];
double Low[];
datetime Time[];


void WriteEnd()
   {
   FileWriteString(Handle0x,"EndBars"+"\r\n");
   MqlDateTime T;
   TimeToStruct(Time[1],T);
   FileWriteString(Handle0x,IntegerToString(int(T.year))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.mon))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.day)));
   }

void OpenAndWriteStart()
   {
   FileDelete(FileNameString);
   Handle0x=FileOpen(FileNameString,FILE_WRITE|FILE_TXT|FILE_COMMON|FILE_ANSI,'\t',CP_UTF8);
   FileSeek(Handle0x,0,SEEK_SET);
   FileWriteString(Handle0x,"DataXXX"+" "+Symbol()+" "+IntegerToString(Period())+"\r\n");
   FileWriteString(Handle0x,DoubleToString(_Point,8)+"\r\n");
   MqlDateTime T;
   TimeToStruct(Time[1],T);
   FileWriteString(Handle0x,IntegerToString(int(T.year))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.mon))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.day))+"\r\n");             
   }
      
void WriteBar()
   {
   FileWriteString(Handle0x,"\r\n");
   FileWriteString(Handle0x,DoubleToString(Close[1],8)+"\r\n");
   FileWriteString(Handle0x,DoubleToString(Open[1],8)+"\r\n");
   FileWriteString(Handle0x,DoubleToString(High[1],8)+"\r\n");
   FileWriteString(Handle0x,DoubleToString(Low[1],8)+"\r\n");         
   FileWriteString(Handle0x,IntegerToString(int(Time[1]))+"\r\n");
   MqlDateTime T;
   TimeToStruct(Time[1],T);
   FileWriteString(Handle0x,IntegerToString(int(T.hour))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.min))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.day_of_week))+"\r\n");         
   //FileClose(Handle0x);
   }      

void CloseFile()
   {
   FileClose(Handle0x);
   }

bool bNewBar()
   {
   ArraySetAsSeries(Close,false);                        
   ArraySetAsSeries(Open,false);                           
   ArraySetAsSeries(High,false);                        
   ArraySetAsSeries(Low,false);                              
   CopyOpen(_Symbol,_Period,0,2,Open);
   CopyClose(_Symbol,_Period,0,2,Close);
   CopyHigh(_Symbol,_Period,0,2,High);
   CopyLow(_Symbol,_Period,0,2,Low);
   ArraySetAsSeries(Close,true);                        
   ArraySetAsSeries(Open,true);                           
   ArraySetAsSeries(High,true);                        
   ArraySetAsSeries(Low,true);                                 
   if ( Time0 < Time[1] )
      {
      if (Time0 != 0)
         {
         Time0=Time[1];
         return true;
         }
      else
         {
         Time0=Time[1];
         return false;
         }
      }
   else return false;
   }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
  ArrayResize(Close,2,0);
  ArrayResize(Open,2,0);   
  ArrayResize(Time,2,0);
  ArrayResize(High,2,0);
  ArrayResize(Low,2,0);  
  FileNameString="DataHistory"+" "+Symbol()+" "+IntegerToString(Period());
  OpenAndWriteStart();
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
  WriteEnd();
  CloseFile();
  }

void OnTick()
  {
  ArraySetAsSeries(Time,false);
  CopyTime(_Symbol,_Period,0,2,Time);
  ArraySetAsSeries(Time,true);
  if ( bNewBar()) WriteBar();
  }

Es gibt nur ein paar einfache Funktionen. Einige Funktionen schreiben etwas zu Beginn des Tests, andere fügen am Ende einige Informationen über den Kurs hinzu, und die Hauptfunktion schreibt einfach Informationen über einen Balken, wenn er erscheint. Der EA hat keine Eingabeparameter. Führen Sie ihn mit historischen Daten aus, und er wird die Kursdatei im entsprechenden Format erzeugen, die vom Programm gelesen werden kann. Nun, dies ist keine sehr gute Lösung. Vielleicht werde ich in Zukunft in der Lage sein, das direkte Lesen von Kursen aus dem Terminal zu implementieren. Die obige Lösung ist bis jetzt recht bequem. Zumindest ist sie für mich bequem.

Anstatt temporäre Funktionen zu verwenden, die datetime in die Wochentage, Stunden und Minuten umwandeln, habe ich sie als zusätzliche Balkeninformation in das Zitat geschrieben. Es sind alles Integer-Werte, außer ENUM_DAY_OF_WEEK. Alles, was ich tun musste, war, eine solche nummerierte Liste in C#-Code zu implementieren und in meinen Vorlagen dafür zu sorgen, dass die Daten in der gleichen Form zurückgegeben werden. Durch den Verzicht auf Zeitfunktionen können Sie unnötige Berechnungen auf der C#-Code-Seite vermeiden. Es vermeidet auch Zeitinkonsistenzen. Solche Dinge sind gefährlich, daher sollten Sie sie besser vermeiden.

Die resultierende Kursdatei kann in einem beliebigen Texteditor geöffnet werden. Sie werden die folgende einfache und klare Struktur sehen:

Datei mit historischen Daten


Der Kopf der Vorlage, in dem die Variablen registriert sind, enthielt bisher Felder zum automatischen Ausfüllen zum Zeitpunkt der Generierung. Jetzt wurden Variablen für die Handelszeit und die Handelstage in die Liste aufgenommen.

Eingabevorgabe sieht jetzt so aus:

double C1[] = { %%%CVALUES%%% };//Brutted Values
int CNum=%%%CNUMVALUE%%%;//Bars To Equation
int DeepBruteX=%%%DEEPVALUE%%%;//Max Pow Of Polynomial
int DatetimeStart=%%%DATETIMESTART%%%;//Help Datetime
input bool bInvert=%%%INVERT%%%;//Invert Trade(or sign of values as the same)
input int DaysToFuture=%%%DAYSFUTURE%%%;//Days To Future
int DaysToTrade[]={ %%%DAYS%%% };//Days To Trade
input double ValueOpenE=%%%OPTVALUE%%%;//Open Signal
input bool bUseTimeCorridorE=%%%TIMECORRIDORVALUE%%%;//Use Time Corridor
input int TradeHour=%%%HOURSTARTVALUE%%%;//Start Trading Hour
input int TradeMinute=%%%MINUTESTARTVALUE%%%;//Start Trading Minute
input int TradeHourEnd=%%%HOURENDVALUE%%%;//End Trading Hour
input int TradeMinuteEnd=%%%MINUTEENDVALUE%%%;//End Trading Minute

Alle Werte hier werden vom Programm bei der Erstellung des Roboters ausgefüllt, sodass der Roboter sofort mit den Standardeinstellungen arbeiten kann und im Moment des Terminalstarts kompiliert werden kann, ohne dass MetaEditor geöffnet werden muss. Alle Einstellungen und Arrays sind in den Expert Advisor eingebettet. Ich finde das sehr praktisch. Stellen Sie sich vor, Sie haben eine Menge Expert Advisors und unterschiedliche Set-Dateien. Der Brute-Force-Software-Prototyp für MetaTrader 4 hat gezeigt, dass ich manchmal Einstellungen verwechsle. Das schränkt zwar die mögliche Funktionalität ein, im Vergleich zu Textdateien, aber diese Methode ist zuverlässiger.

Die Hauptfunktion wurde ebenfalls geändert:

bool bDay()//Day check
   {
   MqlDateTime T;
   TimeToStruct(Time[0],T);
   for ( int i=0; i<ArraySize(DaysToTrade); i++ )
      {
      if ( T.day_of_week == DaysToTrade[i] ) return true;
      }
   return false;
   }

void Trade()//Trade Function
   {
   double Value;
   Value=PolinomTrade();
   MqlTick LastTick;
   SymbolInfoTick(Symbol(),LastTick);
   MqlDateTime tm;
   TimeToStruct(LastTick.time,tm);
   int MinuteEquivalent=tm.hour*60+tm.min;
   int BorderMinuteStartTrade=HourCorrect(TradeHour)*60+MinuteCorrect(TradeMinute);
   int BorderMinuteEndTrade=HourCorrect(TradeHourEnd)*60+MinuteCorrect(TradeMinuteEnd);
   
   if ( Value > ValueCloseE)
      {
      if ( !bInvert ) CloseBuyF();
      else CloseSellF();
      }
      
   if ( Value < -ValueCloseE)
      {
      if ( !bInvert ) CloseSellF();
      else CloseBuyF();
      }   
   
   if ( !bUseTimeCorridorE )
      {
      if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value > ValueOpenE && Value <= ValueOpenEMax )
         {
         if ( !bInvert ) SellF();
         else BuyF();
         }
      
      if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value < -ValueOpenE && Value >= -ValueOpenEMax )
         {
         if ( !bInvert ) BuyF();
         else SellF();
         }      
      }
   else
      {
      if ( BorderMinuteStartTrade > BorderMinuteEndTrade && bDay() )
         {
         if ( !(MinuteEquivalent>=BorderMinuteEndTrade && MinuteEquivalent<= BorderMinuteStartTrade) )
            {
            if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value > ValueOpenE && Value <= ValueOpenEMax )
               {
               if ( !bInvert ) SellF();
               else BuyF();
               }
      
            if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value < -ValueOpenE && Value >= -ValueOpenEMax )
               {
               if ( !bInvert ) BuyF();
               else SellF();
               }
            }        
         }
      if ( BorderMinuteStartTrade <= BorderMinuteEndTrade && bDay() )
         {
         if ( MinuteEquivalent>=BorderMinuteStartTrade && MinuteEquivalent<= BorderMinuteEndTrade )
            {
            if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value > ValueOpenE && Value <= ValueOpenEMax )
               {
               if ( !bInvert ) SellF();
               else BuyF();
               }
      
            if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value < -ValueOpenE && Value >= -ValueOpenEMax )
               {
               if ( !bInvert ) BuyF();
               else SellF();
               }
            }        
         }      
      }

   if ( bPrintValue ) Print("Value="+DoubleToString(Value));     
   }

Wir haben hier nur die Logik zur Steuerung der Wochentage und des Zeitintervalls innerhalb des Tages hinzugefügt, während der Rest unverändert blieb. Übrigens muss das Zeitintervall nicht zwischen 0-24 Stunden liegen. Es kann auch an einem Tag beginnen und an einem anderen enden. Es kann also auch den Tausch von Ladepunkten beinhalten. Nach der ursprünglichen Idee können die Positionen in bestimmten Korridoren platziert werden und können jederzeit geschlossen werden. Vielleicht wäre es eine bessere Lösung, das erzwungene Schließen von Positionen nach Zeit als separate Operation hinzuzufügen. Bisher scheint es mir, dass der aktuelle Ansatz stabilere Roboter erzeugen sollte, weil wir die Grenzen des Zeitkorridors unscharf machen. Dies geschieht, um die Wahrscheinlichkeit zu verringern, ein zufälliges Ergebnis zu erhalten, durch eine Bestätigung, dass der gefundene Korridor und seine Formel die Leistung nicht abrupt beendet, sondern sich allmählich abschwächt.


Analyse der globalen Muster

Alle hier vorgestellten Ergebnisse wurden auf der Grundlage des Trainings im Intervall 2010.01.01-2020.01.01 erzielt, wie im vorherigen Artikel. Dies geschieht absichtlich, um das aktuelle Jahr als Vorwärtsperiode zu belassen, um die Ergebnisse zu überprüfen. Der Vorwärtszeitraum ist 2020.01-2020.12.01.

Die Qualität der Ergebnisse hat sich deutlich erhöht. Obwohl die Anzahl der Geschäfte abgenommen hat, ist das Ergebnis für die Vorwärtsperiode besser geworden. Wie ich im letzten Artikel vermutet habe, führt eine Erhöhung der Qualität des Anfangstests zu einer Erhöhung der Musterlebensdauer in der Vorwärtsperiode. Der Beweis wird im Folgenden erbracht.

Beginnen wir mit dem Paar EURCHF H1. Die vorherige Analyse zeigte eine gute Vorhersagbarkeit dieses Symbols, also entschied ich mich, damit zu beginnen. Ich habe 3 Expert Advisors basierend auf den Optimierungsergebnissen erstellt. Ich werde zusätzlich ein paar Tests von MetaTrader 4 zur Verfügung stellen, um zu zeigen, wie sehr sich die Leistung der gefundenen Muster verbessert hat. Werfen Sie einen Blick auf die erste Option:

Erster Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 4

Die Losgröße des Tests wurde auf 0,1 gesetzt. Wenn wir den resultierenden Expected Payoff mit dem in der vorherigen Programmversion vergleichen, ist er von den vorherigen USD 8 auf USD 54 gestiegen. Der Gewinnfaktor hat sich auch deutlich erhöht, mindestens um 0,5 (vielleicht sogar mehr). Der gleiche Parameter lag im letzten Artikel bei 1,14. Dies war der höchste Gewinnfaktor, den ich erreichen konnte. Sie können sehen, wie die Strukturierung der Stichprobe nach Wochentagen und Betriebszeit die Ergebnisse beeinflusst hat.

Dies ist jedoch nicht das bestmögliche Ergebnis. Die Tests wurden aufgrund der Aufgabenstellung nur für eine sehr begrenzte Zeit durchgeführt. Der Zeitrahmen war sehr eng gesteckt. Insgesamt dauerten alle Tests etwa 2-3 Tage. Die Tests wurden auf 2 Kernen durchgeführt, und jede Variante dauerte etwa 5-6 Stunden.

Außerdem habe ich während des Testprozesses einige Fehler im Programmalgorithmus gefunden, die oft falsche Ergebnisse erzeugten. Ich habe sie bereits behoben, aber dadurch wurde die Anzahl der gefundenen Muster reduziert. Trotzdem war diese Zeit ausreichend, um akzeptable Optionen zu finden. Lassen Sie uns nun den Test in MetaTrader 5 durchführen:

Erster Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 5

Dieser Test hatte weniger Abschlüsse, weil ich die Testspanne begrenzt habe, um einen stabilen Test zu erhalten, während ich versuchte, eine höhere Rentabilität zu erreichen. Wie die Praxis jedoch gezeigt hat, ist dies nicht notwendig. Ich werde am Ende des Artikels erklären, warum. Trotz der sehr geringen Anzahl von Positionen können diese Daten als zuverlässig angesehen werden, da sie auf einer sehr langen Stichprobe beruhen (sie wurde durch Brute-Forcing der Formelkoeffizienten auf der ersten Registerkarte gewonnen). In der Tat berechnen wir auf der ersten Registerkarte alle Balken, die sich im geladenen Segment befinden, so dass dies eine ideale Basis für die Optimierung ist. Wenn wir einen Teil der Ergebnisse einer großen Stichprobe in eine kleinere Stichprobe nehmen, dann ist das kleinere Muster umso stärker, je mehr Daten in der ersten Stichprobe enthalten sind (Aufträge).

Hier ist der Test für die Vorwärtsperiode:

Zukunft, 1 Jahr

Es gibt nur 2 Positionen in 1 Jahr, aber das Ergebnis ist positiv.

Hier ist ein weiteres Ergebnis für das gleiche Intervall:

Zweiter Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 4

Die Vorgaben ohne Spread ist diese Formel im MetaTrader 5 verlustbringend. Aber wenn wir den Spread begrenzen, basierend auf der erhaltenen erwarteten Auszahlung, wird es gute Signale geben, obwohl der Graph nicht gut aussieht:

Zweiter Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 5

Der Graph ist wirklich schlecht, wie können wir also in Zukunft davon profitieren? Nun, der Graph basiert auf einer riesigen zugrundeliegenden Stichprobe, die alle weiteren Stichproben bestärkt, also gibt es nichts Schlechtes in einem solchen Graphen. Wie auch immer, es zeigt einen gewissen Gewinn. Lassen Sie uns die Zukunft betrachten:

Zukunft, 1 Jahr

Wie Sie sehen können, ist das Ergebnis sehr gut, obwohl es nicht so viele Positionen gibt. Eigentlich sind die Testergebnisse in den letzten Jahren besser, weil die Broker ständig die Spreads reduzieren und gleichzeitig neue Technologien verwenden. Nun, eine Schlussfolgerung bezüglich der Prognosen und ihrer möglichen Leistung ist recht gut. Allerdings gibt es nicht genug Daten, um endgültige Schlussfolgerungen zu ziehen. Also habe ich noch ein paar weitere Tests mit verschiedenen Währungspaaren durchgeführt - sie werden später gezeigt. Schauen wir uns nun den dritten Roboter auf dem gleichen Währungspaar an.

Es wird keine weiteren Tests von MetaTrader 4 geben. Ich denke, zwei vollständige Varianten sind genug für den Vergleich. Also, hier ist die dritte Variante:

Dritter Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 5

Das Diagramm ist nicht so schlecht. Prüfen wir die Zukunft:

Zukunft, 1 Jahr

Das gleiche Bild. Alle Vorwärtsperioden haben positive Ergebnisse gezeigt. Man kann sagen, dass die Ergebnisse ähnlich sind, weil alle drei Roboter auf dem gleichen Datenintervall des gleichen Währungspaares trainiert wurden und somit das gleiche Muster beschreiben.

Oder dass das Währungspaar so gut ist, dass die Roboter positiv sind. Selbst wenn es so ist, können wir davon profitieren. Aber die Gründe sind allgemeiner. Um zu beweisen, dass der Grund nicht nur in dem Währungspaar oder in dem Intervall liegt, lassen Sie uns ein anderes Währungspaar auf einem anderen Zeitrahmen prüfen.

Testen von EURUSD H4

Ich stelle hier keine Tests von MetaTrader 4 zur Verfügung, aber die Graphen für dieses Währungspaar sehen genauso glatt und schön aus wie die vorherigen Tests. Ich habe zwei verschiedene Bots auf diesem Zeitrahmen gefunden. Der erste:

Erster Bot EURUSD H4 2010.01.01-2020.01.01 MetaTrader 5

Das Diagramm ist hässlich, aber nach unseren bisherigen Annahmen sollte uns das nicht beunruhigen, da dies nur ein Teil einer sehr großen Stichprobe ist. Prüfen wir die Zukunft:

Zukunft, 1 Jahr

Auch hier gilt, dass das Muster das ganze Jahr über funktioniert. Selbst wenn wir den ersten Auftrag, der der größte war, nicht berücksichtigen, ist der Rest ebenfalls positiv.

Nun wollen wir den zweiten EA prüfen:

Zweiter Bot EURUSD H4 2010.01.01-2020.01.01 MetaTrader 5

Das ist das glatteste Diagramm von allen. Und hier der Vorwärtstest

Zukunft, 1 Jahr

Alles funktioniert wie erwartet. Der Graph ähnelt sogar einer geraden Linie, trotz des großen Hügels am Anfang. Wir haben fünf Expert Advisors auf zwei verschiedenen Währungspaaren getestet, und alle Vorwärtstests waren positiv. Das ist eine gute Statistik. Allerdings brauche ich mehr Daten. Also habe ich beschlossen, ein völlig anderes Paar und einen anderen Zeitrahmen zu testen.

Test von EURJPY M5.

EURJPY M5 2010.01.01-2020.01.01 MetaTrader 5

Das Trainingsintervall sieht seltsam aus, es gibt einen ausgeprägten Umschwung im Jahr 2015, aber das allgemeine Ergebnis sieht gut aus. Hier ist die Vorwärtsperiode:

Zukunft, 1 Jahr

Es ist schwierig, Schlussfolgerungen zu ziehen, aber es ist klar, dass dies der erste negative Vorwärtstest ist. Dennoch denke ich nicht, dass dieses Ergebnis eine Widerlegung der Annahme über die Stabilität aller unserer Algorithmen ist. Das liegt daran, dass es im Backtest 2015 eine klare Umkehr gab. Ich versuche nicht, die Ergebnisse an meine Vision des Marktes anzupassen, aber ich sehe den Grund in dieser Umkehrung. Im Gegenteil, wir haben es mit der Fortsetzung dieser Umkehrung zu tun, die im Jahr 2015 stattfand.

Um solche Einflüsse externer Ergebnisse zu vermeiden, muss der Mustersuchalgorithmus etwas modifiziert werden. Diese Algorithmus-Modifikation wird in der nächsten Version implementiert werden.


Ziehen von Schlussfolgerungen

Ich glaube, dass die obigen Tests ausreichen, um einige wichtige Schlussfolgerungen bezüglich der Suche und des Testens von funktionierenden Expert Advisors in den Terminals MetaTrader 4 und MetaTrader 5 zu ziehen. Die Tester in diesen beiden Terminals arbeiten etwas anders. Die Kurse in MetaTrader 4 speichern die Historie ohne Angaben zum Spread, wodurch der Benutzer den Spread auf "1" setzen kann, was fast gleich "0" ist. Der Spread spielt für die meisten Expert Advisors überhaupt keine Rolle, während wir nicht sehr offensichtliche Muster erkennen und entwickeln können. Dies ist im MetaTrader 5 nicht möglich. Aber MetaTrader 5 Kurse beinhalten Spread-Informationen, die es erlauben, die tatsächliche Profitabilität des Systems zu beurteilen.

Nach meiner Erfahrung, wenn ein System, das ursprünglich für MetaTrader 4 geschrieben wurde, nicht richtig für das fünfte Terminal konvertiert wurde, hat ein solches System sehr wenig Chancen, Profit zu zeigen, weil die meisten Muster, die wir finden können, innerhalb des Spreads liegen, also nutzlos sind. In einigen Fällen kann es möglich sein, Signale mit dem minimalen Spread unter allen Signalen zu finden. Aber das ist nicht immer möglich.

Sehr oft verschlechtern wir die Signale, indem wir den erforderlichen Spread verringern. In diesem Fall habe ich die Spreads für MetaTrader 5-Tests manuell ausgewählt, um akzeptable Tests zu erhalten, aber das dauert sehr lange. Dies kann durch eine Modifikation des Programms automatisch erfolgen. Die folgende Abbildung zeigt den aktuellen Prozess der Mustersuche, bis zur letzten Stufe, und eine mögliche Automatisierung des Spread-Auswahlprozesses:

Entwicklungs-Zyklus

Das Diagramm zeigt den gesamten neuen EA-Entwicklungszyklus, vom Anfang bis zum Ende. Der aktuell implementierte Zustand dieses Zyklus ist in schwarz dargestellt. Grau wird für mögliche Änderungen verwendet. Weitere mögliche Verbesserungen sind in 6 Kategorien unterteilt:

  1. Verwendung der einfachsten mathematischen Funktionen zur Verarbeitung der Balkendaten.
  2. Hinzufügen eines Losgrößenmanagements, das den Gewinnfaktor für Expert Advisors erhöhen, die globale Muster implementieren.
  3. Hinzufügen von Martingal- und Reverse-Martingale-Mechanismen für die Arbeit mit ultrakurzen Perioden.
  4. Hinzufügen eines Mechanismus zum Kombinieren guter EA in einen Bot mit der höchstmöglichen Frequenz von Positionen.
  5. Hinzufügen von Spreads zum Kurs und Vermeidung der manuellen Spread-Auswahl (vollständige Automatisierung des gesamten Entwicklungszyklus).
  6. Korrektur von erkannten Optimierer-Fehlern.

Ich möchte die Punkte 1, 5 und 6 hervorheben. Die Variabilität der Brute-Force-Formeln wird es uns ermöglichen, mehr verschiedene Varianten von Expert Advisors aus einem Brute-Optimierungszyklus zu erstellen und die durchschnittliche Qualität der Ergebnisse zu erhöhen. In Kommentaren zu früheren Artikeln schlugen Benutzer vor, Fourier-Reihen zu verwenden, um periodische Marktprozesse zu beschreiben. Ich wollte diese Aufgabe für spätere Modifikationen belassen. Aber die Methode ist nicht so schwierig. Wir müssen keine Funktionen in eine Reihe umwandeln, sondern nur die Koeffizienten der Terme finden, ähnlich wie bei Taylor-Reihen, die ich verwende. Außerdem wird die Variabilität dieser Methode viel höher sein als die der Taylor-Reihe. Mein Algorithmus verwendet nur den ersten Grad, denn mit zunehmendem Grad nimmt die Qualität ab, da die Komplexität der Berechnung überproportional steigt. Auch die Streuungen sind sehr wichtig. Warum Signale manuell filtern, wenn man es automatisch tun kann? Es gab auch Fehler bei den Zeiten der Balken, aber diese Fehler wurden behoben. Solche Fehlanpassungen waren auf den Unterschied in der Funktionalität der Vorlagen und der Funktionalität der Software zurückzuführen.

Nun, der eigentliche Zweck dieser Software ist es, den gesamten Prozess zu automatisieren, einschließlich der Entwicklung, des Testens und der Optimierung von Expert Advisors für beide Plattformen. Die Aktionen, die ich noch manuell durchführe, können ebenfalls automatisiert werden. Außerdem kann die Maschine viel schneller die passenden Varianten finden. Um ehrlich zu sein, ist dies meiner Faulheit geschuldet, dass ich solche elementaren Dinge wie die Spread-Größe nicht manuell konfigurieren möchte. Dieser Prozess erhöht den Entwicklungszyklus des Handelssystems erheblich. Wichtig ist die Quantität und Qualität der erzielten Ergebnisse pro Zeiteinheit, da dies den weiteren Gewinn direkt beeinflusst. Wenn Sie außerdem zu viel Zeit mit der Konfiguration des Systems verbringen, kann es irrelevant werden. Die meisten der gefundenen Expert Advisors arbeiten für eine sehr begrenzte Zeit, daher sollte alles sehr schnell erledigt werden. Oder Sie können jeden Monat einen Optimierer verwenden, aber das ist eine schlechte Lösung.

Wenn ich das Potential in der Weiterentwicklung der Idee sehe, werde ich sie weiter entwickeln. Wenn die Idee erfolgreich ist, werde ich ein ähnliches Programm für Gradient Boosting erstellen, oder einen neuen Modus in Form der dritten Stufe der Datenanalyse hinzufügen. Denn die Methode selbst ist sehr gut als Prädiktorsuchmaschine für Gradient Boosting geeignet. Wir können also einfach die mit dieser Methode gefundenen Prädiktoren verwenden, anstatt neue zu erfinden und zu testen. Dies erfordert jedoch eine viel ernsthaftere und tiefere Modifikation. Daher werde ich das jetzt nicht tun. Aber ein paar Modifikationen, die ich oben erwähnt habe, sind bereits implementiert worden, und jetzt teste ich sie und sammle Daten für den nächsten Artikel. Also, "TO BE CONTINUED".

Alle früheren Artikel waren hauptsächlich auf MetaTrader 4 ausgerichtet, aber wie die Praxis gezeigt hat, lässt sich die Automatisierung auch auf MetaTrader 5 umstellen. Dieser Ansatz wird im nächsten Artikel vollständig umgesetzt.

MetaTrader 5 ist eine viel fortschrittlichere Plattform, die echte Tick-Historie und Spread-Daten zur Verfügung stellt, was es ermöglicht, die tatsächliche Rentabilität eines jeden Handelssystems zu beurteilen, daher ist es besser, sich auf diese Plattform zu konzentrieren.

Während des Testprozesses habe ich einen sehr wichtigen Faktor gefunden, der die Qualität der generierten Expert Advisors und den Prozentsatz der EAs, die die Auswahl nach dem Test auf realen Tick-Daten in MetaTrader 5 weiter bestehen können, reduziert. Dieser Faktor ist nicht nur für Machine-Learning-basierte Systeme sehr wichtig, sondern auch für alle anderen Expert Advisors, die ursprünglich in MetaTrader 4 erstellt wurden. Er hängt mit dem Spread zusammen und wie er die endgültige Datenprobe für das Training beeinflusst. Viele Benutzer ignorieren den Spread oder berücksichtigen ihn nur bei der Positionierung. Aber er enthält eine unsichtbare, aber sehr wichtige Komponente, die einen sehr negativen Effekt auf den maschinellen Lernprozess hat. Ich werde die Details dazu im nächsten Artikel liefern.


Schlussfolgerung

Die wichtigste Schlussfolgerung aus diesem Artikel ist, dass Ihre Handelsroboter in MQL5 implementiert werden müssen, wenn Sie die Chancen für die reale Leistung Ihres Programms erhöhen wollen. MQL5-Programme können unter Bedingungen getestet werden, die den realen Bedingungen sehr nahe kommen. Die eingehende Analyse hat gezeigt, dass Sie ohne Tests in MetaTrader 5 keine wirklich zuverlässigen Ergebnisse erhalten können.

Wie der Artikel zeigt, kann sogar eine begrenzte Rechenleistung ein Ergebnis erzeugen, wenn wir sehr einfache mathematische Formeln verwenden, wie lineare Polynome und Polynome höheren Grades. Das Programm bietet eine Grundlage für die weitere Verwendung von einfachen mathematischen Funktionen. Die Ergebnisse zeigen, dass eine lineare und Potenzkombination der einfachsten Funktion ein hervorragendes Signal für den Handel liefern kann.

Die Ergebnisse zeigen, dass eine beliebige Menge von logischen Bedingungen auf eine einzige quantitative Metrik in Form einer Funktion reduziert werden kann. In der Tat bildet die Formel einen Indikator, der symmetrische positive und negative Werte erzeugt, die als Kauf- oder Verkaufssignale verwendet werden können. Die Indikatorformel ist immer anders und das sichert die Variabilität der Methode. Ich denke, viele Händler träumen von einem Indikator, der genau sagen kann, wann man kaufen und wann man verkaufen sollte. Diese Methode setzt diese Möglichkeit in dem Maße um, wie es der Markt zulässt. Der nächste Artikel wird noch viel bessere Ergebnisse liefern. Ich werde versuchen, alle Schlussfolgerungen zu konsolidieren, die während der gesamten Serie dieser Artikel gemacht wurden. Ich werde auch einige Details liefern, die sowohl für die manuelle Erstellung von Handelssystemen als auch für maschinelle Lernprozesse nützlich sein werden.

Referenzen

  1. Brute-Force-Ansatz zur Mustersuche
  2. Brute-Force-Ansatz zur Mustersuche (Teil II): Immersion


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

Beigefügte Dateien |
Bots.zip (846.48 KB)
Entwicklung eines selbstanpassenden Algorithmus (Teil II): Effizienzverbesserungen Entwicklung eines selbstanpassenden Algorithmus (Teil II): Effizienzverbesserungen
In diesem Artikel werde ich die Entwicklung des Themas fortsetzen, indem ich die Flexibilität des zuvor erstellten Algorithmus verbessere. Der Algorithmus wurde stabiler mit einer Erhöhung der Anzahl der Kerzen im Analysefenster oder mit einer Erhöhung des Schwellenprozentsatzes des Übergewichts der fallenden oder wachsenden Kerzen. Ich musste einen Kompromiss eingehen und eine größere Stichprobengröße für die Analyse oder einen größeren Prozentsatz des vorherrschenden Kerzenübergewichts einstellen.
Über das Finden von zeitlicher Mustern im Devisenmarkt mit dem CatBoost-Algorithmus Über das Finden von zeitlicher Mustern im Devisenmarkt mit dem CatBoost-Algorithmus
Der Artikel befasst sich mit dem Erstellen von Machine-Learning-Modellen mit Zeitfiltern und diskutiert die Effektivität dieses Ansatzes. Der menschliche Faktor kann nun eliminiert werden, indem das Modell einfach angewiesen wird, zu einer bestimmten Stunde an einem bestimmten Wochentag zu handeln. Die Mustersuche kann durch einen separaten Algorithmus bereitgestellt werden.
Neuronale Netze leicht gemacht (Teil 10): Multi-Head Attention Neuronale Netze leicht gemacht (Teil 10): Multi-Head Attention
Wir haben zuvor den Mechanismus der Self-Attention (Selbstaufmerksamkeit) in neuronalen Netzen besprochen. In der Praxis verwenden moderne neuronale Netzwerkarchitekturen mehrere parallele Self-Attention-Threads, um verschiedene Abhängigkeiten zwischen den Elementen einer Sequenz zu finden. Betrachten wir die Implementierung eines solchen Ansatzes und bewerten seine Auswirkungen auf die Gesamtleistung des Netzwerks.
Der Markt und die Physik seiner globalen Muster Der Markt und die Physik seiner globalen Muster
In diesem Artikel werde ich versuchen, die Annahme zu testen, dass jedes System mit auch nur einem kleinen Verständnis des Marktes auf globaler Ebene funktionieren kann. Ich werde keine Theorien oder Muster erfinden, sondern nur bekannte Fakten verwenden und diese Fakten schrittweise in die Sprache der mathematischen Analyse übersetzen.