English Русский 中文 Español 日本語 Português
preview
Datenkennzeichnung für Zeitreihenanalyse (Teil 1):Erstellen eines Datensatzes mit Trendmarkierungen durch den EA auf einem Chart

Datenkennzeichnung für Zeitreihenanalyse (Teil 1):Erstellen eines Datensatzes mit Trendmarkierungen durch den EA auf einem Chart

MetaTrader 5Experten | 12 Dezember 2023, 08:30
345 0
Yuqiang Pan
Yuqiang Pan

Zusammenfassung

Wenn wir Modelle der künstlichen Intelligenz entwerfen, müssen wir zunächst oft Daten aufbereiten. Eine gute Datenqualität ermöglicht es uns, mit der Hälfte des Aufwands für die Modellschulung und -validierung das doppelte Ergebnis zu erzielen. Aber unsere Devisen- oder Aktiendaten sind etwas Besonderes, da sie komplexe Markt- und Zeitinformationen enthalten, und die Kennzeichnung der Daten ist schwierig, aber wir können den Trend in den historischen Daten auf dem Chart leicht analysieren.

 

In diesem Abschnitt wird eine Methode zur Erstellung von Datensätzen mit Trendmarkierungen auf dem Chart durch den EA vorgestellt, mit der Sie Daten intuitiv nach Ihren eigenen Vorstellungen manipulieren können. Natürlich können Sie die gleiche Methode auch verwenden, um Ihre eigenen Datensätze zu erweitern und anzupassen!

Inhaltsverzeichnis

  1. Definieren des Formats der gekennzeichneten Daten
  2. Initialisieren der Charts und der Dateien
  3. Operationslogik entwerfen und kennzeichnen
  4. Organisieren der Daten und Speichern in einer Datei
  5. Anlage: Beispiel eines vollständigen EA-Codes


Definieren des Formats der gekennzeichneten Daten

Wenn wir Devisen- oder Aktiendaten vom Kunden erhalten (in diesem Artikel wird nicht auf externe Daten eingegangen, die aus Dateien gelesen oder von anderen Websites heruntergeladen werden), ist die allgemeine Situation wie folgt:

Zeit Eröffnungskurs Hoch Tief Schlusskurs Tick_Volumen
2021-12-10 01:15:00
1775.94
1775.96
1775.58
1775.58
173
2021-12-10 01:30:00
1775.58
1776.11
1775.48
1775.88
210
2021-12-10 01:45:00
1775.88
1776.22
1775.68
1776.22
212
2021-12-10 02:00:00
1776.22
1777.57
1775.98
1777.02
392
2021-12-10 02:15:00
1776.99
1777.72
1776.89
1777.72
264

Oben sehen Sie, wie die 5 Zeitreihendaten aussehen. Ihre Eröffnungs- und Schlusskurse sind von Anfang bis Ende miteinander verbunden, und die Kohärenz ist sehr stark. Nehmen wir an, dass es sich bei den ersten beiden um einen Aufwärtstrend und bei den anderen um einen Abwärtstrend handelt (die obigen 5 Daten werden als Beispiel genommen). Bei der allgemeinen Kennzeichnungsmethode werden die Daten in zwei Teile unterteilt:

Zeit

Eröffnungskurs Hoch   Tief   Schlusskurs Tick_Volumen
2021-12-10 01:15:00
1775.94
1775.96
1775.58
1775.58
173
2021-12-10 01:30:00
1775.58
1776.11
1775.48
1775.88
210

Zeit Eröffnungskurs Hoch   Tief Schlusskurs Tick_Volumen
2021-12-10 01:45:00
1775.88
1776.22
1775.68
1776.22
212
2021-12-10 02:00:00
1776.22
1777.57
1775.98
1777.02
392
2021-12-10 02:15:00
1776.99
1777.72
1776.89
1777.72
264

Dann sagen wir unserem Modell, welcher Teil ein Aufwärtstrend und welcher Teil ein Abwärtstrend ist, aber das ignoriert ihre allgemeinen Attribute und zerstört die Integrität der Daten, wie lösen wir also dieses Problem?

Eine praktikable Methode ist das Hinzufügen einer Trendgruppierung in unseren Zeitreihen wie folgt (nehmen Sie die obigen 5 Daten als Beispiel oder folgen Sie den obigen Annahmen):

Time Open High Low Close Tick_volume Trend_group
2021-12-10 01:15:00
1775.94
1775.96
1775.58
1775.58
173 0
2021-12-10 01:30:00
1775.58
1776.11
1775.48
1775.88
210 0
2021-12-10 01:45:00
1775.88
1776.22
1775.68
1776.22
212 1
2021-12-10 02:00:00
1776.22
1777.57
1775.98
1777.02
392 1
2021-12-10 02:15:00
1776.99
1777.72
1776.89
1777.72
264 1

Wenn wir jedoch eine Trendentwicklungsanalyse in das Modell einbauen wollen, z. B. inwieweit sich der aktuelle Trend entwickelt hat (die Wellentheorie besagt beispielsweise, dass ein allgemeiner Trend im Allgemeinen ein Trendstadium und ein Anpassungsstadium umfasst, das Trendstadium hat 5 Wellenstufen und das Anpassungsstadium hat 3 Anpassungswellen usw.), müssen wir die Daten weiter kennzeichnen. Wir können dies tun, indem wir eine weitere Indexspalte hinzufügen, die die Entwicklung des Trends in den Daten wie folgt darstellt (unter der Annahme, dass die ersten 2 der folgenden 10 Daten ein Aufwärtstrend und die letzten 5 ein Aufwärtstrend sind, der Rest in der Mitte ist ein Abwärtstrend):

Time Open High Low Close Tick_volume Trend_group Trend_index
2021-12-10 03:15:00 1776.38 1777.94 1775.47 1777.71 565 0 0
2021-12-10 03:30:00 1777.75 1778.93 1777.68 1778.61 406 0 1
2021-12-10 03:45:00 1778.58 1778.78 1777.65 1778.16 388 1 0
2021-12-10 04:00:00 1778.14 1779.42 1778.06 1779.14 393 1 1
2021-12-10 04:15:00 1779.16 1779.49 1778.42 1779.31 451 1 2
2021-12-10 04:30:00 1779.22 1779.42 1778.36 1778.37 306 0 0
2021-12-10 04:45:00 1778.42 1778.51 1777.60 1777.78 411 0 1
2021-12-10 05:00:00 1777.81 1778.68 1777.61 1778.57 372 0 2
2021-12-10 05:15:00 1778.54 1779.29 1778.42 1779.02 413 0 3
2021-12-10 05:30:00 1778.97 1779.49 1778.48 1778.50 278 0 4

Anmerkung:

1. Trend_group, ist bei einem Aufwärtstrend 0.

2. Trend_group, ist bei einem Abwärtstrend 1.

 Als Nächstes beginnen wir mit der Manipulation des Charts auf der Client-Seite und kennzeichnen die Daten nach dem von uns gewünschten Muster.


Initialisieren der Charts und der Dateien

    Chart-Initialisierung

          Da wir uns das Chart ansehen müssen, um die Daten zu markieren, kann das Chart nicht einfach gescrollt werden, sondern muss entsprechend unserer manuellen Bedienung gescrollt werden. Daher müssen wir CHART_AUTOSCROLL und CHART_SHIFT deaktivieren:

           ChartSetInteger (0, CHART_AUTOSCROLL, false);
          
            ChartSetInteger (0, CHART_SHIFT, true);
          
            ChartSetInteger (0, CHART_MOUSE_SCROLL ,1);
          
          Anmerkung: Der grüne Teil des Codes soll es uns ermöglichen, das Chart mit dem Mausrad zu steuern
            Initialisierung der Datei

                Bei der Initialisierung der Datei sollte zunächst geprüft werden, ob eine Labeldatei vorhanden ist, und wenn eine historische Datei vorhanden ist, sollte der Dateiname in der Variablen „reName“ gespeichert werden:

                 do
                     {
                       //---Find if there are files that match the chart
                       if (StringFind(name, Symbol())!=-1 && StringFind(name,".csv")!=-1)
                         reName=name;
                     }
                
                   while (FileFindNext(hd,name));
                
                Anmerkung: Hier ist zu beachten, dass wir eine „do - while“-Schleife verwenden, die sich von einer „while“-Schleife dadurch unterscheidet, dass sie zuerst den Operator ausführt und dann den Ausdruck auswertet Aber die Initialisierung von „name“ ist ein Problem, wir können Folgendes tun
                int hd= FileFindFirst("*",name,0);


                  Wenn es eine markierte Originaldatei gibt, öffnen Sie die Datei und holen Sie den letzten Zeitpunkt der Markierung mit der Funktion read_csv() ab:

                    read_csv(file_handle,a);
                    Blättern Sie dann im Chart bis zur letzten markierten Zeit:
                    shift = - iBarShift(Symbol(),PERIOD_CURRENT,(datetime)a[i-8]);
                    ChartNavigate(0, CHART_END ,shift);
                    


                    Erstellen Sie eine Datei, wenn keine Verlaufsdatei vorhanden ist:

                    file_handle = FileOpen(StringFormat("%s%d-%d.csv",Symbol(),Period(),start_t), FILE_WRITE | FILE_CSV | FILE_READ);
                    Anschließend wird das Chart an die durch die globale Variable „start_t“ festgelegte Position verschoben.
                     shift = -iBarShift(Symbol(),PERIOD_CURRENT,(datetime)start_t);
                      ChartNavigate(0,CHART_END,shift);
                    
                    Fügen Sie eine vertikale rote Linie hinzu, um die Anfangsspalte zu markieren:
                     ObjectCreate (0,"Start",OBJ_VLINE,0,(datetime)start_t,0)
                    Die Logik dieses Teils ist folgendermaßen aufgebaut:
                     if (FileIsExist(reName))
                         {
                          file_handle = FileOpen(reName, FILE_WRITE | FILE_CSV | FILE_READ );
                           string a[];
                           int i= 0 ;
                          read_csv(file_handle,a);
                          i = ArraySize (a);
                          shift = -iBarShift(Symbol(), PERIOD_CURRENT,(datetime)a[i-8]);
                           ChartNavigate(0,CHART_END,shift);
                         }
                       else
                         {
                          file_handle = FileOpen (StringFormat ("%s%d-%d.csv", Symbol(), Period(),start_t), FILE_WRITE | FILE_CSV | FILE_READ );
                           Print ("There is no history file,create file:" , StringFormat ( "%s%d-%d",Symbol(), Period(),start_t));
                           shift = - iBarShift (Symbol(), PERIOD_CURRENT ,(datetime)start_t);
                           ChartNavigate (0, CHART_END ,shift);
                           ObjectCreate (0,"Start", OBJ_VLINE,0,(datetime)start_t,0);
                         }
                    
                    Achtung! Da wir das Chart nach links verschieben wollen, müssen wir ein „-“ vor der Funktion „iBarShift()“ hinzufügen
                    shift = -iBarShift(Symbol(), PERIOD_CURRENT ,(datetime)start_t);
                    Natürlich kann es auch in der ChartNavigate() Funktion implementiert werden, wie z.B:
                    ChartNavigate(0,CHART_END,-shift);
                    Der Code in diesem Artikel ist noch nach der ersten Methode implementiert.
                      Diese Initialisierungsaktionen werden in unserer OnInit() implementiert, einschließlich der Definition der benötigten Variablen. Das Wichtigste ist, zu klären, wohin sich das Chart verschieben soll, und mit der Beschriftung zu beginnen. Dies wird hauptsächlich durch die Variablen „shift“ und „start_t“ gesteuert. Wir werden uns im endgültigen Code wiederfinden:
                        int OnInit()
                          {
                        //---initial
                           string name;
                           string reName="1";
                           int hd=FileFindFirst("*",name,0);
                           int shift;
                        
                           ChartSetInteger(0,CHART_AUTOSCROLL,false);
                           ChartSetInteger(0,CHART_SHIFT,false);
                           ChartSetInteger(0,CHART_MOUSE_SCROLL,1);
                        
                        
                           do
                             {
                              //---check File
                              if(StringFind(name,Symbol())!=-1 && StringFind(name,".csv")!=-1)
                                 reName=name;
                             }
                           while(FileFindNext(hd,name));
                        
                           if(FileIsExist(reName))
                             {
                              file_handle = FileOpen(reName,FILE_WRITE|FILE_CSV|FILE_READ);
                              string a[];
                              int i=0;
                              read_csv(file_handle,a);
                              i = ArraySize(a);
                              shift = -iBarShift(Symbol(),PERIOD_CURRENT,(datetime)a[i-8]);
                              ChartNavigate(0,CHART_END,shift);
                             }
                           else
                             {
                              file_handle = FileOpen(StringFormat("%s%d-%d.csv",Symbol(),Period(),start_t),FILE_WRITE|FILE_CSV|FILE_READ);
                              Print(FileTell(file_handle));
                              Print("No history file,create file:",StringFormat("%s%d-%d",Symbol(),Period(),start_t));
                              shift = -iBarShift(Symbol(),PERIOD_CURRENT,(datetime)start_t);
                              ChartNavigate(0,CHART_END,shift);
                              ObjectCreate(0,"Start",OBJ_VLINE,0,(datetime)start_t,0);
                             }
                           return(INIT_SUCCEEDED);
                          }
                        

                          Anmerkung:

                          1. start_t-Variable - Angabe des zu startenden Zeitrahmens;

                          2. die Variable shift - es ist die Angabe der Anzahl der zu verschiebenden Spalten, und das Code-Beispiel zeigt die Anzahl der zu verschiebenden Spalten durch Konvertierung der angegebenen Zeit;

                          3. Die Funktion read_csv() wird später definiert.

                            Definition der Funktion read_csv():
                               void read_csv(int hd,
                                             string &arry[])
                                {
                                 int i= 0;
                                 while(!FileIsEnding(hd))
                                   {
                                    ArrayResize(arry,i+1);
                                    arry[i]= FileReadString(hd);
                                    i++;
                                   }
                                }
                              

                              Anmerkung: Wir verwenden die „while“-Schleife, um die Endzeile der historischen Datei mit den Anmerkungen zu finden, die letzte Datenzeile in der Datei zu erhalten und die Endzeit unserer letzten Anmerkung zu ermitteln. Mit dieser Anmerkung wird das Chart zu diesem SäulenChart verschoben, sodass wir von hier aus mit den Anmerkungen fortfahren können.


                              Operationslogik entwerfen und kennzeichnen

                                Manipulation der Charts: Dieser Abschnitt kann leicht über die Hilfethemen des Clients abgefragt werden.
                                  • Home — geht zum letzten Balken des Charts;
                                  • End — geht zum ersten Balken des Charts;
                                  • Seite nach oben — verschiebt das Chart um ein Fenster nach hinten;
                                  • Seite nach unten — verschiebt das Chart um ein Fenster nach vorne;
                                  • Ctrl+I — öffnet ein Fenster mit einer Liste von Indikatoren;
                                  • Ctrl+B — öffnet ein Fenster mit einer Liste von Objekten;
                                  • Alt+1 — Das Chart wird als eine Reihe von Balken angezeigt;
                                  • Alt+2 — das Chart wird als eine Folge von japanischen Leuchtern angezeigt;
                                  • Alt+3 — das Chart wird als Linie dargestellt, die die Schlusskurse verbindet;
                                  • Strg+G — zeigt/versteckt das Gitter im Chartfenster;
                                  • "+" — vergrößert das Chart;
                                  • "-" — Zoom der Karte;
                                  • F12 — Chart Schritt für Schritt scrollen;
                                  • F8 — Chart-Eigenschaften öffnen;
                                  • Backspace — entfernt das zuletzt hinzugefügte Objekt aus dem Chart;
                                  • Entf — alle ausgewählten Objekte löschen;
                                  • Ctrl+Z — Löscht das letzte Objekt zurück.
                                    Steuerlogik:
                                      1. Drücken Sie eine Taste, um dem EA mitzuteilen, welche Art von Trend die als Nächstes markierten Daten sein werden
                                        Definition der Tasten „b“ und „s“. Definiert durch den Code der virtuellen Taste:
                                           #define KEY_B     66
                                           #define KEY_S     83
                                          
                                            Drücken Sie „b“ und dann „s“ für einen Aufwärtstrend, drücken Sie „s“ und dann „b“ für einen Abwärtstrend. Nehmen wir den Aufwärtstrend als Beispiel:
                                              1) Drücken Sie zu diesem Zeitpunkt „b“, um einen Aufwärtstrend darzustellen. Wir setzen die Variable „typ“ auf 0, die Variable „tp“ auf „start“, die Pfeilfarbe auf „clrBlue“ und die Labelanzahl „Num“ auf 1. Es ist zu beachten, dass wir nur die Variable am Anfang des Datensegments inkrementieren müssen und festlegen, dass ein erneutes Drücken der Taste den „end“-Teil des markierten Datensegments ausführt, indem wir zuerst invertieren;
                                              b_press
                                              2) Drücken Sie „s“, um das Ende des Aufwärtstrends zu markieren, die Variable „typ“ ist immer noch 0, die Variable „tp“ ist auf „end“ gesetzt, die Pfeilfarbe ist immer noch „clrBlue“, und die Anzahl der Label „Num“ bleibt unverändert. Es ist zu beachten, dass wir nur die Variable am Anfang des Datensegments inkrementieren müssen, und die Umkehrung von first wird verwendet, um festzulegen, dass das erneute Drücken der Taste den „Start“-Teil des markierten Datensegments ausführt. s_press
                                              3) Rufen Sie nach der Ausführung der Switch-Anweisung die Funktion ChartRedraw() auf, um das Chart neu zu zeichnen.
                                              if(id==CHARTEVENT_KEYDOWN)
                                                   {
                                                    switch(lparam)
                                                      {
                                                       case KEY_B:
                                                          if(first)
                                                            {
                                                             col=clrBlue ;
                                                             typ =0;
                                                             Num+=1;
                                                             tp = "start";
                                                            }
                                                          else
                                                            {
                                                             col=clrRed ;
                                                             typ = 1;
                                                             tp = "end";
                                                            }
                                                          ob =OBJ_ARROW_BUY;
                                                          first = !first;
                                                          Name = StringFormat("%d-%d-%s",typ,Num,tp);
                                                          break;
                                                       case KEY_S:
                                                          if(first)
                                                            {
                                                             col=clrRed ;
                                                             typ =1;
                                                             Num+=1;
                                                             tp = "start";
                                                            }
                                                          else
                                                            {
                                                             col=clrBlue ;
                                                             typ = 0;
                                                             tp = "end";
                                                            }
                                                          ob =OBJ_ARROW_SELL;
                                                          first = !first;
                                                          Name = StringFormat("%d-%d-%s",typ,Num,tp);
                                                          break;
                                              
                                                       default:
                                                          Print("You pressed:"+lparam+" key, do nothing!");
                                                      }
                                                    ChartRedraw(0);
                                                   }
                                              

                                              Anmerkung:

                                              1. die Variable „typ“ - 0 bedeutet einen Aufwärtstrend, 1 bedeutet einen Abwärtstrend;

                                              2. Die Variable „Num“ - die Anzahl der Markierungen - wird intuitiv auf dem Chart angezeigt;

                                              3. die Variable „first“ steuert, dass unsere Beschriftungen immer paarweise sind, um sicherzustellen, dass jede Gruppe „b“ und „s“ oder „s“ und „b“ ohne Verwechslung ist;

                                              4. die Variable „tp“, mit der der Anfang oder das Ende des Datensegments bestimmt wird.

                                              2. Klicken Sie mit der linken Maustaste auf das Chart, um die Position der Markierung zu bestimmen

                                              if(id==CHARTEVENT_CLICK)
                                                   {
                                                    //--- definition
                                                    int x=(int)lparam;
                                                    int y=(int)dparam;
                                                    datetime dt    =0;
                                                    double   price =0;
                                                    int      window=0;
                                                    if(ChartXYToTimePrice(0,x,y,window,dt,price))
                                                      {
                                                       ObjectCreate(0,Name,ob,window,dt,price);
                                                       ObjectSetInteger(0,Name,OBJPROP_COLOR,col);
                                                       //Print("time:",dt,"shift:",iBarShift(Symbol(),PERIOD_CURRENT,dt));
                                                       if(tp=="start")
                                                          Start=dt;
                                                       else
                                                         {
                                                          if(file_handle)
                                                             file_write(Start,dt);
                                                         }
                                                       ChartRedraw(0);
                                                      }
                                                    else
                                                       Print("ChartXYToTimePrice return error code: ",GetLastError());
                                                   }
                                              //--- object delete
                                                 if(id==CHARTEVENT_OBJECT_DELETE)
                                                   {
                                                    Print("The object with name ",sparam," has been deleted");
                                                   }
                                              //--- object create
                                                 if(id==CHARTEVENT_OBJECT_CREATE)
                                                   {
                                                    Print("The object with name ",sparam," has been created!");
                                                   }
                                              

                                              Anmerkung:

                                              1. Die Funktion ChartXYToTimePrice() wird hauptsächlich verwendet, um die Eigenschaften des Säulen-Charts unserer Mausklickposition zu erhalten, einschließlich der aktuellen Zeit und des Preises. Wir verwenden die globale Variable "dt", um die aktuelle Zeit zu erhalten;

                                              2. Wenn wir mit der Maus klicken, müssen wir auch beurteilen, ob die aktuelle Aktion der Anfang oder das Ende des Datensegments ist. Wir verwenden die globale Variable „tp“ zur Beurteilung. 

                                              3. Spezifischer Betriebsprozess


                                                Wenn Sie einen Aufwärtstrend markieren möchten, drücken Sie zunächst die Taste „b“, klicken Sie mit der linken Maustaste auf die Spalte, die im Chart markiert werden soll, drücken Sie dann die Taste „s“ und klicken Sie anschließend mit der linken Maustaste auf das Ende der Spalte auf dem Symbol, um die Beschriftung abzuschließen. Im Chart erscheinen Paare von blauen Pfeilen, wie in der Abbildung unten dargestellt:

                                                  nach oben


                                                      Wenn Sie einen Abwärtstrend markieren möchten, drücken Sie zunächst die Taste „s“, klicken Sie mit der linken Maustaste auf die Spalte, die im Chart markiert werden soll, drücken Sie dann die Taste „b“ und klicken Sie anschließend mit der linken Maustaste auf das Ende der Spalte im Chart. Nachdem die Markierung abgeschlossen ist, werden zwei rote Pfeile angezeigt, wie in der folgenden Abbildung dargestellt:

                                                        nach unten


                                                          In der Ausgabespalte für die Kennzeichnungen wird der Vorgang des Kennzeichens jederzeit angezeigt, was sehr intuitiv ist, um den Vorgang des Kennzeichens zu überwachen, wie in der Abbildung dargestellt:

                                                            AusgabeHinweis: Dieser Teil könnte eigentlich besser optimiert werden, z.B. durch Hinzufügen der Funktion, die letzte Aktion rückgängig zu machen, dann kann man die Position der Markierung jederzeit anpassen, und man kann auch falsche Operationen vermeiden, aber ich bin ein fauler Typ, also... (^o^)


                                                            Organisieren der Daten und Speichern in einer Datei

                                                              Definieren Sie die Variablen „Start“ und „MqlRates rates[]“, um die Startzeit und die Datenreihen des Trends zu speichern:
                                                                datetime Start;
                                                                MqlRates rates[];
                                                                ArraySetAsSeries(rates, false);
                                                                
                                                                  Anmerkung: 1. Hier brauchen wir die Endzeit nicht zu definieren, da die letzte Zeit, die wir aus der Tabelle erhalten, die Endzeit ist; 2. Das Flag in der Funktion „ArraySetAsSeries(rates,false)“ wird als „false“ angegeben, um sicherzustellen, dass die Zeiträume sequentiell verbunden sind.
                                                                    Wenn tp = „end“ ist, schreiben wir das Datensegment in die Datei (der grüne Teil des Codes):
                                                                         if(id==CHARTEVENT_CLICK)
                                                                           {
                                                                            //--- definition
                                                                            int x=(int)lparam;
                                                                            int y=(int)dparam;
                                                                            datetime dt    =0;
                                                                            double   price =0;
                                                                            int      window=0;
                                                                            if(ChartXYToTimePrice(0,x,y,window,dt,price))
                                                                              {
                                                                               ObjectCreate(0,Name,ob,window,dt,price);
                                                                               ObjectSetInteger(0,Name,OBJPROP_COLOR,col);
                                                                               //Print("time:",dt,"shift:",iBarShift(Symbol(),PERIOD_CURRENT,dt));
                                                                               if(tp=="start")
                                                                                  Start=dt;
                                                                               else
                                                                                 {
                                                                                  if(file_handle)
                                                                                     file_write(Start,dt);
                                                                                 }
                                                                               ChartRedraw(0);
                                                                              }
                                                                            else
                                                                               Print("ChartXYToTimePrice return error code: ",GetLastError());
                                                                           }
                                                                      

                                                                        Um die Segmentdaten über die Funktion „CopyRates()“ zu erhalten und die Spalten „trend_group“ und „trend_index“ hinzuzufügen, indem jedes in „rates[]“ enthaltene Datenelement durchlaufen wird, müssen wir diese Funktionen in der Funktion „file_write()“ implementieren:
                                                                          void file_write(datetime start,
                                                                                          datetime end)
                                                                            {
                                                                             MqlRates rates[];
                                                                             ArraySetAsSeries(rates,false);
                                                                             int n_cp=CopyRates(Symbol(),PERIOD_CURRENT,start,end,rates);
                                                                             if(n_cp>0)
                                                                               {
                                                                                if(FileTell(file_handle)==2)
                                                                                  {
                                                                                   FileWrite(file_handle,"time","open","high","low","close","tick_volume","trend_group","trend_index");
                                                                                   for(int i=0; i<n_cp; i++)
                                                                                     {
                                                                                      FileWrite(file_handle,
                                                                                                rates[i].time,
                                                                                                rates[i].open,
                                                                                                rates[i].high,
                                                                                                rates[i].low,
                                                                                                rates[i].close,
                                                                                                rates[i].tick_volume,
                                                                                                typ,
                                                                                                i);
                                                                                     }
                                                                                  }
                                                                                else
                                                                                  {
                                                                                   for(int i=0; i<n_cp; i++)
                                                                                     {
                                                                                      FileWrite(file_handle,
                                                                                                rates[i].time,
                                                                                                rates[i].open,
                                                                                                rates[i].high,
                                                                                                rates[i].low,
                                                                                                rates[i].close,
                                                                                                rates[i].tick_volume,
                                                                                                typ,
                                                                                                i);
                                                                                     }
                                                                                  }
                                                                               }
                                                                             else
                                                                                Print("No data copied!");
                                                                             FileFlush(file_handle);
                                                                             typ=3;
                                                                            }
                                                                          



                                                                          Anmerkung:

                                                                          1. Wir müssen unseren Index-Header schreiben, wenn wir die Datei zum ersten Mal schreiben;

                                                                          2. Trend_group ist eigentlich die globale Variable „typ“;

                                                                          3. Wir haben die Funktion FileClose() in dieser Funktion nicht aufgerufen, da unsere Kennzeichnungen noch nicht abgeschlossen ist. Wir werden diese Funktion in der Funktion OnDeinit() aufrufen, um das Endergebnis in die Datei zu schreiben.

                                                                          4. Besondere Aufmerksamkeit sollte dem gelben Teil des Codes gewidmet werden, der hier verwendet wird

                                                                          if(FileTell(file_handle)==2)
                                                                          Um festzustellen, ob Daten in der Datei vorhanden sind (natürlich können auch andere Methoden verwendet werden, z. B. das Hinzufügen einer Variablen, um ihr während der Initialisierung einen Wert zuzuweisen), müssen wir, wenn keine Daten in der Datei vorhanden sind, eine Kopfzeile wie diese hinzufügen:
                                                                          FileWrite(file_handle,"time","open","high","low","close","tick_volume","trend_group","trend_index");
                                                                          Wenn die Datei Daten enthält, darf keine Kopfzeile hinzugefügt werden, da sonst die Daten abgeschnitten werden. Das ist sehr wichtig.
                                                                            Beispiel einer geschriebenen Datei:
                                                                              daten_0


                                                                                Überprüfen wir die Kohärenz zwischen verschiedenen Datensegmenten und stellen wir fest, dass die Daten perfekt sind:

                                                                                  daten_1


                                                                                  Anlage: Beispiel eines vollständigen EA-Codes

                                                                                  1. Die Definition von globalen Variablen und Konstanten.  Der Parameter „start_t“ kann durch die Daten pro Sekunde ab 01.01.1970 definiert werden. Natürlich kann er auch durch den Standard „datetime“" definiert werden, oder er kann durch die Eingabevariable „input int start_t=1403037112;“ definiert werden, sodass er zu jeder Zeit geändert werden kann, wenn der EA später läuft:
                                                                                  #define KEY_B     66
                                                                                  #define KEY_S     83
                                                                                  
                                                                                  
                                                                                  int Num= 0;
                                                                                  int typ= 3;
                                                                                  string Name;
                                                                                  string tp;
                                                                                  color col;
                                                                                  bool first= true;
                                                                                  ENUM_OBJECT ob;
                                                                                  int file_handle=0;
                                                                                  int start_t=1403037112;
                                                                                  datetime Start;
                                                                                  

                                                                                  Anmerkung: Natürlich können Sie die Schaltfläche auch als Eingabevariable nach Ihren persönlichen Vorlieben definieren.

                                                                                  input int KEY_B=66;
                                                                                  input int KEY_S=83;
                                                                                  

                                                                                  Das hat den Vorteil, dass Sie die Schaltflächen bei jeder Ausführung des EA nach Belieben ändern können, bis Sie zufrieden sind, und dass unser Code vorübergehend nicht geändert wird, wenn Sie der Meinung sind, dass die Schaltflächen nicht einfach zu bedienen sind.


                                                                                  2. OnInit()-Funktion, mit der wir unsere Vorbereitungen initialisieren:

                                                                                  int OnInit()
                                                                                    {
                                                                                  //---initial
                                                                                     string name;
                                                                                     string reName="1";
                                                                                     int hd=FileFindFirst("*",name,0);
                                                                                     int shift;
                                                                                  
                                                                                     ChartSetInteger(0,CHART_AUTOSCROLL,false);
                                                                                     ChartSetInteger(0,CHART_SHIFT,false);
                                                                                     ChartSetInteger(0,CHART_MOUSE_SCROLL,1);
                                                                                  
                                                                                  
                                                                                     do
                                                                                       {
                                                                                        //---check File
                                                                                        if(StringFind(name,Symbol())!=-1 && StringFind(name,".csv")!=-1)
                                                                                           reName=name;
                                                                                       }
                                                                                     while(FileFindNext(hd,name));
                                                                                  
                                                                                     if(FileIsExist(reName))
                                                                                       {
                                                                                        file_handle = FileOpen(reName,FILE_WRITE|FILE_CSV|FILE_READ);
                                                                                        string a[];
                                                                                        int i=0;
                                                                                        read_csv(file_handle,a);
                                                                                        i = ArraySize(a);
                                                                                        shift = -iBarShift(Symbol(),PERIOD_CURRENT,(datetime)a[i-8]);
                                                                                        ChartNavigate(0,CHART_END,shift);
                                                                                       }
                                                                                     else
                                                                                       {
                                                                                        file_handle = FileOpen(StringFormat("%s%d-%d.csv",Symbol(),Period(),start_t),FILE_WRITE|FILE_CSV|FILE_READ);
                                                                                        Print(FileTell(file_handle));
                                                                                        Print("No history file,create file:",StringFormat("%s%d-%d",Symbol(),Period(),start_t));
                                                                                        shift = -iBarShift(Symbol(),PERIOD_CURRENT,(datetime)start_t);
                                                                                        ChartNavigate(0,CHART_END,shift);
                                                                                        ObjectCreate(0,"Start",OBJ_VLINE,0,(datetime)start_t,0);
                                                                                       }
                                                                                  //---
                                                                                     Print("EA:",MQL5InfoString(MQL5_PROGRAM_NAME),"Working!");
                                                                                  //---
                                                                                     ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_CREATE,true);
                                                                                  //---
                                                                                     ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_DELETE,true);
                                                                                  //---
                                                                                     ChartRedraw(0);
                                                                                  //---
                                                                                     return(INIT_SUCCEEDED);
                                                                                    }
                                                                                  


                                                                                  3. Da alle unsere Tastatur- und Mausoperationen auf dem Chart beendet sind, setzen wir die wichtigsten logischen Funktionen in die Funktion OnChartEvent(), um das zu erreichen:

                                                                                  void OnChartEvent(const int id,
                                                                                                    const long &lparam,
                                                                                                    const double &dparam,
                                                                                                    const string &sparam)
                                                                                    {
                                                                                  //Comment(__FUNCTION__,": id=",id," lparam=",lparam," dparam=",dparam," sparam=",sparam);
                                                                                     if(id==CHARTEVENT_KEYDOWN)
                                                                                       {
                                                                                        switch(lparam)
                                                                                          {
                                                                                           case KEY_B:
                                                                                              if(first)
                                                                                                {
                                                                                                 col=clrBlue ;
                                                                                                 typ =0;
                                                                                                 Num+=1;
                                                                                                 tp = "start";
                                                                                                }
                                                                                              else
                                                                                                {
                                                                                                 col=clrRed ;
                                                                                                 typ = 1;
                                                                                                 tp = "end";
                                                                                                }
                                                                                              ob =OBJ_ARROW_BUY;
                                                                                              first = !first;
                                                                                              Name = StringFormat("%d-%d-%s",typ,Num,tp);
                                                                                              break;
                                                                                           case KEY_S:
                                                                                              if(first)
                                                                                                {
                                                                                                 col=clrRed ;
                                                                                                 typ =1;
                                                                                                 Num+=1;
                                                                                                 tp = "start";
                                                                                                }
                                                                                              else
                                                                                                {
                                                                                                 col=clrBlue ;
                                                                                                 typ = 0;
                                                                                                 tp = "end";
                                                                                                }
                                                                                              ob =OBJ_ARROW_SELL;
                                                                                              first = !first;
                                                                                              Name = StringFormat("%d-%d-%s",typ,Num,tp);
                                                                                              break;
                                                                                  
                                                                                           default:
                                                                                              Print("You pressed:"+lparam+" key, do nothing!");
                                                                                          }
                                                                                        ChartRedraw(0);
                                                                                       }
                                                                                  //---
                                                                                     if(id==CHARTEVENT_CLICK&&(typ!=3))
                                                                                       {
                                                                                        //--- definition
                                                                                        int x=(int)lparam;
                                                                                        int y=(int)dparam;
                                                                                        datetime dt    =0;
                                                                                        double   price =0;
                                                                                        int      window=0;
                                                                                        if(ChartXYToTimePrice(0,x,y,window,dt,price))
                                                                                          {
                                                                                           ObjectCreate(0,Name,ob,window,dt,price);
                                                                                           ObjectSetInteger(0,Name,OBJPROP_COLOR,col);
                                                                                           //Print("time:",dt,"shift:",iBarShift(Symbol(),PERIOD_CURRENT,dt));
                                                                                           if(tp=="start")
                                                                                              Start=dt;
                                                                                           else
                                                                                             {
                                                                                              if(file_handle)
                                                                                                 file_write(Start,dt);
                                                                                             }
                                                                                           ChartRedraw(0);
                                                                                          }
                                                                                        else
                                                                                           Print("ChartXYToTimePrice return error code: ",GetLastError());
                                                                                       }
                                                                                  //--- object delete
                                                                                     if(id==CHARTEVENT_OBJECT_DELETE)
                                                                                       {
                                                                                        Print("The object with name ",sparam," has been deleted");
                                                                                       }
                                                                                  //--- object create
                                                                                     if(id==CHARTEVENT_OBJECT_CREATE)
                                                                                       {
                                                                                        Print("The object with name ",sparam," has been created!");
                                                                                       }
                                                                                  
                                                                                    }
                                                                                  

                                                                                  Anmerkung: Bei der Implementierung dieser Funktion haben wir den obigen Code geändert

                                                                                   if (id==CHARTEVENT_CLICK&&(typ!=3))

                                                                                  Der Grund dafür ist ganz einfach: Wir vermeiden falsche Operationen, die durch versehentliche Mausklicks verursacht werden, und verwenden die Variable „typ“, um zu kontrollieren, ob die Mausaktion gültig ist. Wenn wir einen Trend markieren, führen wir die Funktion file_write() aus. Wir fügen diese Zeile am Ende der Funktion ein

                                                                                  typ=3;

                                                                                  Dann können Sie mit der Maus auf dem Chart arbeiten, bevor Sie den nächsten Abschnitt der Markierung beginnen, ohne etwas zu tun, bis Sie eine geeignete Position finden und bereit sind, den nächsten Trend zu markieren.


                                                                                  4. Implementierung der Funktion zum Schreiben von Daten - file_write():

                                                                                  void file_write(datetime start,
                                                                                                  datetime end)
                                                                                    {
                                                                                     MqlRates rates[];
                                                                                     ArraySetAsSeries(rates,false);
                                                                                     int n_cp=CopyRates(Symbol(),PERIOD_CURRENT,start,end,rates);
                                                                                     if(n_cp>0)
                                                                                       {
                                                                                        if(FileTell(file_handle)==2)
                                                                                          {
                                                                                           FileWrite(file_handle,"time","open","high","low","close","tick_volume","trend_group","trend_index");
                                                                                           for(int i=0; i<n_cp; i++)
                                                                                             {
                                                                                              FileWrite(file_handle,
                                                                                                        rates[i].time,
                                                                                                        rates[i].open,
                                                                                                        rates[i].high,
                                                                                                        rates[i].low,
                                                                                                        rates[i].close,
                                                                                                        rates[i].tick_volume,
                                                                                                        typ,
                                                                                                        i);
                                                                                             }
                                                                                          }
                                                                                        else
                                                                                          {
                                                                                           for(int i=0; i<n_cp; i++)
                                                                                             {
                                                                                              FileWrite(file_handle,
                                                                                                        rates[i].time,
                                                                                                        rates[i].open,
                                                                                                        rates[i].high,
                                                                                                        rates[i].low,
                                                                                                        rates[i].close,
                                                                                                        rates[i].tick_volume,
                                                                                                        typ,
                                                                                                        i);
                                                                                             }
                                                                                          }
                                                                                       }
                                                                                     else
                                                                                        Print("No data copied!");
                                                                                     FileFlush(file_handle);
                                                                                     typ=3;
                                                                                    }
                                                                                  

                                                                                  5. Implementierung der Funktion zum Lesen von Dateien - read_csv():
                                                                                  void read_csv(int hd,
                                                                                                string &arry[])
                                                                                    {
                                                                                     int i=0;
                                                                                     while(!FileIsEnding(hd))
                                                                                       {
                                                                                        ArrayResize(arry,i+1);
                                                                                        arry[i]=FileReadString(hd);
                                                                                        i++;
                                                                                       }
                                                                                    }
                                                                                  

                                                                                  6. Es gibt noch ein wichtiges Problem, das hier nicht behandelt wurde: Das Dateihandle „file_handle“, das bei der Initialisierung des EA geöffnet wurde, wird nicht freigegeben. Wir geben den Handle in der abschließenden Funktion OnDeinit() frei. Wenn Sie die Funktion „FileClose(file_handle)“ aufrufen, werden alle Daten tatsächlich in die csv-Datei geschrieben. Daher ist es besonders wichtig, dass Sie nicht versuchen, die csv-Datei zu öffnen, während der EA noch läuft:
                                                                                  void OnDeinit(const int reason)
                                                                                    {
                                                                                     FileClose(file_handle);
                                                                                     Print("Write data!");
                                                                                    }
                                                                                  


                                                                                  Anmerkung: Der in diesem Artikel gezeigte Code dient nur zur Demonstration. Wenn Sie es in der Praxis verwenden wollen, sollten Sie den Code weiter verbessern. Am Ende des Artikels werden die CSV-Datei und die endgültige MQL5-Datei für die Demonstration zur Verfügung gestellt. Der nächste Artikel in dieser Reihe wird zeigen, wie man Daten über den Client in Verbindung mit Python annotiert.

                                                                                  Ich danke Ihnen für Ihre Geduld beim Lesen, ich hoffe, Sie haben etwas davon und wünsche Ihnen ein glückliches Leben, und wir sehen uns im nächsten Kapitel!

                                                                                  Übersetzt aus dem Englischen von MetaQuotes Ltd.
                                                                                  Originalartikel: https://www.mql5.com/en/articles/13225

                                                                                  Beigefügte Dateien |
                                                                                  Datenkennzeichnung für Zeitreihenanalyse (Teil 2): Datensätze mit Trendmarkern mit Python erstellen Datenkennzeichnung für Zeitreihenanalyse (Teil 2): Datensätze mit Trendmarkern mit Python erstellen
                                                                                  In dieser Artikelserie werden verschiedene Methoden zur Kennzeichnung von Zeitreihen vorgestellt, mit denen Daten erstellt werden können, die den meisten Modellen der künstlichen Intelligenz entsprechen. Eine gezielte und bedarfsgerechte Kennzeichnung von Daten kann dazu führen, dass das trainierte Modell der künstlichen Intelligenz besser mit dem erwarteten Design übereinstimmt, die Genauigkeit unseres Modells verbessert wird und das Modell sogar einen qualitativen Sprung machen kann!
                                                                                  Kategorientheorie in MQL5 (Teil 20): Ein Abstecher über die Selbstaufmerksamkeit (Self-Attention) und den Transformer Kategorientheorie in MQL5 (Teil 20): Ein Abstecher über die Selbstaufmerksamkeit (Self-Attention) und den Transformer
                                                                                  Wir schweifen in unserer Serie ab, indem wir über einen Teil des Algorithmus zu chatGPT nachdenken. Gibt es Ähnlichkeiten oder Konzepte, die den natürlichen Transformationen entlehnt sind? Wir versuchen, diese und andere Fragen in einem unterhaltsamen Stück zu beantworten, mit unserem Code in einem Signalklassenformat.
                                                                                  Verständnis der Auftragsvergabe in MQL5 Verständnis der Auftragsvergabe in MQL5
                                                                                  Bei der Entwicklung jedes Handelssystems gibt es eine Aufgabe, die wir effektiv bewältigen müssen. Diese Aufgabe besteht darin, Aufträge zu erteilen oder das erstellte Handelssystem automatisch mit Aufträgen umgehen zu lassen, da dies in jedem Handelssystem von entscheidender Bedeutung ist. Daher finden Sie in diesem Artikel die meisten Themen, die Sie über diese Aufgabe verstehen müssen, um Ihr Handelssystem in Bezug auf die Auftragsvergabe effektiv zu gestalten.
                                                                                  Die Transaktionen des Handels Anfrage- und Antwortstrukturen, Beschreibung und Protokollierung Die Transaktionen des Handels Anfrage- und Antwortstrukturen, Beschreibung und Protokollierung
                                                                                  Der Artikel befasst sich mit der Struktur von Handelsanfragen, d. h. mit der Erstellung einer Anfrage, ihrer vorläufigen Überprüfung vor der Übermittlung an den Server, der Antwort des Servers auf eine Handelsanfrage und der Struktur von Handelsgeschäften. Wir werden einfache und bequeme Funktionen zum Senden von Handelsaufträgen an den Server erstellen und auf der Grundlage der besprochenen Informationen einen EA erstellen, der über Handelsgeschäfte informiert.