Startseite Systemhandel Beitrag

Tick-Datenhistorie für MetaTrader 5 herunterladen – So funktioniert's

Anhang
56324.zip (3.28 KB, Herunterladen 2 mal)

In diesem Artikel zeige ich dir, wie du mit einem Expert Advisor (EA) alle verfügbaren Tick-Daten eines Symbols in MetaTrader 5 herunterladen kannst. Dieser Code durchsucht die Marktplattform deines Brokers und extrahiert die Symbole, für die er alle verfügbaren Ticks oder Ticks bis zu einem bestimmten Datum herunterlädt.

Dies kann dir helfen, die gesamte Symbolhistorie für Backtests herunterzuladen oder benutzerdefinierte Charts aus diesen Ticks zu erstellen. Achte darauf, dass genug Speicherplatz auf deiner Festplatte vorhanden ist, da die Ticks im Datenordner zwischengespeichert werden.

Um den Download der Symbole zu erleichtern, benötigen wir zuerst einen Download-Manager. Die Struktur CDownloadManager enthält alle Informationen, die wir benötigen.

struct CDownloadManager
  {
   bool m_started,m_finished;
   string m_symbols[],m_current;
   int m_index;
}
  • Der Status des Downloads (gestart/abgeschlossen)
  • Die Liste der zu scannenden Symbole
  • Das aktuelle Symbol
  • Der Index des gerade gescannten Symbols

Wir müssen auch mit der Festplatte lesen und schreiben, und da wir mit Symbolen arbeiten, erstellen wir zwei Funktionen, um Strings aus Binärdateien zu lesen und zu schreiben.

Die Funktion zum Speichern eines Strings in eine Datei:

void writeStringToFile(int f,string thestring)
  {
   // Speichere das Symbol-String
   char sysave[];
   int charstotal=StringToCharArray(thestring,sysave,0,StringLen(thestring),CP_ACP);
   FileWriteInteger(f,charstotal,INT_VALUE);
   for(int i=0;i<charstotal;i++)
     {
      FileWriteInteger(f,sysave[i],CHAR_VALUE);
     }
  }

Die Funktion erhält:

  • Die Datei-ID f, einer zum Schreiben geöffneten Datei mit binären Flags FILE_WRITE|FILE_BIN
  • Den zu speichernden String

Sie schreibt die Länge der Zeichen in die Datei und speichert dann jedes Zeichen im String.

Die Funktion zum Laden eines Strings aus einer Datei:

string readStringFromFile(int f)
  {
   string result="";
   // Lade das Symbol-String
   char syload[];
   int charstotal=(int)FileReadInteger(f,INT_VALUE);
   if(charstotal>0)
     {
      ArrayResize(syload,charstotal,0);
      for(int i=0;i<charstotal;i++)
        {
         syload[i]=(char)FileReadInteger(f,CHAR_VALUE);
        }
      result=CharArrayToString(syload,0,charstotal,CP_ACP);
     }
   return(result);
  }

Diese Funktion erhält:

  • Die Datei-ID f, einer zum Lesen geöffneten Datei mit binären Flags FILE_READ|FILE_BIN

Sie liest die Länge der Zeichen und lädt die Zeichen in ein Char-Array, das dann in einen String umgewandelt und zurückgegeben wird.

Zurück zur Struktur CDownloadManager. Wir benötigen eine Möglichkeit, den Manager zu initialisieren und mit den Daten aus der Marktbeobachtung zu füllen:

//+------------------------------------------------------------------+
//| Symbole von der Marktbeobachtung abrufen |
//+------------------------------------------------------------------+
void grab_symbols()
   {
    //! nur von der MW!
    int s=SymbolsTotal(true);
    ArrayResize(m_symbols,s,0);
    for(int i=0;i<ArraySize(m_symbols);i++)
      {
        m_symbols[i]=SymbolName(i,true);
      }
  }

Das ist ziemlich einfach:

  • Wir fragen, wie viele Symbole in der Marktbeobachtung aktiv sind
  • Wir passen unser m_symbols-Array an, um diese aufzunehmen
  • Wir durchlaufen die Symbole und fordern die Namen der Symbole an

Wir sind auch verantwortlich für das Management des Downloads der Symbol-Daten, daher benötigen wir eine Funktion, die im Wesentlichen den Prozess verwaltet:

//+------------------------------------------------------------------+
//| Verwaltung des Downloadprozesses |
//+------------------------------------------------------------------+
void manage(string folder,string filename)
   {
    // Diese Funktion startet oder wechselt zum nächsten Symbol
    // falls gesetzt
    if(ArraySize(m_symbols)>0)
    {
      // wenn nicht gestartet
      if(!m_started)
         {
          m_started=true;
          // gehe zum ersten Symbol
          m_current=m_symbols[0];
          m_index=1;
          save(folder,filename);
          if(_Symbol!=m_current)
            {
              ChartSetSymbolPeriod(ChartID(),m_current,_Period);
          }
          else
          {
              ENUM_TIMEFRAMES new_period=PERIOD_M1;
          for(int p=0;p<ArraySize(TFS);p++)
             {
              if(_Period!=TFS[p])
                {
                 new_period=TFS[p];
                 break;
                }
                 }
              ChartSetSymbolPeriod(ChartID(),m_current,new_period);
              }
          return;
      }
      // Wenn gestartet       else        {             m_index++;             if(m_index<=ArraySize(m_symbols))               {                m_current=m_symbols[m_index-1];                save(folder,filename);                if(_Symbol!=m_current)                  {                   ChartSetSymbolPeriod(ChartID(),m_current,_Period);                  }                return;       }
      else       {              m_finished=true;              FileDelete(folder+"\"+filename);              Print("Fertig");              ExpertRemove();              return;       }      }
    }
    else     {       Print("Bitte zuerst Symbole abrufen");     }
    }

So funktioniert das System:

  • Das Chart öffnet sich, dafür benötigen wir 1 Chart, und ein Timer wird gesetzt.
  • Dieser Timer wird ausgeführt, wir stoppen den Timer
  • Wir prüfen, ob dies ein neuer Download oder ein fortlaufender Download ist
  • Wenn es ein neuer Download ist, richten wir ihn ein, indem wir alle Symbole abrufen
  • Wenn es ein fortlaufender Download ist, laden wir die Daten für das aktuelle Symbol herunter

Hier ist der Teil des Codes, der den Download im Timer durchführt:

//+------------------------------------------------------------------+
//| Timer |
//+------------------------------------------------------------------+
void OnTimer()
  {
//--- wenn synchronisiert
   if(SymbolIsSynchronized(_Symbol)&&TerminalInfoInteger(TERMINAL_CONNECTED)==1)
     {
      EventKillTimer();
      //--- lade das System hier
      if(MANAGER.load(MANAGER_FOLDER,MANAGER_STATUS_FILE))
        {
        //--- System geladen, wir scannen hier ein Symbol
        Comment("System geladen und wir verarbeiten "+MANAGER.m_current);
        //--- Tick laden

        //--- finde den ältesten Tick, der beim Broker verfügbar ist
        int attempts=0;
        int ping=-1;
        datetime cursor=flatten(TimeTradeServer());
        long cursorMSC=((long)cursor)*1000;
        long jump=2592000000;//60*60*24*30*1000;

        MqlTick receiver[];
        long oldest=LONG_MAX;
        Comment("Bitte warten");
        while(attempts<5)
           {
            ping=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,cursorMSC,1);
            if(ping==1)
              {
               if(receiver[0].time_msc==oldest)
                 {
                  attempts++;
                 }
               else
                 {
                  attempts=0;
                 }
               if(receiver[0].time_msc<oldest)
                 {
                  oldest=receiver[0].time_msc;
                 }
               cursorMSC-=jump;
               if(limitDate&&receiver[0].time<=oldestLimit)
                 {
                  break;
                 }
          }
            else
              {
               attempts++;
              }

            Sleep(44);
            Comment("Ältester Tick : "+TimeToString((datetime)(oldest/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+"
Cursor("+TimeToString((datetime)(cursorMSC/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+")
Versuche("+IntegerToString(attempts)+")
Bitte warten auf Antwort...");
      }
      //--- an diesem Punkt haben wir den ältesten Tick
      //--- beginne Ticks vom ältesten zum neuesten anzufordern
      if(oldest!=LONG_MAX)
         {
            ArrayFree(receiver);
            datetime newest_tick=0;
            //--- erhalte die Zeit des letzten Ticks für dieses Symbol, gespeichert in symbol_time
            datetime most_recent_candle=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
            while(newest_tick<most_recent_candle)
              {
               //--- fordere ein neues Batch an, beginnend mit der ältesten Zeit und dem angegebenen Tick-Limit
               int pulled=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,oldest,tick_packets);
               if(pulled>0)
                 {
                  //--- wenn wir ein neues Batch abrufen, aktualisieren wir unsere heruntergeladenen Zeiten
                  newest_tick=receiver[pulled-1].time;
                  oldest=receiver[pulled-1].time_msc;
                  ArrayFree(receiver);
                 }
               //--- Wartezeit für Serveranfragen, ändere sie, wenn du möchtest
               Sleep(44);
               Comment("Bis jetzt bis "+TimeToString(newest_tick,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" gezogen");
              }
          }
          else
           {
            Alert("Bitte schließe das Terminal \n gehe zum Ticks-Ordner \n und lösche die leeren Ordner");
            ExpertRemove();
          }
        //--- aktualisiere den Manager und fahre fort
         MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE);
      }
      else
      {
        //--- hole die Symbole der Marktbeobachtung, um den Download zu starten
         Comment("MW abrufen und starten");
         MANAGER.grab_symbols();
         MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE);
      }
    }

Mit dieser Anleitung bist du nun bestens gerüstet, um die Tick-Datenhistorie für deine Backtests herunterzuladen. Viel Erfolg beim Traden!

Verwandte Beiträge

Kommentar (0)