MetaTrader 5 herunterladen

Maschinelles Lernen: Wie Support Vector Machines beim Handeln verwendet werden können

27 Juni 2016, 16:32
Josh Readhead
0
630

Was ist eine Support Vector Machine?

Eine Support Vector Machine ist eine Methode des maschinellen Lernens, bei der eingegebene Daten in eine von zwei Kategorien klassifiziert werden. Damit eine Support Vector Machine effektiv ist, ist es notwendig, zuerst einen Satz Übungsdaten zu verwenden, um ein Modell einer Support Vector Machine zu bauen, das für die Klassifizierung von neuen Daten verwendet werden kann.

Eine Support Vector Machine entwickelt dieses Modell, indem sie die Übungseingabedaten nimmt, sie in multidimensionale Räume zeichnet und dann anhand der Regressionsmethode eine Hyperebene findet, die die zwei Eingabeklassen am besten teilt (eine Hyperebene ist eine Oberfläche im n-dimensionalen Raum, die ihn in zwei Hälften teilt). Sobald die Support Vector Machine eingestellt wurde, kann sie mit der geteilten Hyperebene neue Eingaben bewerten, und sie in eine der zwei Kategorien ordnen.

Eine Support Vector Machine ist im Endeffekt eine Eingabe/Ausgabe-Maschine. Ein Benutzer kann eine Eingabe eingeben, und je nach im Training entwickelten Modell wird sie eine Ausgabe ausgeben. Die Eingabezahl einer beliebigen Support Vector Machine reicht theoretisch von eins zu unendlich, aber praktisch begrenzt die Rechenleistung die Menge an Eingaben. Wenn zum Beispiel N Eingaben für eine bestimmte Support Vector Machine verwendet werden (der ganzzahlige Wert N kann von eins bis nach unendlich gehen), muss die Support Vector Machine jeden Eingabesatz in N-dimensionalen Raum zeichnen und eine (N-1)-dimensionale Hyperebene finden, die die Trainingsdaten am besten trennt.

Eingabe/Ausgabe Maschine

Abbildung 1 Eine Support Vector Machine ist eine Eingabe/Ausgabe-Maschine.

Am besten zeigt man die Funktionsweise einer Support Vector Machine, indem man den zweidimensionalen Fall anschaut. Angenommen, wir wollen eine Support Vector Machine entwerfen, die zwei Eingaben hat und eine einzelne Ausgabe zurück gibt, die den Datenpunkt in eine von zwei Kategorien zuordnet. Wir können dies darstellen indem wir es in ein zweidimensionales Diagramm zeichnen, wie das untere Diagramm.

Teilende Hyperebene

Abbildung 2 Links: Eingaben in eine Support Vector Machine, die in ein 2D-Diagramm gezeichnet wurden. Die roten Kreise und blauen Kreuze werden verwendet, um die zwei Eingabeklassen zu bezeichnen.

Abbildung 3 Rechts: Eingaben in eine Support Vector Machine, die in ein 2D-Diagramm gezeichnet wurden. Die roten Kreise und blauen Kreuze werden für die Bezeichnung von zwei Eingabeklassen verwendet, und die schwarze Linie zeigt die teilende Hyperebene an.

In diesem Beispiel stehen die blauen Kreuze für Datenpunkte, die in die Kategorie eins gehören, und die roten Kreise bezeichnen Datenpunkte, die in Kategorie zwei gehören. Jeder der individuellen Datenpunkte hat den einzigartigen Eingabewert 1 (der von ihrer Position auf der x-Achse dargestellt wird) und den einzigartigen Eingabewert 2 (von ihrer Position auf der y-Achse dargestellt) und alle diese Punkte wurden in den zweidimensionalen Raum gezeichnet.

Eine Support Vector Machine kann Daten klassifizieren, indem sie ein Modell dieser Punkte im zweidimensionalen Raum erstellt. Die Support Vector Machine überwacht die Daten im zweidimensionalen Raum und verwendet einen Regressions-Algorithmus, um eine eindimensionale Hyperebene zu finden, die die Daten sehr genau in die zwei Kategorien aufteilt. Die teilende Linie wird dann von der Support Vector Machine verwendet, um neue Datenpunkte entweder in Kategorie eins oder zwei aufzuteilen.

Die untere Animation zeigt die Prozesse des Trainings einer neuen Support Vector Machine. Der Algorithmus startet mit einer zufälligen Vermutung, wo die teilende Hyperebene ist, um dann iterativ die Genauigkeit der Hyperebene zu verbessern. Wie Sie sehen fängt der Algorithmus sehr aggressiv an, wird aber langsamer wenn die gewünschte Lösung näher kommt.

Support Vector Machine Regressionsalgorithmus auf der Suche nach der besten teilenden Hyperebene

Abbildung 4 Eine Animation zeigt Support Vector Machine Training. Die Hyperebene konvergiert fortlaufend auf der idealen Geometrie um zwei Klassen von Daten zu teilen.

Höhere Dimensionen

Das oben präsentierte zweidimensionale Szenario erlaubt es uns, den Prozess einer Support Vector Machine zu visualisieren, es ist aber nur die Klassifizierung eines Datenpunkts mit zwei Eingaben möglich. Was, wenn wir mehr Eingaben benutzen wollen? Zum Glück erlaubt uns der Support-Vector-Machine-Algorithmus dasselbe in höheren Dimensionen, aber die Konzeptionalisierung wird schwerer.

Das gilt es zu beachten, wenn Sie eine Support Vector Machine erstellen wollen, die 20 Eingaben macht, jeden Datenpunkt klassifizieren kann und ihn anhand der Eingaben entweder Kategorie eins oder zwei zuordnet. Um dies zu tun, modelliert die Support Vector Machine die Daten in 20-dimensionalem Raum und verwendet einen Regressionsalgorithmus, um eine 19-dimensionale Hyperebene zu finden, die die Datenpunkte in zwei Kategorien einteilt. Es wird überaus schwierig, dies wie es ist zu visualisieren, da alles, was über 3 Dimensionen hinaus geht, von Menschen nicht verstanden werden kann. Aber das Wichtigste ist, dass alles genauso funktioniert, wie im Fall mit den zwei Dimensionen.


Wie funktionieren Support Vector Machines? Beispiel: Ist es ein Schnick?

Stellen Sie sich folgendes hypothetisches Szenario vor: Sie sind ein Forscher und untersuchen seltene Tiere, die nur in den Tiefen der Arktis leben, die Schnicks. Da diese Tiere so zurückgezogen leben, konnte nur eine kleine Menge je gefunden werden (sagen wir ungefähr 5.000 Exemplare). Als Forscher stehen Sie nun vor der Frage, wie man einen Schnick identifizieren kann?

Ihnen stehen lediglich zuvor veröffentlichte Forschungsberichte jener, die Schnicks schon einmal gesehen haben, zur Verfügung. In diesen Forschungsberichten beschreiben die Autoren bestimmte Eigenschaften der Schnicks die sie gefunden haben, zum Beispiel Größe, Gewicht, Anzahl der Beine, etc. Aber all diese Eigenschaften variieren je nach Bericht, nach keinem erkennbaren Muster.

Wie können wir die Daten verwenden, um ein neues Tier als Schnick zu identifizieren?

Eine mögliche Lösung für unser Problem ist eine Support Vector Machine, um die Muster in den Daten zu identifizieren und einen Rahmen zu erstellen, mit dem man Tiere entweder als Schnick identifizieren kann, oder nicht. Der erste Schritt ist die Erstellung eines Datensatzes, der für das Training einer Support Vector Machine verwendet werden kann, um Schnicks zu identifizieren. Die Trainingsdaten sind einige Eingaben und passende Ausgaben, die die Support Vector Machine analysieren und ein Muster extrahieren kann.

Daher müssen wir entscheiden, welche Eingaben verwendet werden, und wie viele. Theoretisch können wir so viele Eingaben machen wie wir wollen, aber das kann oft zu einem langsamen Training führen (je mehr Eingaben man hat, desto mehr Zeit braucht die Support Vector Machine, um Muster zu extrahieren). Vielleicht sollten Sie auch Eingabewerte auswählen, die für alle Schnicks typisch sind. Zum Beispiel wären Größe oder Gewicht der Tiere gute Eingaben, da man meinen könnte, das wäre ziemlich gleich bei allen Schnicks. Das durchschnittliche Alter eines Tieres wäre aber kein guter Eingabewert, da sich das Alter der Tiere stark unterscheiden kann.

Aus diesem Grund wurden die folgenden Eingaben gewählt.

  • Größe
  • Gewicht
  • Anzahl der Glieder
  • Anzahl der Augen
  • Länge der Glieder
  • Durchschnittliche Geschwindigkeit
  • Brunsthäufigkeit

Mit diesen Eingaben können wir unsere Trainingsdaten kompilieren. Effektive Trainingsdaten für eine Support Vector Machine müssen bestimmten Kriterien entsprechen:

  • Die Daten müssen Beispiele von Tieren haben, die Schnicks sind
  • Die Daten müssen Beispiele von Tieren haben, die keine Schnicks sind

In diesem Fall haben wir Forschungsberichte von Wissenschaftlern, die erfolgreich einen Schnick identifiziert und seine Eigenschaften aufgeschrieben haben. Daher können wir diese Berichte lesen, die Daten jeder Eingabe extrahieren und eine Ausgabe entweder als richtig oder falsch jedem dieser Beispiele zuteilen. Die Trainingsdaten in diesem Fall sind vielleicht ähnlich wie in der unteren Tabelle.

Trainingsbeispiele Größe [mm] Gewicht [kg] N_legs (Anzahl Glieder) N_eyes (Anzahl Augen) L_arm [mm] (Länger Glieder) av_speed [m/s] (durchschnittliche Geschwindigkeit) f_call [Hz] (Brunst) Schnick (true/false)
Beispiel 1 1030 45 8 3 420 2,1 14000 TRUE
Beispiel 2 1010 42 8 3 450 2,2 14000 TRUE
Beispiel 3 900 40 7 6 600 6 13000 FALSE
Beispiel 4 1050 43 9 4 400 2,4 12000 TRUE
Beispiel 5 700 35 2 8 320 21 13500 FALSE
Beispiel 6 1070 42 8 3 430 2,4 12000 TRUE
Beispiel 7 1100 40 8 3 430 2,1 11000 TRUE
Beispiel: ... ... ... ... ... ... ... ...

Tabelle 1 Beispiel der Schnick-Beobachtung

Wenn wir einmal die Daten für alle Trainings-Eingaben gesammelt haben, können wir sie verwenden, um unsere Support Vector Machine zu trainieren. Während des Trainingsprozesses erstellt die Support Vector Machine ein Modell im siebendimensionalen Raum, das verwendet werden kann, um jedes der Trainingsbeispiele in entweder true (wahr) oder false (falsch) zu ordnen. Die Support Vector Machine wird mit dieser Tätigkeit fortfahren, bis sie ein Modell hat, das die Trainingsdaten korrekt darstellt (innerhalb der festgesetzten Fehlertoleranz). Sobald das Training abgeschlossen ist, kann dieses Modell dafür verwendet werden, neue Datenpunkte als entweder true oder false zu identifizieren.


Funktioniert diese Support Vector Machine wirklich?

Anhand des Schnick-Beispieles habe ich ein Skript geschrieben, das prüft wie gut eine Support Vector Machine tatsächlich Schnicks identifizieren kann. Dafür habe ich die Funktionsbibliothek “Support Vector Machine Learning Tool” verwendet, die vom Markt heruntergeladen werden kann.

Um dieses Szenario erfolgreich zu modellieren, müssen wir erst bestimmen, was die eigentlichen Eigenschaften eines Schnicks sind. Die in diesem Fall angenommenen Eigenschaften sind in der unteren Tabelle aufgelistet. Wenn ein Tier alle Kriterien erfüllt, ist es ein Schnick.

Parameter Unterer Bereich Oberer Bereich
Größe [mm] 1000 1100
Gewicht [kg] 40 50
N_legs (Anzahl Glieder) 8 10
N_eyes (Anzahl Augen) 3 4
L_arm [mm] (Länge Glieder) 400 450
av_speed [m/s] (durchschnittliche Geschwindigkeit) 2 2,5
f_call [Hz] (Brunst) 11000 15000

Tabelle 2. Zusammenfassung der Parameter, die einen Schnick definieren

Da wir nun unseren Schnick definiert haben, können wir diese Definition dazu benutzen, mit den Support Vector Machines zu experimentieren. Der erste Schritt ist die Schaffung einer Funktion, die sieben Eingaben für ein bestimmtes Tier aufnehmen kann und die tatsächliche Klassifizierung des Tieres als "Schnick" oder "nicht" ausgeben kann. Diese Funktion wird verwendet, um Trainingsdaten für die Support Vector Machine zu generieren, sowie ihre Performance am Ende. Das geschieht mithilfe unterer Funktion:

//+------------------------------------------------------------------+
//| This function takes the observation properties of the observed 
//| animal and based on the criteria we have chosen, returns true/false whether it is a schnick
//+------------------------------------------------------------------+
bool isItASchnick(double height,double weight,double N_legs,double N_eyes,double L_arm,double av_speed,double f_call)
  {
   if(height   < 1000  || height   > 1100)  return(false);   // If the height is outside the parameters > return(false)
   if(weight   < 40    || weight   > 50)    return(false);   // If the weight is outside the parameters > return(false)
   if(N_legs   < 8     || N_legs   > 10)    return(false);   // If the N_Legs is outside the parameters > return(false)
   if(N_eyes   < 3     || N_eyes   > 4)     return(false);   // If the N_eyes is outside the parameters > return(false)
   if(L_arm    < 400   || L_arm    > 450)   return(false);   // If the L_arm  is outside the parameters > return(false)
   if(av_speed < 2     || av_speed > 2.5)   return(false);   // If the av_speed is outside the parameters > return(false)
   if(f_call   < 11000 || f_call   > 15000) return(false);   // If the f_call is outside the parameters > return(false)
   return(true);                                             // Otherwise > return(true)
  }

Der nächste Schritt im Prozess ist die Schaffung einer Funktion die die Trainingsein- und -ausgaben generieren kann. Eingaben werden in diesem Fall durch die Schaffung von zufälligen Nummern in einem bestimmten Bereich der sieben Eingabewerte generiert. Dann wird für jede dieser zufällig generierten Eingaben die obige Funktion isItASchnick() verwendet, um die gewünschte Ausgabe zu generieren. Dies geschieht in der folgenden Funktion:

//+------------------------------------------------------------------+
//| This function takes an empty double array and an empty boolean array,
//| and generates the inputs/outputs to be used for training the SVM
//+------------------------------------------------------------------+ 
void genTrainingData(double &inputs[],bool &outputs[],int N)
  {
   double in[];                    // Creates an empty double array to be used for temporarily storing the inputs generated
   ArrayResize(in,N_Inputs);       // Resize the in[] array to N_Inputs
   ArrayResize(inputs,N*N_Inputs); // Resize the inputs[] array to have a size of N*N_Inputs 
   ArrayResize(outputs,N);         // Resize the outputs[] array to have a size of N 
   for(int i=0;i<N;i++)
     {
      in[0]=    randBetween(980,1120);      // Random input generated for height
      in[1]=    randBetween(38,52);         // Random input generated for weight
      in[2]=    randBetween(7,11);          // Random input generated for N_legs
      in[3]=    randBetween(3,4.2);         // Random input generated for N_eyes
      in[4]=    randBetween(380,450);       // Random input generated for L_arms
      in[5]=    randBetween(2,2.6);         // Random input generated for av_speed
      in[6]=    randBetween(10500,15500);   // Random input generated for f_call
      ArrayCopy(inputs,in,i*N_Inputs,0,N_Inputs);                         // Copy the new random inputs generated into the training input array
      outputs[i]=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]); // Assess the random inputs and determine if it is a schnick
     }
  }
//+------------------------------------------------------------------+
//| This function is used to create a random value between t1 and t2
//+------------------------------------------------------------------+ 
double randBetween(double t1,double t2)
  {
   return((t2-t1)*((double)MathRand()/(double)32767)+t1);
  }

Nun haben wir einen Satz an Trainingseingaben und -ausgaben, und es ist Zeit, unsere Support Vector Machine mit dem auf dem Markt erhältlichen Werkzeug "Support Vector Machine Learning Tool" zu erstellen Wenn einmal eine neue Support Vector Machine erstellt wurde, ist es notwendig, die Trainingseingabe und -ausgabe einzugeben und das Training auszuführen.

void OnStart()
  {
   double inputs[];              // Empty double array to be used for creating training inputs
   bool   outputs[];             // Empty bool array to be used for creating training inputs
   int    N_TrainingPoints=5000; // Defines the number of training samples to be generated
   int    N_TestPoints=5000;     // Defines the number of samples to be used when testing

   genTrainingData(inputs,outputs,N_TrainingPoints); //Generates the inputs and outputs to be used for training the SVM

   int handle1=initSVMachine();             // Initializes a new support vector machine and returns a handle
   setInputs(handle1,inputs,7);             // Passes the inputs (without errors) to the support vector machine
   setOutputs(handle1,outputs);             // Passes the outputs (without errors) to the support vector machine
   setParameter(handle1,OP_TOLERANCE,0.05); // Sets the error tolerance parameter to <5%
   training(handle1);                       // Trains the support vector machine using the inputs/outputs passed
  }

Nun haben wir eine Support Vector Machine, die erfolgreich im Identifizieren von Schnicks trainiert wurde. Um dies zu bestätigen, können wir die endgültige Support Vector Machine testen indem wir sie beauftragen, neue Datenpunkte zu klassifizieren. Dies wird zunächst mit der Generierung von zufälligen Eingaben erreicht, dann verwenden wir die Funktion isItASchnick(), um festzustellen, ob diese Eingaben einem tatsächlichen Schnick entsprechen, und dann verwenden wir die Support Vector Machine um die Eingaben zu klassifizieren und festzustellen, ob das vorhergesagte Ergebnis dem tatsächlichen Ergebnis entspricht. Dies geschieht in der folgenden Funktion:

//+------------------------------------------------------------------+
//| This function takes the handle for the trained SVM and tests how
//| successful it is at classifying new random inputs
//+------------------------------------------------------------------+ 
double testSVM(int handle,int N)
  {
   double in[];
   int atrue=0;
   int afalse=0;
   int N_correct=0;
   bool Predicted_Output;
   bool Actual_Output;
   ArrayResize(in,N_Inputs);
   for(int i=0;i<N;i++)
     {
      in[0]=    randBetween(980,1120);      // Random input generated for height
      in[1]=    randBetween(38,52);         // Random input generated for weight
      in[2]=    randBetween(7,11);          // Random input generated for N_legs
      in[3]=    randBetween(3,4.2);         // Random input generated for N_eyes
      in[4]=    randBetween(380,450);       // Random input generated for L_arms
      in[5]=    randBetween(2,2.6);         // Random input generated for av_speed
      in[6]=    randBetween(10500,15500);   // Random input generated for f_call
      Actual_Output=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]); // Uses the isItASchnick fcn to determine the actual desired output
      Predicted_Output=classify(handle,in);                                  // Uses the trained SVM to return the predicted output.
      if(Actual_Output==Predicted_Output)
        {
         N_correct++;   // This statement keeps count of the number of times the predicted output is correct.
        }
     }

   return(100*((double)N_correct/(double)N));   // Returns the accuracy of the trained SVM as a percentage
  }

Ich empfehle Ihnen, mit den Werten innerhalb der oberen Funktionen herumzuspielen, um zu sehen, wie die Support Vector Machine sich unter verschiedenen Bedingungen verhält.


Warum ist die Support Vector Machine so nützlich?

Der Vorteil einer Support Vector Machine für die Extraktion komplexer Muster von den Daten ist, dass ein voriges Verständnis des Datenverhaltens nicht notwendig ist. Eine Support Vector Machine kann die Daten analysieren und die Einblicke in die Beziehungen extrahieren. So funktioniert sie ähnlich einer Black Box, die Eingaben empfängt und Ausgaben generiert, was sehr nützlich sein kann bei der Suche nach Mustern in den Daten, die zu komplex und nicht offensichtlich sind.

Eine der besten Eigenschaften der Support Vector Machines ist, dass sie sehr gut mit Fehlern und Ungenauigkeiten in den Daten umgehen können. Sie können oft tiefer liegende Muster in den Daten erkennen und die Ausreißerdaten und andere Komplikationen ausfiltern Stellen Sie sich vor, dass Sie mit Ihrer Forschung über Schnicks auf zahlreiche Forschungsberichte stoßen, die Schnicks mit sehr verschiedenen Eigenschaften beschreiben (zum Beispiel ein Schnick, der 220 kg wiegt und 150.000 mm groß ist).

Fehler wie diese führen zu Verzerrungen des Modells was ein Schnick ist, was bei der Klassifizierung neuer Schnick-Funde potenziell zu Fehlern führen kann. Der Vorteil einer Support Vector Machine ist, dass sie ein Modell entwickeln wird, das mit dem unterliegenden Muster übereinstimmt, im Gegensatz zu einem Modell, das all den Trainingsdatenpunkten entspricht. Dieser Vorteil besteht dank einer bestimmten Anzahl erlaubter Fehler im Modell, um die Support Vector Machine dazu zu befähigen, etwaige Fehler in den Daten zu übersehen.

Im Falle der Support Vector Machine für Schnicks wird der Trainingsdurchlauf ein Modell erstellen, das lediglich mit 95% der Trainingsdaten übereinstimmt, wenn wir eine Fehlertoleranz von 5% erlauben. Das kann nützlich sein, da es dem Trainingsdurchlauf erlaubt, die kleine Prozentzahl an Ausreißern zu ignorieren.

Wir können diese Eigenschaft der Support Vector Machine weiter erforschen, indem wir unser Schnick-Skript anpassen. Die untere Funktion wurde hinzugefügt, um absichtliche, zufällige Fehler in unseren Datensatz einzuführen. Diese Funktion wird zufällig Trainingspunkte auswählen und die Eingaben und entsprechende Ausgaben durch zufällige Variablen ersetzen.

//+------------------------------------------------------------------+
//| This function takes the correct training inputs and outputs generated
//| and inserts N random errors into the data
//+------------------------------------------------------------------+ 
void insertRandomErrors(double &inputs[],bool &outputs[],int N)
  {
   int    nTrainingPoints=ArraySize(outputs); // Calculates the number of training points
   int    index;                              // Creates new integer 'index'
   bool   randomOutput;                       // Creates new bool 'randomOutput'
   double in[];                               // Creates an empty double array to be used for temporarily storing the inputs generated
   ArrayResize(in,N_Inputs);                  // Resize the in[] array to N_Inputs
   for(int i=0;i<N;i++)
     {
      in[0]=    randBetween(980,1120);        // Random input generated for height
      in[1]=    randBetween(38,52);           // Random input generated for weight
      in[2]=    randBetween(7,11);            // Random input generated for N_legs
      in[3]=    randBetween(3,4.2);           // Random input generated for N_eyes
      in[4]=    randBetween(380,450);         // Random input generated for L_arms
      in[5]=    randBetween(2,2.6);           // Random input generated for av_speed
      in[6]=    randBetween(10500,15500);     // Random input generated for f_call

      index=(int)MathRound(randBetween(0,nTrainingPoints-1)); // Randomly chooses one of the training inputs to insert an error
      if(randBetween(0,1)>0.5) randomOutput=true;             // Generates a random boolean output to be used to create an error
      else                     randomOutput=false;

      ArrayCopy(inputs,in,index*N_Inputs,0,N_Inputs);         // Copy the new random inputs generated into the training input array
      outputs[index]=randomOutput;                            // Copy the new random output generated into the training output array
     }
  }

Diese Funktion erlaubt uns, absichtliche Fehler in unseren Trainingsdatensatz einzuführen. Mit diesen fehlerhaften Daten können wir eine neuen Support Vector Machine erstellen und trainieren und ihre Leistung mit der ursprünglichen vergleichen.

void OnStart()
  {
   double inputs[];              // Empty double array to be used for creating training inputs
   bool   outputs[];             // Empty bool array to be used for creating training inputs
   int    N_TrainingPoints=5000; // Defines the number of training samples to be generated
   int    N_TestPoints=5000;     // Defines the number of samples to be used when testing

   genTrainingData(inputs,outputs,N_TrainingPoints); // Generates the inputs and outputs to be used for training the svm

   int handle1=initSVMachine();             // Initializes a new support vector machine and returns a handle
   setInputs(handle1,inputs,7);             // Passes the inputs (without errors) to the support vector machine
   setOutputs(handle1,outputs);             // Passes the outputs (without errors) to the support vector machine
   setParameter(handle1,OP_TOLERANCE,0.05); // Sets the error tolerance parameter to <5%
   training(handle1);                       // Trains the support vector machine using the inputs/outputs passed

   insertRandomErrors(inputs,outputs,500);  // Takes the original inputs/outputs generated and adds random errors to the data

   int handle2=initSVMachine();             // Initializes a new support vector machine and returns a handle
   setInputs(handle2,inputs,7);             // Passes the inputs (with errors) to the support vector machine
   setOutputs(handle2,outputs);             // Passes the outputs (with errors) to the support vector machine
   setParameter(handle2,OP_TOLERANCE,0.05); // Sets the error tolerance parameter to <5%
   training(handle2);                       // Trains the support vector machine using the inputs/outputs passed

   double t1=testSVM(handle1,N_TestPoints); // Tests the accuracy of the trained support vector machine and saves it to t1
   double t2=testSVM(handle2,N_TestPoints); // Tests the accuracy of the trained support vector machine and saves it to t2

   Print("The SVM accuracy is ",NormalizeDouble(t1,2),"% (using training inputs/outputs without errors)");
   Print("The SVM accuracy is ",NormalizeDouble(t2,2),"% (using training inputs/outputs with errors)");
   deinitSVMachine();                       // Cleans up all of the memory used in generating the SVM to avoid memory leak
  }

Das Skript produziert bei seiner Ausführung folgende Ergebnisse im Expert-Protokoll. Innerhalb eines Trainingsdatensatzes mit 5.000 Trainingspunkten konnten wir 500 zufällige Fehler einführen. Beim Vergleich der Performance dieser fehlerhaften Support Vector Machine mit der ursprünglichen ist die Leistung nur durch <1% reduziert. Das liegt daran, dass die Support Vector Machine beim Training die Ausreißer eines Datensatzes übersehen kann und sie aber trotzdem ein eindrucksvoll präzises Modell der wahren Daten produziert. Das legt nahe, dass die Support Vector Machines potenziell ein nützlicheres Werkzeug sein könnten bei der Extraktion komplexer Muster und Einblicken in unklare Datensätze.

Expert Advisor Protokoll

Abbildung 5 Das resultierende Expert Advisor Protokoll aus dem Durchlauf des "Schnick"-Skript im MetaTrader5.


Demo Versionen

Eine Vollversion des obigen Codes kann von Code Base heruntergeladen werden, aber dieses Skript kann nur von Ihrem Terminal ausgeführt werden, wenn Sie eine Vollversion des Werkzeugs "Support Vector Machine Learning Tool" vom Markt heruntergeladen haben. Wenn Sie nur eine Demoversion dieses Werkzeugs heruntergeladen haben, dürfen Sie das Werkzeug nur via dem Strategietester nutzen. Um den "Schnick"-Code mit der Demoversion des Werkzeugs zu testen, habe ich eine Kopie des Skripts in einen Expert Advisor geschrieben, der mit dem Strategietester verwendet werden kann. Beide dieser Code-Versionen können durch folgenden Link heruntergeladen werden:

  • Vollversion - mit einem Skript, das vom MetaTrader5-Terminal ausgeführt werden kann (man braucht eine gekaufte Version des "Support Vector Machine Learning Tool")

  • Demo Version - mit einem Expert Advisor, der vom MetaTrader5-Strategietester ausgeführt wird (möglich mit der Demoversion des "Support Vector Machine Learning Tool")


Wie können Support Vector Machines auf dem Markt verwendet werden?

Zugegeben, das obige Schnick-Beispiel ist recht einfach, aber es gibt einige Ähnlichkeiten, die zwischen diesem Beispiel und dem Gebrauch der Support Vector Machine für technische Marktanalysen gezogen werden können.

Technische Analysen bestehen grundlegend aus historischen Marktdaten, mit denen zukünftige Preisbewegungen vorausgesagt werden können Beim Schnick-Beispiel haben wir auch die Beobachtungen früherer Forscher benutzt, um zu entscheiden, ob ein neu entdecktes Tier ein Schnick ist, oder nicht. Außerdem wird der Markt von unklaren Daten, Fehlern und statistischen Ausreißern geplagt, die den Gebrauch einer Support Vector Machine interessant machen.

Die Grundlage für eine signifikante Anzahl Ansätze technischer Handelsanalyse beinhaltet die folgenden Schritte:

  1. Die Beobachtung einiger Indikatoren
  2. Die Identifikation der Bedingungen, die für jeden Indikator mit einem potentiell erfolgreichen Handel einhergehen
  3. Die Beurteilung, welcher der Indikatoren einen Handel signalisiert

Ähnliche Vorgehensweisen sind möglich bei der Verwendung von Support Vector Machines, um neue Handel ähnlich zu signalisieren. Das "Support Vector Machine Learning Tool" wurde mit diesem Ziel im Sinne entwickelt. Eine vollständige Beschreibung der Verwendung dieses Tools ist im Markt erhältlich, dies ist also nur ein schneller Überblick. Der Prozess für die Verwendung dieses Werkzeugs lautet wie folgt:

Blockdiagramm

Abbildung 6 Das Blockdiagramm zeigt den Prozess einer Implementierung des "Support Vector Machine Tool" in einem Expert Advisor.

Bevor Sie das "Support Vector Machine Learning Tool" verwenden, ist es wichtig, dass Sie verstehen, wie man Trainingseingaben und -ausgaben generiert.

Wie werden Trainingseingaben generiert?

Die Indikatoren, die Sie als Eingabe verwenden wollen, genauso wie Ihre neue Support Vector Machine, wurden bereits initialisiert. Der nächste Schritt ist, die Indikator-Identifikatoren in Ihre neue Support Vector Machine zu geben und sie zu programmieren, wie die Trainingsdaten generiert werden. Dies geschieht durch Aufruf der Funktion setIndicatorHandles(). Mit dieser Funktion können Sie die Identifikatoren von initialisierten Indikatoren in die Support Vector Machine geben. Das macht man, indem man ein ganzzahliges Array mit den Identifikatoren übergibt. Die zwei anderen Eingaben dieser Funktion sind der Offsetwert und die Anzahl von Datenpunkten.

Der Offsetwert bezeichnet den Offset zwischen dem aktuellen Balken und dem Startbalken, die bei der Generierung der Trainingseingaben verwendet werden, und die Anzahl der Trainingspunkte (bezeichnet von N) bestimmt die Größe der Trainingsdaten. Das untere Diagramm zeigt wie diese Werte verwendet werden. Ein Offsetwert 4 und ein N-Wert 6 befehlen der Support Vector Machine, nur die Balken zu verwenden, die im weißen Quadrat sind, um Trainingseingaben und -ausgaben zu generieren. Ein Offsetwert 8 und ein N-Wert 8 befehlen der Support Vector Machine, nur die Balken zu verwenden, die im blauen Quadrat sind, um Trainingseingaben und -ausgaben zu generieren.

Sobald die Funktion setIndicatorHandles() aufgerufen wurde, ist es möglich, die Funktion genInputs() aufzurufen. Diese Funktion wird den Indikator-Identifikator verwenden, um einen Array aus Eingabedaten zu generieren, die im Training verwendet werden können.

Abbildung 7 Kerzen-Chart mit den Werten Offset und N

Abbildung 7 Kerzen-Chart mit den Werten Offset und N


Wie werden Trainingsausgaben generiert?

Trainingsausgaben werden durch die Simulation hypothetischer Handel generiert, die auf historischen Preisdaten basieren, und sie bestimmen, ob solch ein Handel erfolgreich hätte sein können oder nicht. Um dies zu tun, gibt es einige Parameter, die verwendet werden um das Support Vector Machine Learning Tool anzuleiten, wie man einen hypothetischen Handel als entweder erfolgreich oder nicht erfolgreich beurteilt.

Die erste Variable ist OP_TRADE. Ihr Wert kann entweder BUY oder SELL sein und entspricht entweder hypothetischen Käufen oder Verkäufen. Ist der Wert BUY, wird er bei der Generierung von Ausgaben nur auf potentiellen Erfolg von hypothetischen Käufen schauen. Ist der Wert SELL, wird er bei der Generierung von Ausgaben nur auf potentiellen Erfolg von hypothetischen Verkäufen schauen.

Die nächsten Werte für diese hypothetischen Handel sind Stop Loss und Take Profit. Die Werte sind in "pips" gesetzt und bestimmen die Grenzen der hypothetischen Handel.

Der Endparameter ist die Handelsdauer. Diese Variable wird in Stunden gemessen, und sie wird sicherstellen, dass nur innerhalb der maximalen Zeit vervollständigte Handel erfolgreich sind. Diese Variable wird inkludiert, um zu vermeiden, dass die Support Vector Machine Handel in einem langsamen Markt signalisiert.


Wichtiges bei der Auswahl von Eingaben

Es ist wichtig, ein bisschen über die Eingabe nachzudenken, wenn Support Vector Machines in ihre Geschäfte einbezogen werden sollen. Ähnlich wie beim Schick-Beispiel ist es wichtig, eine Eingabe auszuwählen, die alle Möglichkeiten abdeckt. Zum Beispiel könnte es verlockend sein, einen gleitenden Durchschnitt als Eingabe auszuwählen, aber da der längerfristige Durchschnittspreis dazu tendiert, sich dramatisch zu ändern, ist ein gleitender Durchschnitt alleine vielleicht nicht die beste Eingabe. Das kommt daher, dass es keine signifikante Ähnlichkeit zwischen dem gleitenden Durchschnitt heute und dem gleitenden Durchschnittswert vor sechs Monaten gibt.

Angenommen, wir handeln EURUSD und verwenden eine Supporting Vector Machine mit einer gleitenden Durchschnitt-Eingabe, um einen Kauf zu signalisieren. Angenommen der aktuelle Preis beträgt 1,10, aber die generierten Trainingsdaten sind von vor sechs Monaten, als der Preis noch 0,55 war. Beim Training der Support Vector Machine ist das gefundene Muster vielleicht nur ein Handel, der signalisiert wird, wenn der Preis um 0,55 ist, da dies die einzigen Daten sind, die sie kennt. Daher darf die Support Vector Machine nie einen Handel signalisieren, bis der Preis wieder auf 0,55 fällt.

Stattdessen ist eine bessere Eingabe für die Support Vector Machine ein MACD oder ein einfacher Oszillator, da der Wert des MACD unabhängig vom Durchschnittspreisniveau ist und nur relative Bewegungen signalisiert. Ich empfehle Ihnen, damit zu experimentieren, um zu sehen, wie Sie das beste Produkt bekommen.

Ein weiterer Faktor den es bei der Auswahl der Eingabe zu beachten gilt, ist die Sicherstellung, dass die Support Vector Machine passende Schnappschüsse eines Indikators hat, um neue Handel zu signalisieren. Sie können in ihrer eigenen Handelserfahrung finden, dass ein MACD nur nützlich ist, wenn Sie die letzten fünf Balken betrachten können, da dies einen Trend anzeigt. Ein einzelner Balken des MACD kann in Isolation unbrauchbar sein, außer man kann sagen, ob er nach oben oder unten geht. Daher kann es notwendig sein, die letzten paar Balken des MACD Indikators der Support Vector Machine zu übergeben. Es gibt mehrere Möglichkeiten, dies zu tun:

  1. Sie können einen neuen, benutzerdefinierten Indikator erstellen, der die letzten fünf Balken des MACD-Indikators verwendet, um einen Trend als einen Einzelwert zu kalkulieren. Dieser benutzerdefinierte Indikator kann dann der Support Vector Machine als Einzeleingabe übergeben werden oder

  2. Sie können die vorigen fünf Balken des MACD-Indikators in der Support Vector Machine als fünf separate Eingaben verwenden. Man macht das, indem man fünf verschiedene Beispiele des MACD-Indikators initialisiert. Jeder dieser Indikatoren kann mit einem anderen Offset des aktuellen Balkens initialisiert werden. Dann können die fünf Identifikatoren der separaten Indikatoren der Support Vector Machine übergeben werden. Hier sollte man beachten, dass die zweite Option längere Ausführungszeiten des Expert Advisor auslöst. Je mehr Eingaben man hat, desto länger wird ein erfolgreiches Training dauern.


Die Implementierung von Support Vector Machines und Expert Advisors

Als Beispiel, wie man Support Vector Machines beim Handeln verwenden könnte, habe ich einen Expert Advisors vorbereitet (eine Kopie kann unter folgendem Link heruntergeladen werden https://www.mql5.com/de/code/1229). Hoffentlich wird der Expert Advisor Ihnen erlauben, ein bisschen mit Support Vector Machines zu experimentieren. Ich empfehle Ihnen, den Expert Advisor auf Ihre Bedürfnisse einzustellen. Der EA funktioniert folgendermaßen:

  1. Zwei neue Support Vector Machines werden mit der Bibliothek svMachineTool erstellt. Einer signalisiert neue "Käufe" und der andere signalisiert neue "Verkäufe".

  2. Sieben Standardindikatoren werden initialisiert und jeder ihrer Identifikatoren in einem ganzzahligen Array gespeichert (beachten Sie: jede Kombination von Indikatoren kann als Eingabe verwendet werden, sie müssen nur in die SVM als einzelne, ganzzahlige Array übergeben werden).

  3. Der Array von Indikator-Identifikatoren wird neuen Support Vector Machines übergeben.

  4. Mit der Verwendung von Indikator-Identifikatoren und anderen Parametern werden vergangene Preisdaten verwendet, um genaue Eingaben und Ausgaben für das Training von Support Vector Machines zu generieren.

  5. Wenn alle Eingaben und Ausgaben generiert wurden, werden beide Support Vector Machines trainiert.

  6. Die trainierten Support Vector Machines werden im EA verwendet, um neue "Käufe" und "Verkäufe" zu signalisieren. Wenn ein neuer "Kauf" oder "Verkauf" signalisiert wird, beginnt der Handel mit manuellen "Stop Loss"- und "Take Profit"-Befehlen.

Die Initialisierung und das Training der Support Vector Machine werden in der Funktion onInit() ausgeführt. Dieses Segment des svTrader-EA ist unten mit Kommentaren zu finden.

#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#property indicator_buffers 7

//+---------Support Vector Machine Learning Tool Functions-----------+
//| The following #import statement imports all of the support vector
//| machine learning tool functions into the EA for use. Please note, if
//| you do not import the functions here, the compiler will not let you
//| use any of the functions
//+------------------------------------------------------------------+
#import "svMachineTool.ex5"
enum ENUM_TRADE {BUY,SELL};
enum ENUM_OPTION {OP_MEMORY,OP_MAXCYCLES,OP_TOLERANCE};
int  initSVMachine(void);
void setIndicatorHandles(int handle,int &indicatorHandles[],int offset,int N);
void setParameter(int handle,ENUM_OPTION option,double value);
bool genOutputs(int handle,ENUM_TRADE trade,int StopLoss,int TakeProfit,double duration);
bool genInputs(int handle);
bool setInputs(int handle,double &Inputs[],int nInputs);
bool setOutputs(int handle,bool &Outputs[]);
bool training(int handle);
bool classify(int handle);
bool classify(int handle,int offset);
bool classify(int handle,double &iput[]);
void  deinitSVMachine(void);
#import

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\HistoryOrderInfo.mqh>

//+-----------------------Input Variables----------------------------+
input int            takeProfit=100;      // TakeProfit level measured in pips
input int            stopLoss=150;        // StopLoss level measured in pips
input double         hours=6;             // The maximum hypothetical trade duration for calculating training outputs.
input double         risk_exp=5;          // Maximum simultaneous order exposure to the market
input double         Tolerance_Value=0.1; // Error Tolerance value for training the SVM (default is 10%)
input int            N_DataPoints=100;    // The number of training points to generate and use.

//+---------------------Indicator Variables--------------------------+
//| Only the default indicator variables have been used here. I
//| recommend you play with these values to see if you get any 
//| better performance with your EA.                    
//+------------------------------------------------------------------+
int bears_period=13;
int bulls_period=13;
int ATR_period=13;
int mom_period=13;
int MACD_fast_period=12;
int MACD_slow_period=26;
int MACD_signal_period=9;
int Stoch_Kperiod=5;
int Stoch_Dperiod=3;
int Stoch_slowing=3;
int Force_period=13;

//+------------------Expert Advisor Variables------------------------+
int         tickets[];
bool        Opn_B,Opn_S;
datetime    New_Time;
int         handleB,handleS;
double      Vol=1;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   New_Time=0;
   int handles[];ArrayResize(handles,7);
//+------------------------------------------------------------------+
//| The following statements are used to initialize the indicators to be used for the support 
//| vector machine. The handles returned are stored to an int[] array. I have used standard 
//| indicators in this case however, you can also you custom indicators if desired
//+------------------------------------------------------------------+
   handles[0]=iBearsPower(Symbol(),0,bears_period);
   handles[1]=iBullsPower(Symbol(),0,bulls_period);
   handles[2]=iATR(Symbol(),0,ATR_period);
   handles[3]=iMomentum(Symbol(),0,mom_period,PRICE_TYPICAL);
   handles[4]=iMACD(Symbol(),0,MACD_fast_period,MACD_slow_period,MACD_signal_period,PRICE_TYPICAL);
   handles[5]=iStochastic(Symbol(),0,Stoch_Kperiod,Stoch_Dperiod,Stoch_slowing,MODE_SMA,STO_LOWHIGH);
   handles[6]=iForce(Symbol(),0,Force_period,MODE_SMA,VOLUME_TICK);

//----------Initialize, Setup and Training of the Buy-Signal support vector machine----------
   handleB=initSVMachine();                             // Initializes a new SVM and stores the handle to 'handleB'
   setIndicatorHandles(handleB,handles,0,N_DataPoints); // Passes the initialized indicators to the SVM with the desired offset 
                                                        // and number of data points
   setParameter(handleB,OP_TOLERANCE,Tolerance_Value);  // Sets the maximum error tolerance for SVM training
   genInputs(handleB);                                  // Generates inputs using the initialized indicators
   genOutputs(handleB,BUY,stopLoss,takeProfit,hours);   // Generates the outputs based on the desired parameters for taking hypothetical trades

//----------Initialize, Setup and Training of the Sell-Signal support vector machine----------
   handleS=initSVMachine();                             // Initializes a new SVM and stores the handle to 'handleS'
   setIndicatorHandles(handleS,handles,0,N_DataPoints); // Passes the initialized indicators to the SVM with the desired offset 
                                                        // and number of data points
   setParameter(handleS,OP_TOLERANCE,Tolerance_Value);  // Sets the maximum error tolerance for SVM training
   genInputs(handleS);                                  // Generates inputs using the initialized indicators
   genOutputs(handleS,SELL,stopLoss,takeProfit,hours);  // Generates the outputs based on the desired parameters for taking hypothetical trades
//----------
   training(handleB);   // Executes training on the Buy-Signal support vector machine
   training(handleS);   // Executes training on the Sell-Signal support vector machine   
   return(0);
  }


Fortgeschrittenes Handeln mit der Support Vector Machine

Für fortgeschrittene Benutzer wurden zusätzliche Fähigkeiten in das "Support Vector Machine Learning Tool" gebaut. Mit dem Werkzeug können Benutzer ihre eigenen benutzerdefinierten Eingabe- und Ausgabedaten übergeben (wie im Schnick-Beispiel). Damit kann man seine eigenen Kriterien für "Support Vector Machine"-Eingaben und -Ausgaben entwerfen, und manuell Daten eingeben um es zu üben. Das ermöglicht die Verwendung von Support Vector Machines in jedem Aspekt des Handelns.

Es ist nicht nur möglich, Support Vector Machines zu verwenden, um neue Handel zu signalisieren, mit ihnen kann man auch einen Handelsabschluss, Geldmanagement oder neue, fortgeschrittene Indikatoren und vieles mehr signalisieren. Um aber Fehler zu vermeiden, ist ein Verständnis der Struktur dieser Eingaben und Ausgaben wichtig.

Eingaben: Eingaben werden als ein eindimensionaler Array von Doppelwerten in SVM gegeben. Bitte beachten Sie, dass jegliche Eingabe, die Sie erstellen, in einen Doppelwert übergeben werden muss. Boolesche, ganzzahlige, etc., müssen alle in einen Doppelwert konvertiert werden, bevor sie in die Support Vector Machine übergeben werden. Die Eingaben müssen folgende Form haben. Nehmen wir zum Beispiel an, wir übergeben Eingaben mit 3 Eingaben x 5 Trainingspunkten. Um das zu erreichen, muss unser Doppelarray 15 Einheiten lang sein, im Format:

| A1 | B1 | C1 | A2 | B2 | C2 | A3 | B3 | C3 | A4 | B4 | C4 | A5 | B5 | C5 |

Es ist auch notwendig, einen Wert für die Anzahl an Eingaben zu übergeben. In diesem Fall, N_Inputs=3.

Ausgaben: Ausgaben werden als ein Array von booleschen Werten übergeben. Ihre booleschen Werte sind die gewünschte Ausgabe der SVM, die jedem dieser Eingabesätzen entspricht. Nach dem folgenden Beispiel haben wir 5 Trainingspunkte. In diesem Szenario übergeben wir einen booleschen Array an Ausgabewerten der 5 Einheiten lang ist.

Allgemeine Bemerkungen:

  • Bei der Generierung Ihrer eigenen Eingaben und Ausgaben sollten Sie sicherstellen, dass die Länge Ihrer Arrays zu den eingegebenen Werten passt. Wenn sie nicht passen, wird eine Fehlermeldung generiert, die Sie über die Abweichung informiert. Wenn wir zum Beispiel N_Inputs=3 übergeben haben und die Eingabe ein Array mit der Länge 16 ist, wird ein Fehler angezeigt (da ein N_inputs-Wert 3 bedeutet, dass die Länge jedes Eingabe-Arrays ein Vielfaches von 3 sein muss). Stellen Sie außerdem sicher, dass die Anzahl an Eingabesätzen und die Anzahl an Ausgabesätzen, die übergeben werden, gleich sind. Wenn Sie also N_Inputs=3 haben, die Länge der Eingaben 15 ist und eine Länge von Ausgaben 6 ist, wird ein anderer Fehler angezeigt (da Sie 5 Eingabesätze und 5 Ausgabesätze haben).

  • Versuchen Sie, so viel Vielfalt wie möglich in Ihren Trainingsausgaben zu haben. Wenn Sie zum Beispiel 100 Trainingspunkte übergeben, also einen Ausgabe-Array mit einer Länge von 100, und alle diese Werte sind false, mit nur einem der true ist, dann ist der Unterschied zwischen dem true-Fall und dem false-Fall nicht genug. Das führt sehr schnell zum SVM-Training, aber die endgültige Lösung wird nicht gut sein. Ein vielfältigeres Trainingsset führt oft zu effektiveren SVM.

Übersetzt aus dem Englischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/en/articles/584

Beigefügte Dateien |
schnick.mq5 (10.8 KB)
schnick_demo.mq5 (11.39 KB)
Die Grundlagen von MQL5 Strings Die Grundlagen von MQL5 Strings

Dieser Artikel behandelt alle Funktionsweisen von Strings in MQL5. Er ist vor allem für neue MQL5-Programmierer interessant, und für erfahrene Entwickler ist es eine gute Möglichkeit, ihre Kenntnisse zusammenzufassen und zu systematisieren.

Wie teste ich einen Handelsroboter vor dem Kauf Wie teste ich einen Handelsroboter vor dem Kauf

Der Kauf eines Handelsroboters hat bestimmte Vorzüge gegenüber ähnlichen Möglichkeiten - ein automatisiertes System kann direkt im MetaTrader5-Terminal getestet werden. Vor dem Kauf kann und soll ein Expert Advisor sorgfältig in allen ungünstigen Modi im eingebauten Strategietester ausgeführt werden, um das System komplett zu verstehen.

Spontane Änderung der Expert-Advisor-Parameter vom Bedienfeld aus Spontane Änderung der Expert-Advisor-Parameter vom Bedienfeld aus

Dieser Artikel zeigt anhand eines Beispiels die Implementierung eines Expert Advisors, dessen Parameter vom Bedienfeld aus kontrolliert werden können. Bei einer spontanen Änderung der Parameter schreibt der Expert Advisor die Werte vom Infofeld in eine Datei, um sie später von dieser Datei zu lesen und sie im Feld darzustellen. Dieser Artikel ist interessant für alle, die manuell oder semi-automatisch handeln wollen.

Grafische Interfaces II: Das Menu-Item-Element (Kapitel 1) Grafische Interfaces II: Das Menu-Item-Element (Kapitel 1)

In dem zweiten Teil dieser Serie, werden wir im Detail auf die Entwicklung von Interface Elementen, wie einen Hauptmenü und Kontextmenüs eingehen. Wir werden auch das Zeichnen und das Entwickeln einer speziellen Klasse für diese Elemente berücksichtigen. Wir werden ausführlich den Fragen der Verwaltung von Events und benutzerdefinierten Events nachgehen.