English Русский 中文 Español 日本語 Português
Interaktion zwischen MetaTrader 4 und Matlab über CSV Dateien

Interaktion zwischen MetaTrader 4 und Matlab über CSV Dateien

MetaTrader 4Beispiele | 19 Februar 2016, 07:10
1 029 0
Dmitriy
Dmitriy

Einführung

Die Rechenleistung der Matlab-Umgebung ist bekannt dafür, jeder Programmiersprache, einschließlich MQL4, deutlich überlegen zu sein. Die von Matlab angebotene breite Palette an mathematischen Funktionen ermöglicht es, komplexe Berechnungen durchzuführen, die theoretische Basis der gemachten Operation vollständig vernachlässigend.

Allerdings stellt die Echtzeit-Interaktion zwischen einer Handelsplattform und Matlab keine einfache Aufgabe dar. Ich schlage einen Weg vor, den Datenaustausch zwischen MetaTrader 4 und Matlab über CSV Dateien zu organisieren.


1. Zusammenarbeit

Nehmen wir an, bei jedem eingehenden neuen Balken, muss MetaTrader 4 Daten über die letzten 100 Balken an Matlab senden und Antwort mit deren Verarbeitungsergebnissen erhalten.

Um dieses Problem zu lösen, müssen wir einen Indikator in MetaTrader 4 erstellen, der Daten in eine Textdatei schreibt und Verarbeitungsergebnisse aus einer anderen Textdatei ausliest, die von Matlab erstellt wurde.

MetaTrader 4 must seine Daten-Datei beim Eintreffen jedes neuen Balkens bilden. Er muss auch versuchen die Ergebnisse bei jedem Tick zu lesen. Um die Ergebnisse nicht zu lesen, bevor Matlab sie aktualisiert hat, löschen wir die Datei mit dem Ergebnis, bevor wir unsere Ausgabedatei bilden. In diesem Fall wird der Leseversuch nur erfolgreich sein nachdem Matlab seine Berechnungen beendet und eine neue Datei gebildet hat.

Matlab muss in jeder Sekunde in MetaTrader 4 erstellte Datei-Attribute analysieren und mit der Verarbeitung beginnen, wenn der Erstellungszeitpunkt sich ändert. Wenn die Verarbeitung beendet ist, wird die von MetaTrader 4 vor dem Beginn der Aufzeichnung gelöschte Datei neu erstellt. MetaTrader 4 löscht sie erfolgreich, lädt neue Daten und wartet auf Antwort.


2. Bilden einer Daten-Ausgabedatei

Es gibt viele dem Speichern von Daten als Datei gewidmete Artikel, also werde ich diesen Punkt hier nicht ausarbeiten. Ich möchte nur klar machen, dass wir Daten in 7 Spalten scheiben: “DATE”, “TIME”, “HI”, “LOW”, “CLOSE”, “OPEN”, “VOLUME”. Das trennende Zeichen ist “;”. Priorität der Balken ist von früheren zu späteren, d.h. die Zeile mit den Null-Balken Eigenschaften muss als letztes aufgezeichnet werden. Der Dateiname besteht aus dem Symbolnamen und dem Zeitrahmen.

#property indicator_chart_window
extern int length = 100;   // The amount of bars sent to be processed
double ExtMap[];           // Chart buffer
string nameData;
int init()
{
   nameData = Symbol()+".txt";         // name of the data file to be sent
   return(0);
}
int start()
{
   static int old_bars = 0;   // remember the amount of bars already known   
   if (old_bars != Bars)      // if a new bar is received 
   {
      write_data();                             // write the data file                              
   }      
   old_bars = Bars;              // remember how many bars are known
   return(0);
}
//+------------------------------------------------------------------+
void write_data()
{
  int handle;
  handle = FileOpen(nameData, FILE_CSV|FILE_WRITE,';');
  if(handle < 1)
  {
    Comment("Creation of "+nameData+" failed. Error #", GetLastError());
    return(0);
  }
  FileWrite(handle, ServerAddress(), Symbol(), Period());                  // heading
  FileWrite(handle, "DATE","TIME","HIGH","LOW","CLOSE","OPEN","VOLUME");   // heading
  int i;
  for (i=length-1; i>=0; i--)
  {
    FileWrite(handle, TimeToStr(Time[i], TIME_DATE), TimeToStr(Time[i], TIME_SECONDS),
                      High[i], Low[i], Close[i], Open[i], Volume[i]);
  }
  FileClose(handle);
  Comment("File "+nameData+" has been created. "+TimeToStr(TimeCurrent(), TIME_SECONDS) );
  return(0);
}

Wir werden nicht alle diese Daten brauchen, aber es ist immer besser eine aussagekräftige Datei zu haben, als eine Reihe von Spalten mir unbekannten Zahlen.


3. Erstellen einer Grafischen Benutzeroberfläche (Graphical User Interface - GUI)

Also, die Datei ist fertig. Beginnen wir mit Matlab.

Wir müssen eine Anwendung entwickeln, die Textdaten aus einer Datei liest, verarbeitet und die Ergebnisse in einer anderen Datei aufzeichnet. Wir müssen eine GUI erstellen zur Bestimmung des Dateinamens, Anzeige von Diagrammen und Starten der Verarbeitung. Fangen wir gleich damit an.

Um die GUI zu erstellen, starten wir den “GUIDE Quick Start” durch Eingeben von “guide” in die Konsole oder durch drücken auf das Matlab Hauptfenster. In der angezeigten Dialogbox wählen Sie “Create New GUI” --> “Blank GUI (Default)”. Nun sehen wir die Schnittstelle zum Erstellen einer GUI mit einem leeren Formular. In dieses Formular platzieren wir die folgenden Objekte: “Edit Text”, “Push Button”, “Static Text”, “Axes”, "Push Button". m Ergebnis muss es ungefähr so aussehen:

Jetzt müssen wir den Builder für visuelle Eigenschaften für jedes Objekt aufrufen und de Eigenschaften wir folgt festlegen:

Static Text : HorizontalAlignment – left, Tag – textInfo, String - Info.
Edit Text: HorizontalAlignment – left, Tag – editPath, String – Path select .
Push Button: Tag – pushBrowse, String – Browse.
Axes: Box – on, FontName – MS Sans Serif, FontSize – 8, Tag - axesChart.
Push Button: Tag – pushStart, String – Start.

Durch ändern der Tag-Eigenschaft, wählen wir einen einzigartigen Namen für jedes Objekt. Durch ändern anderer, modifizieren wir die Erscheinung.

Wenn alles fertig ist, starten wir die Schnittstelle durch drücken auf “Run”, bestätigen die Schnittstellen-Dateispeicherung und Speichern der M-File, vergeben einen Namen (zum Beispiel "VonZu"), und drücken auf "Save". Danach startet die GUI und erscheint so, wie sie während der Arbeit erscheint. Matlab erzeugt die M-File als Grundlage für unser zukünftiges Programm und öffnet sie im eingebetteten Editor.

Wenn das Erscheinungsbild aus irgendeinem Grund nicht passt, schließen Sie die offene GUI und korrigieren Sie die Objekt-Anordnung mit dem Editor. Meine Ausgabe zum Beispiel, zeigt MS Sans Serif nicht richtig an, also musste ich es für “Sans Serif” ändern.


4. Aufbau der Benutzeroberfläche

Das Verhalten der Schnittstelle kann im M-File Editor mit der Matlab-Sprache programmiert werden. Das durch Matlab erzeugte Programmgerüst stellt eine Liste von Funkionen dar, die bei der Arbeit mit den Schnittstellen-Objekten durch den Benutzer aufgerufen werden. Die Funktionen sind leer, also macht die GUI noch nichts. Es ist unsere Aufgabe, Funktionen mit den notwendigen Inhalten zu füllen.


4.1 Programmieren der Browse (Durchsuchen) Schaltfläche


Zunächst benötigen wir Zugriff auf eine von MetaTrader 4 erzeugte Datei, also starten wir mit der durch drücken auf "Browse" aufgerufenen Funktion.

Der Name der Funktion, die durch Drücken der Schaltfläche aufgerufen wird, besteht aus dem Namen der Schaltfläche (festgelegt durch die "Tag" Eigenschaft) und das Postfix. Wir suchen die Funktion “pushBrowse_Callback” im Dateitext oder drücken einfach auf “Show Functions” in der Werkzeugleiste und wählen “pushBrowse_Callback” in der Liste.

Die Syntax der Matlab Programmiersprache unterscheidet sich von den herkömmlichen Regeln der Codierung in C und C-ähnlichen Sprachen. Insbesondere besteht keine Notwendigkeit den Funktions-body mit Klammern zu markieren oder den Datentyp zur Übergabe an die Funktion anzugeben, Array (Vektor) Indizes starten mit einem, und das Kommentar-Zeichen ist "%". Also, der gesamte grüne obere Text ist kein Programm, sondern ein Kommentar der Matlab Entwickler für uns, um in der Lage zu sein den Fall zu erfassen.

Wir müssen ein Dialogfeld für die Eingabe des vollen Dateinamen erstellen. Dafür verwenden wir die Funktion “uigetfile”:

% --- Executes on button press in pushBrowse.
function pushBrowse_Callback(hObject, eventdata, handles)
[fileName, filePath] = uigetfile('*.txt'); % receive and the path from the user
if fileName==0          % if it is canceled
    fileName='';        % create an empty name
    filePath='';        % create an empty path
end
fullname = [filePath fileName] % form a new name
set(handles.editPath,'String', fullname); % write in the editPath

“handles” ist hier eine Struktur, die Beschreibungen aller Objekte in unserer GUI speichert, einschließlich die des Formulars, in dem wir sie platziert haben. Die Struktur wird von einer Funktion zur anderen übergeben und ermöglicht den Zugriff auf die Objekte.
“hObject” ist eine Beschreibung des Objekts, das die Funktion aufgerufen.
“set” hilft den Objekt-Wert auf einen bestimmten Wert zu setzen und hat die folgende Syntax: set(object_descriptor, object_property_name, property_value).

Sie finden den Wert der Objekteigenschaften mit der folgenden Funktion: property_value = get(object_descriptor, object_descriptor_name).
Aber vergessen Sie nicht, dass der Name ein Wert von Typ String ist, also in einzelnen Anführungszeichen stehen muss.

Das letzte, das wir über Objekte und deren Eigenschaften wissen müssen. Das Formular, in dem wir die GUI-Elemente platziert haben, ist selbst ein Objekt, platziert im "root" Objekt (es ist sein Nachfahre). Es hat außerdem eine Reihe an Eigenschaften, die modifiziert werden können. Eigenschaften können mit dem Tool namens “Object Editor” angezeigt werden, das in der Werkzeugleiste des Schnittstellen-Editors aufgerufen wird. Da Objekt "root" ist, wie der Name bereits andeutet, die Wurzel der Hierarchie der grafischen Objekte und hat keine Vorfahren.

Prüfen wir nun, was wir als Ergebnis haben. Wir starten jetzt unsere GUI durch drücken auf Run in der Haupt-Werkzeugleiste des M-File Editors. Versuchen Sie auf Browse zu klicken und wählen Sie unsere Datei. Es funktioniert? Dann schließen Sie die geöffnete GUI und gehen Sie zum nächsten Punkt.


4.2 Programmierung der Start Schaltfläche, Diagramm Zeichnen


Jetzt werden wir der Start-Schaltfläche den Aufruf der Funktion zuweisen, welche die Daten liest und in einem Diagramm anzeigt.

Zunächst erstellen wir die Funktion selbst. Wir benötigen die Struktur der 'handles' Objekt-Beschreibung als Eingaben. Mit dem Zugriff auf Objekte, sind wir in der Lage diese zu lesen und ihre Eigenschaften festzulegen.

% data reading, chart drawing, processing, storage
function process(handles)
fullname = get(handles.editPath, 'String'); % read the name from editPath
data = dlmread(fullname, ';', 2, 2);    % read the matrix from file
info = ['Last update: ' datestr(now)];  % form an informative message
set(handles.textInfo, 'String',info);   % write info into the status bar
 
high = data(:,1);   % it is now high where the first column of the data matrix is
low = data(:,2);    % d low -- the second
close = data(:,3);  % --/--
open = data(:,4);   %
len = length(open); % the amount of elements in open
 
axes(handles.axesChart); % make the axes active
hold off; % clean axes off before adding a new chart
candle(high, low, close, open); % draw candlesticks (in the current axes)
set(handles.axesChart,'XLim',[1 len]); % set limits for charting

Ein paar Erklärungen:

“dlmread” liest Daten aus der Textdatei mit Trennzeichen und hat die folgende Syntax: dlmread(full_file_name, separator, skip_strings, skip_columns),
“length(qqq)” – die größere Größe der Matrix qqq,
”now” – aktuelle Zeit und Datum,
“datestr(now)” – wandelt Datum und Zeit in einen Text,

Sie sollten außerdem wissen, das Matlab umfangreiche Hilfe-Informationen bereitstellt, mit Theorie und Beispielen.

Wir platzieren unsere Funktion am Ende des Programms (sie ist dort einfacher zu finden) und fügen ihren Aufruf in “pushStart_Callback” hinzu:

% --- Executes on button press in pushStart.
function pushStart_Callback(hObject, eventdata, handles)
process(handles);

Sie starten sie mit "Run", Datei auswählen, "Start", drücken und genießen Sie das Ergebnis


4.3 Speichern des Pfads zu einer Datei


Bis hierhin ist alles in Ordnung, aber es ist ein wenig nervend, ständig mit der Maus die Auswahl zu klicken, nachdem auf "Browse" gedrückt wurde. Versuchen wir den einmal gewählten Pfad zu speichern.
Wir beginnen mit dem Lesen. Der Name der Datei, die den Pfad speichert, besteht aus dem GUI-Namen und dem Postfix “_saveparam” und hat die Erweiterung ".mat".
Die Funktion “FromTo_OpeningFcn” wird direkt nachdem die GUI-Form erstellt wurde ausgeführt. Wir werden hier den Versuch hinzufügen, den Pfad aus der Datei zu lesen. Wenn der Versuch fehlschlägt, wird der Standartwert verwendet.

% --- Executes just before FromTo is made visible.
function FromTo_OpeningFcn(hObject, eventdata, handles, varargin)
guiName = get(handles.figure1, 'Name'); % get the name of our GUI
name = [guiName '_saveparam.mat']       % define the file name
h=fopen(name);                          % try to open the file
if h==-1                                % if the file does not open
    path='D:\';                         % the default value
else
    load(name);                         % read the file    
    fclose(h);                          % close the file
end
set(handles.editPath,'String', path);   % write the name into object "editPath"

Weitere Strings der Funktion “FromTo_OpeningFcn” bleiben unverändert.


Nun ändern wir die Funktion “pushBrowse_Callback” wie folgt:

% --- Executes on button press in pushBrowse.
function pushBrowse_Callback(hObject, eventdata, handles)
path = get(handles.editPath,'String'); % read the path from object editPath 
[partPath, partName, partExt] = fileparts(path);    % divide the path into parts
template = [partPath '\*.txt'];                     % create a template of parts
[userName, userPath] = uigetfile(template);         % get the user name and the path from the user
if userName~=0                                      % if "Cancel" is not pressed        
    path = [userPath userName];                     % reassemble the path
end
set(handles.editPath,'String', path);               % write the path into object "editPath"
guiName = get(handles.figure1, 'Name');             % get to know the name of our GUI
save([guiName '_saveparam.mat'], 'path');           % save the path

4.4 Datenverarbeitung


Als beispielhaftes Verfahren, fügen wir die Spalte "OPEN" durch eine Polynom Funktion vierter Ordnung ein.
Den folgenden Code fügen wir am Ende unserer Funktion "process" ein:

fitPoly2 = fit((1:len)',open,'poly4'); % get the polynomial formula
fresult = fitPoly2(1:len); % calculate Y values for X=(from 1 to len)
hold on; % a new chart has been added to the old one
stairs(fresult,'r'); % plot stepwise by color - 'r'- red


Nun versuchen wir zu starten und drücken “Start”.


Wenn Sie ungefähr das gleiche Ergebnis haben wie oben dargestellt, ist es höchste Zeit, anzufangen Daten als Datei zu speichern.


4.5 Daten als eine Datei Speichern


Das Speichern von Daten ist nicht komplizierter als sie zu lesen. Die einzige "Feinheit" ist, dass der Vektor “fresult” heruntergezählt werden muss, d.h. von dem neuesten zum ersten. Dies wird gemacht um das Lesen der Datei in MetaTrader 4 zu vereinfachen, beginnend von dem Null-Balken bis zum Dateiende.

Ergänzen wir die Funktion mit dem folgenden Code:

[pathstr,name,ext,versn] = fileparts(fullname); % divide the full name
                                                % of the file into parts
newName = [pathstr '\' name '_result' ext];     % re-compose the new file name
fresult = flipud(fresult);  % turn vector fresult
dlmwrite(newName, fresult);    % write in the file

Stellen Sie jetzt bitte sicher, dass die Datei das erstellte Ergebnis sich an derselben Stelle befindet, an der es in der ursprünglichen Datei war, und denselben Namen hat, ergänzt mit dem Postfix “_result”.


4.6 Timer-Steuerung


Dies ist der schwierigste Teil der Arbeit. Wir müssen einen Timer erstellen, der die von MetaTrader 4 gebildete Datei-Erstellung jede Sekunde prüft. Wenn die Zeit sich ändert, muss die Funktion "process" gestartet werden. Stop-Start des Timers werden mit "Start" ausgeführt. Wenn die GUI sich öffnet, löschen wir alle vorher erstellten Timer.

Erstellen wir einen Timer durch das Platzieren des folgenden Codes innerhalb der Funktion “FromTo_OpeningFcn”:

timers = timerfind; % find timers
if ~isempty(timers) % if timers are available
    delete(timers); % delete all timers
end
handles.t = timer('TimerFcn',{@checktime, handles},'ExecutionMode','fixedRate','Period',1.0,'UserData', 'NONE');

Der obige Code muss sofort nach unserem vorherigen Einfügen in diese Funktion eingefügt werden, d.h. vor den Strings “handles.output = hObject;” und “guidata(hObject, handles);”.

Durch Ausführen dieses Codes, prüft Matlab sofort nach Erstellung der GUI die verfügbaren Timer, löscht die bestehenden und erstellt einen neuen Timer. Der Timer ruft die Funktion "checktime" jede Sekunde auf und übergibt de Beschreibungen "handles" in sie. Abgesehen von "handles", übergibt der Timer seine eigene Beschreibung an die Funktion, sowie die Struktur, die Aufruf-Zeit und Grund enthält. Wir können dies nicht beeinflussen, aber wir müssen es berücksichtigen, wenn wir den Code der Funktion schreiben, die durch den Timer aufgerufen wird.

Sie können die Funktion dort platzieren, wo Sie es möchten. Lassen Sie sie selbst die Zeit ihres Aufrufs in die Matlab Statusleiste schreiben:

% function called by the timer
function checktime(obj, event, handles)
set(handles.textInfo,'String',datestr(now));

Bei seiner Einrichtung wird der Timer angehalten, jetzt müssen wir ihn wieder starten. Suchen wir die Funktion “pushStart_Callback”. Lassen Sie uns den in ihr platzierten Aufruf 'process(handles)' kommentieren und das Timer-Management in sie schreiben:

% --- Executes on button press in pushStart.
function pushStart_Callback(hObject, eventdata, handles)
% process(handles);
statusT = get(handles.t, 'Running'); % Get to know the timer status
if strcmp(statusT,'on')     % If it is enabled - 
    stop(handles.t);        % disable it
    set(hObject,'ForegroundColor','b'); % change color of pushStart marking
    set(hObject,'String',['Start' datestr(now)]); % change the button top marking
end     
if strcmp(statusT,'off')    % If it is disabled - 
    start(handles.t);       % enable it
    set(hObject,'ForegroundColor','r');% change color of pushStart marking
    set(hObject,'String',['Stop' datestr(now)]); % change the button top marking
end 

Nun überprüfen wir, wie alles funktioniert. Lassen Sie uns versuchen den Timer mit "Start" zu aktivieren und zu deaktivieren. Wenn der Timer aktiviert ist, muss die Uhr über dem Eingabefeld für den Pfad funktionieren.

Es wäre sinnvoller den Timer mit der "X" Schaltfläche, beim Schließen der GUI zu löschen. Wenn Sie dies tun möchten, fügen Sie

stop(handles.t) ; % stop the timer
delete(handles.t); % delete the timer

am Anfang der Funktion “figure1_CloseRequestFcn” ein. Die Funktion wird beim Schließen der GUI aufgerufen. Sie können mit dem GUI-Editor auf sie zugreifen:

Aber, bitte berücksichtigen Sie, dass wenn Sie "Run" des Editors drücken, ohne die im Betrieb befindliche GUI vorher zu schließen, der alte Timer nicht gelöscht wird, während der neue erstellt wird. Und das nächste Mal wird ein weiter erstellt, usw. Sie können die "unerledigten" Timer mit dem Befehl “delete(timerfind)” aus der Matlab Konsole behandeln.


Wenn jetzt alles richtig funktioniert, erstellen wir die Funktion zum Prüfen des Zeitpunkts der letzten Dateiänderung durch MetaTrader 4:

% function to be called by the timer
function checktime(obj, event, handles)
filename = get(handles.editPath, 'String'); % get to know the file name 
fileInfo = dir(filename);        % get info about the file
oldTime = get(obj, 'UserData');  % recall the time
if ~strcmp(fileInfo.date, oldTime) % if the time has changed
    process(handles);
end
set(obj,'UserData',fileInfo.date); % save the time
set(handles.pushStart,'String',['Stop ' datestr(now)]); % override the time

Die Funktion "dir(full_file_name)" gibt eine Struktur zurück, mit den Datei-Informationen (Name, Datum, Bytes, isdir). Die Information über den Zeitpunkt der vorherigen Datei-Erstellung, wird in der "Userdate" Eigenschaft des Timer Objekts gespeichert. Seine Beschreibung wird an die Funktione "checktime" übergeben, benannt als obj.

Wenn nun eine von MetaTrader 4 erstellte Datei sich ändert, wird unsere Programm das Ergebnis überschrieben. Sie können dies durch manuelles Ändern der Datei prüfen (z.B. durch löschen des letzten Strings) und die Änderungen in dem sich ergebenden Diagramm oder Datei verfolgen. Natürlich muss die "Start" Schaltfläche dabei gedrückt werden.

Wenn ein zusätzliches Fenster mit der Diagrammkopie während des Programmbetriebes erstellt wird, fügen Sie den folgenden String am Anfang der Funktion "process" ein:

set(handles.figure1,'HandleVisibility','on');


5. Zeichnen der Ergebnisse in MetaTrader 4


Kehren wir zurück zu MetaTrader 4. Wir müssen unseren Indikator mit einer Funktion ergänzen, welche die Ergebnisse aus der Datei liest und in das Diagramm zeichnet. Das Verhalten des Programms wird wie folgt beschrieben:

1. Wenn ein neuer Balken eintrifft: Löschen der alten Ergebnis-Datei, Speichern der Daten-Datei.
2. Wenn die Ergebnisdatei lesbar ist: Lesen der Datei, ein Diagramm zeichnen, Löschen der Ergebnis-Datei.

Ich werde hier jetzt nicht beschreiben, wie der Code unten funktioniert, da das Auslesen von Dateien und das Zeichnen von Indikatoren in anderen Artikel zu finden ist. Ich möchte nur anmerken, dass die Ergebnis-Datei hier sofort gelöscht wird, nachdem sie als Diagramm umgesetzt wurde. Also keine Sorge, wenn Sie mehrere Fehlermeldungen sehen.

Lesefehler treten in zwei Fällen auf:
1. Sofort nachdem ein neuer Balken eingetroffen ist, da die Ergebnis-Datei noch nicht erstellt wurde.
2. Sofort nachdem das Ergebnis gelesen und das Diagramm gezeichnet wurde, weil die Date gelöscht wurde, um nicht die gleichen Daten erneut zu lesen.

Auf diese Weise erhält das Programm seinen "Lesefehler"-Status für praktisch die ganze Zeit. :)

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_width1 2
#property indicator_color1 Tomato
extern int length = 100;   // The amount of bars to be sent for processing
double ExtMap[];           // Chart buffer
string nameData;
string nameResult;

int init()
{
   nameData = Symbol()+".txt";         // the name of the data file to be sent
   nameResult = Symbol()+"_result.txt";// the name of the received file containing results
   SetIndexStyle(0, DRAW_LINE);
   SetIndexBuffer(0, ExtMap);
   return(0);
}
int deinit()
  {
   Comment("");
   return(0);
  }
int start()
{
   static int attempt = 0;    // the amount of attempts to read the result
   static int old_bars = 0;   // remember the amount of the known bars
   
   if (old_bars != Bars)      // if a new bar has income 
   {
      FileDelete(nameResult);                   // delete the result file
      ArrayInitialize( ExtMap, EMPTY_VALUE);    // empty the chart
      write_data();                             // save the data file
      
      old_bars = Bars; return(0);               // nothing should be done this time                           
   }
   //
   int handle_read = FileOpen(nameResult,
                              FILE_CSV|FILE_READ,
                              ';'); // try to open the result file
   attempt++;                       // count the attempt to open
   
   if(handle_read >= 0)             // if the file has opened for reading
   { 
      Comment(nameResult+". Opened with attempt #"+ attempt); // opening report
      read_n_draw(handle_read);  // read the result and draw a chart
      FileClose(handle_read);    // close the file
      FileDelete(nameResult);    // delete the result file
      attempt=0;                 // zeroize the amount of attempts to read
   }
   else                          // if we cannot open the result file
   {
      Comment( "Failed reading "+nameResult+
               ". Amount of attempts: "+attempt+
               ". Error #"+GetLastError()); //Report about failed reading
   }
   old_bars = Bars;              // remember how many bars are known
   return(0);
}
//+------------------------------------------------------------------+
void read_n_draw(int handle_read)
{
   int i=0;
   while ( !FileIsEnding(handle_read)) 
   {
      ExtMap[i] = FileReadNumber(handle_read);
      i++;     
   }
   ExtMap[i-1] = EMPTY_VALUE;
}

 
void write_data()
{
  int handle;
  handle = FileOpen(nameData, FILE_CSV|FILE_WRITE,';');
  if(handle < 1)
  {
    Comment("Failed creating "+nameData+". Error #", GetLastError());
    return(0);
  }
  FileWrite(handle, ServerAddress(), Symbol(), Period());                  // header
  FileWrite(handle, "DATE","TIME","HIGH","LOW","CLOSE","OPEN","VOLUME");   // header
  int i;
  for (i=length-1; i>=0; i--)
  {
    FileWrite(handle, TimeToStr(Time[i], TIME_DATE), TimeToStr(Time[i], TIME_SECONDS),
                      High[i], Low[i], Close[i], Open[i], Volume[i]);
  }
  FileClose(handle);
  Comment("File "+nameData+" has been created. "+TimeToStr(TimeCurrent(), TIME_SECONDS) );
  return(0);
}

Unten ist mein endgültiges Ergebnis. Ich hoffe, ich habe keine Fehler gemacht und Sie sind in der Lage es zu reproduzieren.





Fazit

In diesem Artikel haben wir den Weg zur Organisation der Interaktion zwischen MetaTrader 4 und Matlab über CSV Dateien beschrieben. Diese Methode ist weder einzigartig noch optimal. Der Wert dieses Ansatzes ist es, das er hilft Daten-Arrays auszutauschen, ohne besondere Fähigkeiten in der Arbeit mit Programmierwerkzeugen, außer MetaTrader 4 und Matlab.


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

Beigefügte Dateien |
work.zip (9.98 KB)
Tester im Terminal MetaTrader 4: Man sollte ihn kennen Tester im Terminal MetaTrader 4: Man sollte ihn kennen
Die aufwendige Schnittstelle des Terminals MetaTrader 4 ist führend, aber daneben beinhaltet das Terminal einen intelligent angelegten Tester für Strategien. Und während der Wert von MetaTrader 4 als Handelsplattform offensichtlich ist, kann die Qualität der Strategie-Tests des Testers nur in der Praxis beurteilt werden. Dieser Artikel zeigt die Vorteile und Annehmlichkeiten der Tests in MetaTrader 4.
MT4TerminalSync - System für die Synchronisation von MetaTrader 4 Terminals MT4TerminalSync - System für die Synchronisation von MetaTrader 4 Terminals
Dieser Artikel widmet sich dem Thema "Erweitern der Möglichkeiten von MQL4 Programmen mit Funktionen des Betriebssystems und anderen Mitteln der Programmentwicklung". Der Artikel beschreibt ein Beispiel eines Programmsystems, das die Aufgabe der Synchronisierung mehrerer Terminal-Kopien, basierend auf einer einzelnen Quellvorlage, umsetzt.
Wie man einen EA Code Beschneidet für ein Leichteres Leben und Weniger Fehler Wie man einen EA Code Beschneidet für ein Leichteres Leben und Weniger Fehler
Ein einfaches in diesem Artikel beschriebenes Konzept, ermöglicht die diese Entwicklung a6tomatisierter Handelssysteme in MQL4, um bestehende Handelssysteme zu vereinfachen, sowie die für die Entwicklung neuer Systeme benötigte Zeit durch kürzere Codes zu reduzieren.
Test Visualisierung: Kontostand Charts Test Visualisierung: Kontostand Charts
Genießen Sie den Vorgang des Tests mit Charts, mit Anzeige des Kontostands - alle benötigten Angaben immer im Auge!