Wettmodelle als Mittel zur Entwicklung von "Marktintuition"

Eryomin Sergey | 9 Februar, 2016

Einführung

Dieser Artikel befasst sich mit einem simplen Mechanismus, der Modelle für Wetten in einem Echtzeit-Modus berechnet. Was aber versteht man eigentlich unter Wetten? Finanzielle Wetten sind Vorhersagen bezüglich der künftigen Bewegung (rauf oder runter) einer Finanzanlage, wobei das Ziel darin besteht, die richtige Entwicklung vorherzusagen und daraus Kapital zu schlagen. (Übersetzt in die deutsche Sprache, Quelle: Russische Wikipedia; Übersetzung durch MetaQuotes Software Corp.)

Tatsächlich sind wir beim Wetten nur an einer Sache interessiert: Ob sich ein Finanzhandelsprodukt nach oben oder nach unten entwickelt. Das Handelsvolumen bei dieser Bewegung spielt für uns hierbei keine Rolle.

Wenn wir Wetten in der Form von einem Spiel in Verbindung mit kurzen Zeiträumen benutzen, dann können wir unsere eigene „Marktintuition“ entwickeln. Wir lernen dabei, „vorherzusehen,“ ob ein Währungspaar sich nach unten oder oben entwickelt. Genau das wird in diesem Artikel beschrieben.

Das Konzept

Immer wieder hört man, dass ein tieferes Verständnis der technischen Analyse, der fundamentalen Analyse, der Regeln der Kapitalverwaltung etc. für einen Trader von großer Bedeutung sei. Zweifellos ist das alles auch in der Tat wichtig. Aber es gibt darüber hinaus die sogenannte „Marktintuition“: Wenn ein Traders sich einen absolut „naturbelassenen“ Chart ansehen kann, der keinerlei Indikatoren enthält, und er dennoch ungefähr voraussehen kann, in welche Richtung sich ein Finanzhandelsprodukt entwickelt, dann spricht man von Marktintuition. Natürlich sind solche Vorhersagen meistens nicht besonders genau, aber Fehler können bei jedem Handelsansatz passieren. Und deshalb ist die Fähigkeit, die künftige Entwicklung des Marktes „vorherzusehen,“ eine sehr nützliche Sache, und zwar insbesondere dann, wenn man schnell und einfach die künftige Marktsituation einschätzen möchte.

Üblicherweise ist die Marktintuition das Resultat jahrelanger Erfahrung und zahlloser Experimente. Oftmals beläuft sich die Summe der Kosten solcher Experimente auf tausende von US-Dollar.

Aber ich bin der Ansicht, dass es Mittel und Wege gibt, diese Intuition auf eine Art und Weise zu entwickeln, die viel weniger Zeit und Geld in Anspruch nimmt. Einer dieser Wege besteht darin, ein Spiel zu schaffen, dessen Ziel darin besteht, die künftige Entwicklung eines Finanzhandelsproduktes vorherzusagen. Dieses Spiel wird dann noch viel besser funktionieren, wenn es mit realen Handelskonditionen abläuft. Es kann in diesem Falle auch parallel zum Handel mit echtem Geld betrieben werden.

Zweifellos können die menschlichen Fähigkeiten geschult und trainiert, und somit weiterentwickelt, werden. Als Kinder lernen wir, zu malen, zu singen, und verschiedene Musikinstrumente zu spielen. Ich bin mir ganz sicher, dass wir auf dieselbe Art und Weise auch erlernen können, die künftige Entwicklung auf den Märkten vorauszusehen. Wir können Computerspiele spielen. Und genauso können wir auch das Spiel spielen, die künftige Entwicklung von einzelnen Finanzhandelsprodukte vorherzusehen. Aber was wir hierbei stets wissen sollten, ist die Antwort auf die Frage, womit wir beginnen sollen und wie wir diese Fähigkeit am besten schulen können. Dazu müssen wir uns zunächst einmal das Spiel selbst ansehen.

Die Definition der Aufgabe

Was brauchen wir also? Wir brauchen ein Spiel, mit dessen Hilfe wir mit einem echten Chart im Echtzeit-Modus spielen können. Und dieses Spiel sollte sehr einfache Regeln besitzen und sich leicht implementieren lassen. Darüber hinaus sollte dieses Spiel seine maximale Aufmerksamkeit auf den Markt selbst richten, und nicht auf die auszuführenden Operationen. Und schließlich sollte das Spiel den Trader nicht allzu sehr von der Möglichkeit des realen Handels ablenken.

Beim Wetten scheinen all diese Voraussetzungen erfüllt zu sein. Aber im echten Leben ist dies nicht besonders praktisch. Nicht viele Broker-Firmen bieten ihren Kunden eine solche Gelegenheit zum Training an. Selbst wenn Sie es schaffen sollten, eine solche Firma zu finden, können Sie dennoch mit einigen Unzulänglichkeiten und Problemen konfrontiert werden. Beispielsweise können Demo-Konten Ihre Aufmerksamkeit vom realen Handelsgeschehen ablenken. Und das Spiel ist auch viel zu riskant für ein echtes Handelskonto. Üblicherweise können Sie auch nicht auf Zeiträume wetten, die unterhalb der Grenze von 1 Stunde liegen.

Sie sehen daher, dass diese Variante des Spiels unserer Aufgabe nicht vollständig gerecht wird. Konsequenterweise müssen wir ein separates Programm für dieses Spiel schreiben – ein Programm, das über keinerlei solche Einschränkungen verfügt. Und daher eignet sich MQL4 in idealer Weise für unsere Aufgabe.

Implementierung

Lassen Sie uns mit einer ganz simplen Frage beginnen: Wie sollte die Implementierung aussehen? Offensichtlich könnten Benutzer eine der beiden gegebenen Varianten auswählen – nach oben oder nach unten (das heißt eine Vorhersage bezüglich der künftigen Entwicklung eines Finanzhandelsproduktes treffen). Danach fügt das Programm einen Punkt hinzu, falls die Vorhersage korrekt war, und es zieht einen Punkt ab, falls die Vorhersage nicht zutreffend gewesen sein sollte.

Die Auswahl der Implementierung lässt sich mithilfe von Objekten viel besser realisieren - SYMBOL_ARROWDOWN und SYMBOL_ARROWUP. Der Benutzer könnte also den nötigen Pfeil auf den Charts platzieren. Aber das Zeichnen dieser Pfeile und das Schreiben von Signaturen würde viel zu viel Zeit und Aufmerksamkeit in Anspruch nehmen. Diese Variante eignet sich also daher nicht für unsere Zwecke.

Eine weitere Variante besteht darin, automatisch zwei Pfeile zu Beginn einer neuen Kerze zu platzieren. Der Benutzer könnte nun einen dieser beiden Pfeile löschen, und der verbleibende Pfeil würde damit seine Vorhersage angeben. Im Anschluss daran würde zu Beginn einer neuen Kerze ein Expert Advisor überprüfen, ob die Vorhersage zutreffend war. Und die gesamte Punktzahl, die Anzahl der korrekten und die Anzahl der falschen Vorhersagen würden gezählt werden. Zu diesem Zwecke würde eine externe Datei zum Einsatz kommen, in der die Aufzeichnung dieser Daten erfolgen würde.

Das hört sich alles ganz einfach an. Und es lässt sich auch ganz leicht implementieren.

//+------------------------------------------------------------------+
//|                                                       trener.mq4 |
//|                                       Copyright © 2008, FXRaider |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, FXRaider"
 
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
extern int gap=5;
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//------------------------------
string solution="none"; 
int point, 
    point_neg, 
    point_pos;
//------------------------------    
//+---------------------------------------------------------------+
//|                      "up" choice searching                    | 
 if(
    ObjectGet("up", OBJPROP_PRICE1)==Open[1]+gap*Point
    &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==1
    &&ObjectFind("down") != 0
    &&ObjectFind("up") == 0
    )
    {
     solution="up";
    }
//|                      "up" choice searching                    |  
//+---------------------------------------------------------------+
  
//+---------------------------------------------------------------+
//|                      "down" choice searching                  |     
 if(
    ObjectGet("down", OBJPROP_PRICE1)==Open[1]-gap*Point
    &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==1    
    &&ObjectFind("up") != 0
    &&ObjectFind("down") == 0
    )
    {
     solution="down";
    }
//|                      "down" choice searching                  |       
//+---------------------------------------------------------------+    
 
//+---------------------------------------------------------------+
//|             counting points at a positive answer              |
    if((solution=="up"&&Open[1]<Close[1])
      ||(solution=="down"&&Open[1]>Close[1]))
    {
     point=1;
     point_pos=1;
     point_neg=0;     
    }  
//|             counting points at a positive answer              |   
//+---------------------------------------------------------------+
 
//+---------------------------------------------------------------+
//|             counting points at a negative answer              |    
    if((solution=="up"&&Open[1]>Close[1])
      ||(solution=="down"&&Open[1]<Close[1]))
    {
     point=-1;
     point_pos=0;
     point_neg=1;     
    } 
//|             counting points at a negative answer              |
//+---------------------------------------------------------------+
 
//+----------------------------------------------------------------------------------+
//|                              working with an external file                       |       
      int handle; 
      double points,     //total score
             points_pos, //score of positive answers
             points_neg; //score of negative answers 
       handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv",
                       FILE_CSV|FILE_WRITE|FILE_READ,";");
       if(handle>0) //if there is a file, read it
       { 
        points=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); 
        points_pos=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); 
        points_neg=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits);       
        FileClose(handle);
       } 
       
    if(solution!="none") //if a choice is made 
    {        
      handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv",
                      FILE_CSV|FILE_WRITE|FILE_READ,";");
      FileWrite(handle ,points+point);         //write the total score
      FileWrite(handle ,points_pos+point_pos); //write the score of positive answers
      FileWrite(handle ,points_neg+point_neg); //write the score of negative answers                    
      FileClose(handle); 
    } 
//|                              working with an external file                       | 
//+----------------------------------------------------------------------------------+    
 
//+------------------------------------------------------------------------------------+
//|                                 working with objects                               |   
  if(iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))>0
     ||ObjectGet("down",OBJPROP_PRICE1)!=Open[0]-gap*Point) 
    {
     ObjectDelete("down"); 
    }  
 if(iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))>0
    ||ObjectGet("up",OBJPROP_PRICE1)!=Open[0]+gap*Point) 
    { 
     ObjectDelete("up"); 
    } 
    
   if(ObjectFind("down") != 0&&ObjectFind("up") != 0) //if no object
   {
     ObjectCreate("down", OBJ_ARROW, 0, Time[0], Open[0]-gap*Point); //draw a down arrow
     ObjectSet("down", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("down", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
     ObjectSet("down", OBJPROP_COLOR, Red);
 
     ObjectCreate("up", OBJ_ARROW, 0, Time[0], Open[0]+gap*Point); //draw an up arrow
     ObjectSet("up", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("up", OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
     ObjectSet("up", OBJPROP_COLOR, Blue);
    }
//|                                 working with objects                               |   
//+------------------------------------------------------------------------------------+
 
Comment("Score: ", points," (",points_pos,"/",points_neg,   //show the score
        ") | Time: ", Hour(),":", Minute(),":", Seconds());//show time (for convenience) 
//----
   return(0);
  }
//+------------------------------------------------------------------+

Der Code beinhaltet Kommentare.


Nachdem wir ihn zu einem Chart hinzugefügt haben, erhalten wir die folgenden Resultate :




Wir sehen zwei Pfeile auf dem letzten Balken – einen nach oben und einen nach unten. In der oberen linken Ecke sehen wir die Gesamtpunktzahl im Spiel, sowie die Terminalzeit des letzten Ticks. Die Gesamtpunktzahl wird mit drei Zahlen angegeben: Die erste ist hierbei die Gesamtpunktzahl, die zweite (d.h. die erste in Klammern) ist die Zahl der positiven Antworten (das heißt die Anzahl der richtigen Vorhersagen), die dritte (die zweite in Klammern) ist die Anzahl der negativen Antworten (falsche Vorhersagen). Schließlich wird auch noch die Zeit angezeigt, was einfach der Bequemlichkeit des Benutzers im Vollbildschirmmodus dient (F11).


Um das Spiel zu „spielen,“ sollte man einen unbenötigten Pfeil auswählen, dann einen Doppelklick ausführen (Voreinstellung) und anschließend die Löschtaste betätigen, um diesen Pfeil zu löschen. Der verbleibende Pfeil gibt hierbei unsere Prognose an:




Jetzt warten wir auf den Beginn des nächsten Balken. Falls die Vorhersage korrekt sein sollte, so wird die Punktzahl in der folgenden Art und Weise angezeigt werden: "Score: 1(1/0)". Falls die Vorhersage nicht korrekt sein sollte, so wird die Punktzahl ("Score") wie folgt aussehen: "Score: -1(0/1)". Und falls der Schlusskurs mit dem Eröffnungskurs übereinstimmen sollte, dann wird die Punktzahl sich überhaupt nicht verändern. In unserem Beispiel war die Vorhersage falsch:




Verbesserung

Unsere Aufgabe ist damit erfüllt. Aber es gibt bei dieser Form der Implementierung einen Nachteil: Sie können Ihre Wahl während des gesamten Verlaufs der Kerze treffen, inklusive in den letzten Sekunden. Und dies ist eindeutig unfair. Es wäre besser, wenn man seine Wahl lediglich innerhalb der ersten 30 Sekunden treffen könnte. Zu diesem Zwecke wollen wir einmal die folgende externe int-Variable einführen: "time_limit". Ihr Wert wird stets der Anzahl der Sekunden entsprechen, innerhalb derer die Auswahl getroffen werden sollte. Falls ein Benutzer es nicht schaffen sollte, seine Auswahl innerhalb dieser Zeitperiode zu treffen, dann werden die Pfeile vom Chart gelöscht werden und erst wieder auf der nächsten Kerze erscheinen.

Die Veränderungen werden im Teil "Arbeit mit Objekten" erscheinen (Erklärungen stehen in den Kommentaren). Hier ist der Code:

//+------------------------------------------------------------------+
//|                                                       trener.mq4 |
//|                                       Copyright © 2008, FXRaider |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, FXRaider"
 
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
extern int gap=5;
extern int time_limit=30;
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//------------------------------
string solution="none"; 
int point, 
    point_neg, 
    point_pos;
//------------------------------    
//+---------------------------------------------------------------+
//|                      "up" choice searching                    | 
 if(
    ObjectGet("up", OBJPROP_PRICE1)==Open[1]+gap*Point
    &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==1
    &&ObjectFind("down") != 0
    &&ObjectFind("up") == 0
    )
    {
     solution="up";
    }
//|                      "up" choice searching                    |  
//+---------------------------------------------------------------+
  
//+---------------------------------------------------------------+
//|                      "down" choice searching                  |     
 if(
    ObjectGet("down", OBJPROP_PRICE1)==Open[1]-gap*Point
    &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==1    
    &&ObjectFind("up") != 0
    &&ObjectFind("down") == 0
    )
    {
     solution="down";
    }
//|                      "down" choice searching                  |       
//+---------------------------------------------------------------+    
 
//+---------------------------------------------------------------+
//|             counting points at a positive answer              |
    if((solution=="up"&&Open[1]<Close[1])
      ||(solution=="down"&&Open[1]>Close[1]))
    {
     point=1;
     point_pos=1;
     point_neg=0;     
    }  
//|             counting points at a positive answer              |   
//+---------------------------------------------------------------+
 
//+---------------------------------------------------------------+
//|             counting points at a negative answer              |    
    if((solution=="up"&&Open[1]>Close[1])
      ||(solution=="down"&&Open[1]<Close[1]))
    {
     point=-1;
     point_pos=0;
     point_neg=1;     
    } 
//|             counting points at a negative answer              |
//+---------------------------------------------------------------+
 
//+----------------------------------------------------------------------------------+
//|                              working with an external file                       |       
      int handle; 
      double points,     //total score
             points_pos, //score of positive answers
             points_neg; //score of negative answers 
       handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv",
                       FILE_CSV|FILE_WRITE|FILE_READ,";");
       if(handle>0) //if there is a file, read it
       { 
        points=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); 
        points_pos=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); 
        points_neg=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits);       
        FileClose(handle);
       } 
       
    if(solution!="none") //if a choice is made 
    {        
      handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv",
                      FILE_CSV|FILE_WRITE|FILE_READ,";");
      FileWrite(handle ,points+point);         //write the total score
      FileWrite(handle ,points_pos+point_pos); //write the score of positive answers
      FileWrite(handle ,points_neg+point_neg); //write the score of negative answers                    
      FileClose(handle); 
    } 
//|                              working with an external file                       | 
//+----------------------------------------------------------------------------------+    
 
//+------------------------------------------------------------------------------------+
//|                                 working with objects                               |   
  if(iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))>0
     ||ObjectGet("down",OBJPROP_PRICE1)!=Open[0]-gap*Point) 
    {
     ObjectDelete("down"); 
    }  
 if(iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))>0
    ||ObjectGet("up",OBJPROP_PRICE1)!=Open[0]+gap*Point)            
    { 
     ObjectDelete("up"); 
    } 
   
  int sec_lim;  
  if(!time_limit)
  {
   sec_lim=0; 
  }
  else
  {
   sec_lim=TimeCurrent()-time_limit;
  }
  if(sec_lim>ObjectGet("up",OBJPROP_TIME1)
     &&sec_lim>ObjectGet("down",OBJPROP_TIME1) 
     &&ObjectFind("down") == 0&&ObjectFind("up") == 0
     &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==0
     &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==0)            
    { 
     ObjectDelete("up"); 
     ObjectDelete("down");      
    } 
  
   if((ObjectFind("down") != 0&&ObjectFind("up") != 0) //if no objects
      &&sec_lim<Time[0])
   {
     ObjectCreate("down", OBJ_ARROW, 0, Time[0], Open[0]-gap*Point); //draw a down arrow
     ObjectSet("down", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("down", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
     ObjectSet("down", OBJPROP_COLOR, Red);
 
     ObjectCreate("up", OBJ_ARROW, 0, Time[0], Open[0]+gap*Point); //draw an up arrow
     ObjectSet("up", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("up", OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
     ObjectSet("up", OBJPROP_COLOR, Blue);
    }      
//|                                 working with objects                               |   
//+------------------------------------------------------------------------------------+
 
Comment("Score: ", points," (",points_pos,"/",points_neg,   //show the score
        ") | Time: ", Hour(),":", Minute(),":", Seconds());//Show time (for convenience) 
//----
   return(0);
  }
//+------------------------------------------------------------------+

Wir müssen also zwei veränderbare Variablen in den Eingabeparametern berücksichtigen :



Der Parameter "gap" gibt die Anzahl der Punkte an – d.h. die Distanz zwischen den Pfeilen und dem Eröffnungspreis bei der jeweiligen Kerze. Die Variable "time_limit" gibt die Anzahl der Sekunden an, während derer ein Benutzer seine Auswahl treffen kann. Falls ihr Wert "0" sein sollte, dann wird es keinerlei Zeitbeschränkungen geben. D.h., dass der Benutzer seine Auswahl während der gesamten Dauer der Kerze treffen kann.

Schlussfolgerung

Wir haben nun also eine einfache Version der Modellierung von Finanzwetten implementiert, indem wir die Programmiersprache MQL4 verwendet haben. Dieses Spiel kann Ihnen sehr dabei helfen, Ihre Fähigkeit zu entwickeln, die zukünftige Entwicklung des Marktes vorherzusehen, und es kann Ihnen ebenfalls dabei helfen, mehr über die immer wiederkehrenden Muster bei den Kursbewegungen von Finanzhandelsprodukten zu erfahren. Diese Version ist in einer solchen Art und Weise implementiert worden, dass die Aufmerksamkeit eines Traders ganz gezielt und vollkommen auf den Preis-Chart konzentriert wird. Die Operationen, die durch denTrader ausgeführt werden, erfordern ein Minimum an Zeitaufwand, und sie sind sehr einfach zu verstehen.

Ich würde gerne meine eigenen Resultate des Spiels mit Ihnen teilen. Ich habe es geschafft, korrekte Vorhersagen für 5-10 Kerzen in Folge zu treffen (auf einem 5-Minuten-Chart).

Unter Zuhilfenahme dieses Spiels kann ein Trader die Fähigkeit erlernen, eine der wichtigsten Fragen überhaupt zu beantworten: In welche Richtung wird sich ein Finanzhandelsprodukte bewegen? Dennoch verbleiben auch hierbei immer noch eine Menge anderer wichtiger Fragen, wie die Bestimmung des Gewinns, die Bestimmung des Verlustes, die Festlegung des Handelsvolumens, mit dem man einen Trade eröffnen will, etc. Lediglich der Trader, der die Antworten auf all diese Fragen kennt, kann zuverlässige Resultate erzielen.

Eine weitere wichtige Frage ist die Ruhezeit des Traders. Dieses Spiel kann sich als viel sinnvoller als jedes andere Spiel erweisen, das es auf dem Videospielmarkt derzeit gibt.