Strukturen in MQL5 und Methoden zum Drucken deren Daten
Inhalt
- Einführung
- Die Struktur MqlDateTime
- Druckmethoden für MqlDateTime
- Funktionen für die Arbeit mit den Daten der Struktur von MqlDateTime
- Zusatzfunktionen
- Das Jahr in der Struktur MqlDateTime
- Der Monat in der Struktur MqlDateTime
- Der Tag in der Struktur MqlDateTime
- Stunden in der Struktur MqlDateTime
- Minuten in der Struktur MqlDateTime
- Sekunden in der Struktur MqlDateTime
- Der Wochentag in der Struktur MqlDateTime
- Die Nummer eines Tages in einem Jahr in der Struktur MqlDateTime
- Beispiele für die Verwendung
- Die Struktur MqlTick
- Druckmethoden für MqlTick
- Funktionen für die Arbeit mit den Daten der Struktur MqlTick
- Zusatzfunktionen
- Zeit in der MqlTick-Struktur
- Der Geldkurs (Bid) in der MqlTick-Struktur
- Der Briefkurs (Ask) in der MqlTick-Struktur
- Der letzter Handelskurs in der MqlTick-Struktur
- Das letztes Preisvolumen in der MqlTick-Struktur
- Zeit in Millisekunden in der Struktur MqlTick
- Tick-Flags in der Struktur MqlTick
- Das letztes Preisvolumen mit erhöhter Genauigkeit in der MqlTick-Struktur
- Beispiel für die Verwendung
- Die Struktur MqlRates
- Druckmethoden für MqlRates
- Funktionen für die Arbeit mit den Daten der Struktur MqlRates
- Zeit
- Eröffnungskurs (Open)
- Hoch (High)
- Tief (Low)
- Schlusskurs (Close)
- TickVolume
- Spread
- RealVolume
- Beispiele für die Verwendung
- Die Struktur MqlBookInfo
- Druckmethoden für MqlBookInfo
- Funktionen für die Arbeit mit den Daten der Struktur MqlBookInfo
- Auftragsart in der Struktur der Markttiefe MqlBookInfo
- Auftragspreis in der Struktur der Markttiefe MqlBookInfo
- Auftragsvolumen in der Struktur der Markttiefe MqlBookInfo
- Volumen mit erhöhter Genauigkeit
- Beispiele für die Verwendung
- Schlussfolgerung
Einführung
Die Struktur ist ein praktisches Werkzeug zum Speichern, Aufzeichnen und Abrufen logisch zusammenhängender Daten, die zu einer beliebigen Definition gehören, aus einer einzigen Variablen.
MQL5 verfügt über 12 vordefinierte Strukturen zur Speicherung und Übermittlung von Serviceinformationen:
- MqlDateTime ist für die Darstellung von Datum und Uhrzeit vorgesehen;
- MqlParam ermöglicht die Übergabe von Eingaben bei der Erstellung eines Indikator-Handles mit der Funktion IndicatorCreate();
- MqlRates bietet Informationen über historische Daten mit Preis, Volumen und Spread;
- MqlBookInfo dient zum Abrufen der Daten der Markttiefe (Kursfenster);
- MqlTradeRequest stellt eine Handelsanfrage bei der Durchführung von Handelsgeschäften;
- MqlTradeCheckResult ermöglicht die Überprüfung einer vorbereiteten Handelsanfrage vor deren Absendung;
- MqlTradeResult enthält die Antwort des Handelsservers auf eine Handelsanfrage, die von der Funktion OrderSend() gesendet wurde;
- MqlTradeTransaction spiegelt die den aktuellen Handelsvorgang;
- MqlTick ist für den schnellen Abruf der am meisten nachgefragten Informationen über die aktuelle Preise konzipiert.
- Die Strukturen des Wirtschaftskalenders werden verwendet, um Daten über die Ereignisse des Wirtschaftskalenders zu erhalten, die in Echtzeit an die MetaTrader 5-Plattform gesendet werden. Die Funktionen des Wirtschaftskalenders ermöglichen die Analyse makroökonomischer Parameter unmittelbar nach der Veröffentlichung neuer Berichte, da die relevanten Werte direkt und ohne Verzögerung von der Quelle übertragen werden.
Die Strukturen MqlParam und MqlTradeRequest übermitteln technische Informationen zur Erstellung von Indikatoren und zum Senden von Handelsaufträgen an den Server. Wir füllen die erforderlichen Felder der Strukturen entsprechend dem gewünschten Ergebnis der Datenübermittlung in der ausgefüllten Struktur aus. Mit anderen Worten, diese Strukturen müssen nicht unbedingt die Daten ausgeben, die den Feldern dieser Strukturen von einem Programmierer zugewiesen wurden.
Die übrigen Strukturen liefern jedoch Abfrageergebnisse, und jedes Feld wird entweder vom Terminal-Subsystem oder vom Handelsserver ausgefüllt. Das Abrufen von Daten aus diesen Strukturen, das Analysieren von programmatisch gefüllten Feldern von Strukturen oder das Ausdrucken in ein Protokoll für eine anschließende manuelle Analyse ist sehr praktisch und notwendig, um sowohl programmatische Entscheidungen zu treffen als auch den Ort eines logischen Fehlers zu verstehen und zu finden.
Um alle Felder einer Struktur auszudrucken, gibt es die Standardfunktion ArrayPrint(), die die im Array enthaltenen Daten mit dem Typ der behandelten Struktur in einem praktischen Tabellenformat anzeigt. Aber manchmal müssen wir die Daten aus der Struktur in einem anderen Format ausgeben, das vielleicht bequemer ist als eine tabellarische Darstellung. So kann es beispielsweise erforderlich sein, alle Felder der Struktur in einer Zeile anzuzeigen - mit Überschriften und entsprechenden Daten. Dies kann sich bei der Analyse großer Datenmengen als vorteilhaft erweisen. Gleichzeitig benötigen wir manchmal eine detailliertere Ansicht - mit einer Beschreibung der Strukturfelder und einer anderen Darstellung der entsprechenden Daten.
In diesem Artikel werden wir uns mit den Standardwerkzeugen für die Anzeige von Strukturdaten befassen und nutzerdefinierte Funktionen für verschiedene Darstellungen von Strukturdaten im Journal-Log erstellen.
Die Struktur MqlDateTime
Die Datenstruktur enthält acht Felder vom Typ int.
struct MqlDateTime { int year; // year int mon; // month int day; // day int hour; // hour int min; // minutes int sec; // seconds int day_of_week; // day of the week (0-Sunday, 1-Monday, ... ,6-Saturday) int day_of_year; // number of a day in the year (1st of January has number 0) };
Die Standardfunktionen TimeCurrent(), TimeGMT(), TimeLocal(), TimeTradeServer() und TimeToStruct() werden zum Ausfüllen der Strukturfelder verwendet.
Die ersten vier Funktionen geben nicht nur das aktuelle Datum, das GMT-Datum, die lokale Computerzeit und das Datum des Handelsservers zurück, sondern haben auch jeweils eine Überladung. In den Formalparametern der Funktion können wir ihr eine Datumsstruktur per Referenz übergeben. Nach Ausführung der Funktion werden die an die Funktion übergebenen Strukturfelder mit den von der Funktion zurückgegebenen Datumsdaten gefüllt.
Die Funktion TimeToStruct() wurde speziell entwickelt, um eine Struktur vom Typ datetime (Anzahl der Sekunden seit dem 01.01.1970) der Variablen vom Typ MqlDateTime zuzuweisen.
bool TimeToStruct( datetime dt, // date and time MqlDateTime& dt_struct // structure for accepting values );
Bei Erfolg wird true zurückgegeben, andernfalls false. Nach der Operation sind der Datumsstruktur die Zeitdaten zugewiesen worden, der ersten Parameter ist eine Variable mit dem Typ datetime.
Unsere Datumsstruktur ist vollständig, aber wie können wir sie ausdrucken? Es gibt eine Standardfunktion TimeToString(), die einen Wert, der die Zeit in Sekunden seit dem 01.01.1970 enthält, in eine Zeichenkette im Format „yyyy.mm.dd hh:min:sec“ umwandelt.
Die Funktion funktioniert jedoch nicht mit der MqlDateTime-Struktur, sondern mit einem Datetime-Datum. Sollten wir die Struktur also wieder in einen Zeitwert umwandeln? Nein, natürlich nicht. Jede der Funktionen ist für ihre eigenen Zwecke bestimmt. Wir können jede Komponente des Datums und der Uhrzeit separat aus der Datumsstruktur entnehmen - ein Jahr, einen Monat, eine Stunde, eine Minute, einen Wochentag usw... Aber wie können wir alle Daten der Struktur anzeigen?
Die Funktion ArrayPrint(), die ein Array eines einfachen Typs oder einer einfachen Struktur protokolliert, ist für diese Aufgabe geeignet. Sie zeigt Daten in Form einer Tabelle an, wobei die Spalten die Felder der Struktur und die Zeilen die Array-Zellen darstellen. Mit anderen Worten: Um die Struktur eines einzigen Datums anzuzeigen, benötigen wir ein Array von 1. Für eine Handelswoche beträgt die Array-Größe in der Regel 5 Handelstage, vorausgesetzt, die Daten stammen aus dem D1-Chart.
Druckmethoden für MqlDateTime
Ein solches Skript gibt eine Datumsstruktur aus, die mit ArrayPrint() aus der aktuellen Zeit im Journal ermittelt wurde:
void OnStart() { //--- Declare a date structure variable MqlDateTime time; //--- Get the current time and at the same time fill in the date structure TimeCurrent(time); //--- Declare an array with the MqlDateTime type and write the data of the filled structure into it MqlDateTime array[1]; array[0]=time; //--- Display the header and time using the standard ArrayPrint() Print("Time current (ArrayPrint):"); ArrayPrint(array); /* Sample output: Time current (ArrayPrint): [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year] [0] 2023 7 17 12 8 37 1 197 */ }
Die Funktion, die eine Datumsstruktur aufnimmt und im Journal ausgibt, sieht dementsprechend wie folgt aus:
//+------------------------------------------------------------------+ //| Take a date structure and display its data to the journal. | //| Use ArrayPrint() for display | //+------------------------------------------------------------------+ void MqlDateTimePrint(const MqlDateTime& time_struct) { //--- Declare an array with the MqlDateTime type and write the data of the obtained structure into it MqlDateTime array[1]; array[0]=time_struct; //--- Print the array ArrayPrint(array); /* Sample output: Time current (ArrayPrint): [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year] [0] 2023 7 17 12 8 37 1 197 */ }
Die Funktion ermöglicht den Ausdruck eines in der Variablen time_struct übergebenen Datums im Journal.
Das Skript, das eine einzelne Datumsstruktur mit der oben vorgestellten Funktion protokolliert:
void OnStart() { //--- Declare a date structure variable MqlDateTime time; //--- Get the current time and at the same time fill in the date structure TimeCurrent(time); //--- Display the header and time using the standard ArrayPrint() Print("Time current (ArrayPrint):"); MqlDateTimePrint(time); /* Sample output: Time current (ArrayPrint): [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year] [0] 2023 7 17 12 8 37 1 197 */ }
Wenn wir ein Array mit Daten ausdrucken müssen (was ja das Hauptziel von ArrayPrint() ist), dann müssen wir das Datenarray an die Funktion datetime übergeben, das MqlDateTime-Array ausfüllen und ausdrucken.
Die Funktion, die das Array datetime übernimmt und das MqlDateTime-Array ausgibt:
//+------------------------------------------------------------------+ //| Accept the datetime array, convert it into MqlDateTime and | //| display converted data into the journal. | //| Use ArrayPrint() for display | //+------------------------------------------------------------------+ void MqlDateTimePrint(const datetime& array_time[]) { //--- Declare a dynamic array of the MqlDateTime type MqlDateTime array_struct[]; //--- Get the size of the array passed to the function int total=(int)array_time.Size(); //--- If an empty array is passed, report on that and leave the function if(total==0) { PrintFormat("%s: Error. Empty array.",__FUNCTION__); return; } //--- Change the size of the MqlDateTime array to match the size of the datetime array ResetLastError(); if(ArrayResize(array_struct,total)!=total) { PrintFormat("%s: ArrayResize() failed. Error %s",__FUNCTION__,(string)GetLastError()); return; } //--- Convert dates from the datetime array into the date structure in the MqlDateTime array for(int i=0;i<total;i++) { ResetLastError(); if(!TimeToStruct(array_time[i],array_struct[i])) PrintFormat("%s: [%s] TimeToStruct() failed. Error %s",__FUNCTION__,(string)i,(string)GetLastError()); } //--- Print the filled MqlDateTime array ArrayPrint(array_struct); /* Sample output: Time data of the last 10 bars GBPUSD H1 (ArrayPrint): [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year] [0] 2023 7 17 7 0 0 1 197 [1] 2023 7 17 8 0 0 1 197 [2] 2023 7 17 9 0 0 1 197 [3] 2023 7 17 10 0 0 1 197 [4] 2023 7 17 11 0 0 1 197 [5] 2023 7 17 12 0 0 1 197 [6] 2023 7 17 13 0 0 1 197 [7] 2023 7 17 14 0 0 1 197 [8] 2023 7 17 15 0 0 1 197 [9] 2023 7 17 16 0 0 1 197 */ }
Dementsprechend sieht das Skript, das die obige Funktion verwendet, um das Array datetime im Journal auszudrucken, wie folgt aus:
void OnStart() { //--- Declare a time array datetime array[]; //--- Copy the time of the last 10 bars to the array ResetLastError(); if(CopyTime(Symbol(),Period(),0,10,array)<0) { PrintFormat("CopyTime() failed. Error %s",(string)GetLastError()); return; } //--- Display the header and the time data array of the last 10 bars using the standard ArrayPrint() PrintFormat("Time data of the last 10 bars %s %s (ArrayPrint):",Symbol(),StringSubstr(EnumToString(Period()),7)); MqlDateTimePrint(array); /* Sample output: Time data of the last 10 bars GBPUSD H1 (ArrayPrint): [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year] [0] 2023 7 17 7 0 0 1 197 [1] 2023 7 17 8 0 0 1 197 [2] 2023 7 17 9 0 0 1 197 [3] 2023 7 17 10 0 0 1 197 [4] 2023 7 17 11 0 0 1 197 [5] 2023 7 17 12 0 0 1 197 [6] 2023 7 17 13 0 0 1 197 [7] 2023 7 17 14 0 0 1 197 [8] 2023 7 17 15 0 0 1 197 [9] 2023 7 17 16 0 0 1 197 */ }
Funktionen für die Arbeit mit MqlDateTime-Strukturdaten.
Alles, was oben getestet wurde, ist bequem, praktisch und übersichtlich. Manchmal sind jedoch umfassendere Informationen erforderlich, und zwar vorzugsweise in derselben knappen Darstellung. Oder aber wir brauchen eine detailliertere Beschreibung, indem wir die Kürze und Trockenheit der Datenpräsentation verringern. Zum Beispiel kann eine Tageszahl allein schon verwirrend sein. Wenn aber „Do.“ geschrieben wird, dann verstehen wir sofort, dass es sich um den Donnerstag handelt. Das Gleiche gilt für eine Monatsnummer - manchmal ist es besser, „07 (Juli)“ zu sehen, als sich daran zu erinnern, welcher Monat an siebter Stelle steht... Das mag natürlich übertrieben sein, aber solche kleinen Verbesserungen sind doch sehr praktisch. Diese kleinen Annehmlichkeiten summieren sich zu einem spürbaren Zeitgewinn bei der Analyse großer Mengen von Einträgen in den Programmprotokollen.
Um solche Annehmlichkeiten hinzuzufügen, müssen wir eine eigene Funktion schreiben, die eine Beschreibung des Datums im MqlDateTime-Format zurückgibt.
Die Funktion wird:
- Daten in einem Kurzformat anzeigen (Wochentag, Monat, Tag, Jahr, Uhrzeit);
- Daten in einer Tabellenansicht anzeigen (Datenkopfwert);
Bevor wir mit der Erstellung von Funktionen zur Rückgabe von Beschreibungen von Strukturfeldern beginnen, werden wir Hilfsfunktionen erstellen, die die Namen von Wochentagen und Monaten zurückgeben.
Zusatzfunktionen
Um den Namen eines Wochentags zu erhalten, schreiben wir eine einfache Funktion, die den Text des Wochentags in Abhängigkeit vom Wert im Strukturfeld zurückgibt, in dem der Wochentag im numerischen Format gespeichert ist:
//+------------------------------------------------------------------+ //| Return the name of a week day | //+------------------------------------------------------------------+ string DayWeek(MqlDateTime &date_time) { //--- Define a week day name string dw=EnumToString((ENUM_DAY_OF_WEEK)date_time.day_of_week); //--- Convert all obtained symbols to lower case and replace the first letter from small to capital if(dw.Lower()) dw.SetChar(0,ushort(dw.GetChar(0)-0x20)); //--- Return a resulting string return dw; /* Sample output: Wednesday */ }
Da MQL5 eine Liste mit Wochentagsnamen hat, verwenden wir hier die Zeichen-Darstellung des Enumerationswertes. Um sicherzustellen, dass der Text korrekt erscheint, werden alle Zeichen in der Zeile in Kleinbuchstaben umgewandelt, mit Ausnahme des ersten Buchstabens des Wortes.
Um den Namen eines Monats zu erhalten, schreiben wir eine einfache Funktion, die den Text eines Monats in Abhängigkeit vom Wert im Strukturfeld zurückgibt, das den Monat im numerischen Format speichert:
//+------------------------------------------------------------------+ //| Return a month name | //+------------------------------------------------------------------+ string Month(MqlDateTime &date_time) { //--- Define a month name switch(date_time.mon) { case 1 : return "January"; case 2 : return "February"; case 3 : return "March"; case 4 : return "April"; case 5 : return "May"; case 6 : return "June"; case 7 : return "July"; case 8 : return "August"; case 9 : return "September"; case 10 : return "October"; case 11 : return "November"; case 12 : return "December"; default : return "Undefined"; } /* Sample output: July */ }
MQL5 hat keine Liste mit den Monatsnamen, sodass wir hier den Switch-Operator verwenden müssen, um den Text des Monatsnamens auszuwählen und zurückzugeben, abhängig von dem digitalen Wert, der in das Strukturfeld geschrieben wurde.
Diese Funktionen werden uns bei der Anzeige von Beschreibungen der Wochentage und Monate nützlich sein. Außerdem können sie in Zukunft für unsere weiteren Projekte nützlich sein.
Die Funktionen, die die Beschreibungen der Felder der Struktur MqlDateTime zurückgeben, müssen das Format vom Artikel „StringFormat() Beurteilung und fertige Beispiele“ verwenden. Jede Zeile, die von der Funktion zurückgegeben wird, hat eine Kopfzeile und Daten. Die Kopfzeile kann vom linken Rand aus eingerückt werden und kann eine Breite für die tabellarische Ansicht des zurückgegebenen Datensatzes erhalten. Wir werden die Werte für Einrückung und Breite als Parameter an die Funktionen übergeben. Die Standardwerte für diese Optionen sind Null, d. h. keine Zuweisung, und eine Breite, die der Länge des Kopfzeilentextes + 1 entspricht.
Das Jahr in der Struktur MqlDateTime:
//+------------------------------------------------------------------+ //| Return the year as a string from MqlDateTime | //+------------------------------------------------------------------+ string MqlDateTimeYear(MqlDateTime &date_time,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Year:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-lu",indent,"",w,header,date_time.year); /* Sample output: Year: 2023 */ }
Der Monat in der Struktur MqlDateTime:
//+------------------------------------------------------------------+ //| Return the month as a string from MqlDateTime | //+------------------------------------------------------------------+ string MqlDateTimeMonth(MqlDateTime &date_time,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Month:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get a month name string mn=Month(date_time); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%02lu (%s)",indent,"",w,header,date_time.mon,mn); /* Sample output: Month: 07 (July) */ }
Der Tag in der Struktur MqlDateTime:
//+------------------------------------------------------------------+ //| Return the day as a string from the MqlDateTime structure | //+------------------------------------------------------------------+ string MqlDateTimeDay(MqlDateTime &date_time,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Day:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%02lu",indent,"",w,header,date_time.day); /* Sample output: Day: 19 */ }
Stunden in der Struktur MqlDateTime:
//+------------------------------------------------------------------+ //| Return hours as a string from the MqlDateTime structure | //+------------------------------------------------------------------+ string MqlDateTimeHour(MqlDateTime &date_time,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Hour:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%02lu",indent,"",w,header,date_time.hour); /* Sample output: Hour: 08 */ }
Minuten in der Struktur MqlDateTime:
//+------------------------------------------------------------------+ //| Return minutes as a string from MqlDateTime | //+------------------------------------------------------------------+ string MqlDateTimeMin(MqlDateTime &date_time,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Minutes:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%02lu",indent,"",w,header,date_time.min); /* Sample output: Minutes: 41 */ }
Sekunden in der Struktur MqlDateTime:
//+------------------------------------------------------------------+ //| Return seconds as a string from MqlDateTime | //+------------------------------------------------------------------+ string MqlDateTimeSec(MqlDateTime &date_time,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Seconds:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%02lu",indent,"",w,header,date_time.sec); /* Sample output: Seconds: 23 */ }
Der Wochentag in der Struktur MqlDateTime:
//+------------------------------------------------------------------+ //| Return a week day as a string from the MqlDateTime structure | //+------------------------------------------------------------------+ string MqlDateTimeDayWeek(MqlDateTime &date_time,const uint header_width=0,const uint indent=0,bool descr=true) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Day of week:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get a week day name string dw=DayWeek(date_time); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s (%-lu)",indent,"",w,header,dw,date_time.day_of_week); /* Sample output: Day of week: Wednesday (3) */ }
Die Nummer eines Tages in einem Jahr in der Struktur MqlDateTime:
//+------------------------------------------------------------------+ //|Return a number of a day in a year from MqlDateTime | //+------------------------------------------------------------------+ string MqlDateTimeDayYear(MqlDateTime &date_time,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Day of year:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-lu",indent,"",w,header,date_time.day_of_year); /* Sample output: Day of year: 199 */ }
Anwendungsbeispiele:
Um einen kurzen Datensatz der Datumszeit aus der MqlDateTime-Struktur anzuzeigen, schreiben wir eine Funktion, die das Datum im Format „DW, Monat DD, YYYY, HH:MM:SS“ zurückgibt:
//+------------------------------------------------------------------+ //| Return the date as a string from the MqlDateTime structure | //| in the DW, Month DD, YYYY, HH:MM:SS format | //+------------------------------------------------------------------+ string DateTime(MqlDateTime &date_time) { //--- Get the month and the first three characters of a week day string mn=Month(date_time); string dw=StringSubstr(DayWeek(date_time),0,3); //--- Return a string in the DW, Month DD, YYYY, HH:MM:SS format return StringFormat("%s, %s %02lu, %lu, %02lu:%02lu:%02lu",dw,mn,date_time.day,date_time.year,date_time.hour,date_time.min,date_time.sec); /* Sample output: Wed, July 19, 2023, 08:41:23 */ }
Dies ist eine einzeilige Zusammenfassung aller Strukturdaten mit Ausnahme der Tageszahl des Jahres. Die Funktion ist z.B. praktisch, um eine bestimmte Anzahl von Balken im Journal anzuzeigen:
void OnStart() { datetime array[]; MqlDateTime adt[]; if(CopyTime(Symbol(),PERIOD_CURRENT,0,10,array)==10) { int total=(int)array.Size(); if(ArrayResize(adt,total)==total) { for(int i=0;i<total;i++) { ResetLastError(); if(!TimeToStruct(array[i],adt[i])) Print("TimeToStruct failed. Error: ",GetLastError()); PrintFormat("%s %s [%02u] %s",Symbol(),StringSubstr(EnumToString(Period()),7),i,DateTime(adt[i])); } } } /* Sample output: GBPUSD H1 [00] Wed, July 19, 2023, 02:00:00 GBPUSD H1 [01] Wed, July 19, 2023, 03:00:00 GBPUSD H1 [02] Wed, July 19, 2023, 04:00:00 GBPUSD H1 [03] Wed, July 19, 2023, 05:00:00 GBPUSD H1 [04] Wed, July 19, 2023, 06:00:00 GBPUSD H1 [05] Wed, July 19, 2023, 07:00:00 GBPUSD H1 [06] Wed, July 19, 2023, 08:00:00 GBPUSD H1 [07] Wed, July 19, 2023, 09:00:00 GBPUSD H1 [08] Wed, July 19, 2023, 10:00:00 GBPUSD H1 [09] Wed, July 19, 2023, 11:00:00 */ }
Implementieren wir die folgende Funktion, um alle Felder der Struktur in kurzen und tabellarischen Formaten zu protokollieren:
//+------------------------------------------------------------------+ //| Logs descriptions of all fields of the MqlDateTime structure | //+------------------------------------------------------------------+ void MqlDateTimePrint(MqlDateTime &date_time,const bool short_entry=true,const uint header_width=0,const uint indent=0) { //--- If it is a short entry, log the date and time in the DW, Month DD, YYYY, HH:MM:SS format if(short_entry) Print(DateTime(date_time)); /* Sample output: Wed, July 19, 2023, 08:41:23 */ //--- Otherwise else { //--- create a string describing all the data of the structure with indents and a given width of the header field string res=StringFormat("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", MqlDateTimeYear(date_time,header_width,indent), MqlDateTimeMonth(date_time,header_width,indent), MqlDateTimeDay(date_time,header_width,indent), MqlDateTimeHour(date_time,header_width,indent), MqlDateTimeMin(date_time,header_width,indent), MqlDateTimeSec(date_time,header_width,indent), MqlDateTimeDayWeek(date_time,header_width,indent), MqlDateTimeDayYear(date_time,header_width,indent) ); //--- Display the obtained string in the journal Print(res); } /* Sample output: Year: 2023 Month: 07 (July) Day: 19 Hour: 09 Minutes: 32 Seconds: 25 Day of week: Wednesday (3) Day of year: 199 */ }
Ein Skript mit einem Beispiel für die Verwendung der Funktion. Es zeig zunächst einen kurzen Eintrag im Journal an, gefolgt von der tabellarischen Form mit eingerückten Feldüberschriften und Feldbreiten von 2 bzw. 14 Zeichen:
void OnStart() { MqlDateTime dt; TimeCurrent(dt); MqlDateTimePrint(dt,true); MqlDateTimePrint(dt,false,14,2); /* Sample output: Wed, July 19, 2023, 09:33:56 Year: 2023 Month: 07 (July) Day: 19 Hour: 09 Minutes: 33 Seconds: 56 Day of week: Wednesday (3) Day of year: 199 */ }
Alle oben vorgestellten Funktionen für die Arbeit mit Feldern der MqlDateTime-Struktur und mit Hilfsfeldern können in Ihren Programmen „so wie sie sind“ verwendet oder nach Ihren Vorstellungen und Bedürfnissen verändert werden.
Die Struktur MqlTick
Struktur zur Speicherung der letzten Preise nach Symbolen. Die Struktur ist so konzipiert, dass die am meisten benötigten Daten über die aktuellen Preise zeitnah zur Verfügung stehen.
struct MqlTick { datetime time; // Last price update time double bid; // Current Bid price double ask; // Current Ask price double last; // Current price of the last trade (Last) ulong volume; // Volume for the current Last price long time_msc; // Last price update time in milliseconds uint flags; // Tick flags double volume_real; // Volume for the current Last price };
Eine Variable vom Typ MqlTick ermöglicht es, Ask-, Bid-, Last- und Volume-Werte sowie die Zeit in Millisekunden mit einem Aufruf der Funktion SymbolInfoTick() abzufragen.
Die Parameter jedes Ticks werden unabhängig davon ausgefüllt, ob es Änderungen gegenüber dem vorherigen Tick gibt. Auf diese Weise ist es möglich, einen korrekten Preis für einen beliebigen Zeitpunkt in der Vergangenheit zu ermitteln, ohne dass man in der Tick-Historie nach früheren Werten suchen muss. Selbst wenn sich beispielsweise nur der Bid während einer Tickankunft ändert, enthält die Struktur noch andere Parameter, darunter den vorherigen Ask, das Volumen usw.
Analyse der Ticks, um festzustellen, welche Daten sich geändert haben:
- TICK_FLAG_BID — der Tick hat den Geldkurs verändert
- TICK_FLAG_ASK — der Tick hat den Briefkurs verändert
- TICK_FLAG_LAST — der Tick hat den Preis des letzten Geschäfts geändert
- TICK_FLAG_VOLUME — der Tick hat das Volumen verändert
- TICK_FLAG_BUY — der Tick ist das Ergebnis eines Kaufgeschäfts
- TICK_FLAG_SELL — der Tick ist das Ergebnis eines Verkaufsgeschäfts
Druckmethoden für MqlTick
Die Funktion ArrayPrint() ist geeignet, die Struktur im Journal auf die gleiche Weise wie bei MqlDateTime darzustellen:
void OnStart() { //--- Declare a variable with the MqlTick type MqlTick tick; //--- If failed to get the last tick, display the error message and exit the method if(!SymbolInfoTick(Symbol(),tick)) { Print("SymbolInfoTick failed, error: ",(string)GetLastError()); return; } //--- Display the tick using standard ArrayPrint() //--- To do this, declare an array of dimension 1 with type MqlTick, //--- enter the value of the 'tick' variable into it and print it MqlTick array[1]; array[0]=tick; Print("Last tick (ArrayPrint):"); ArrayPrint(array); /* Sample output: Last tick (ArrayPrint): [time] [bid] [ask] [last] [volume] [time_msc] [flags] [volume_real] [0] 2023.07.19 17:02:49 1.28992 1.28996 0.0000 0 1689786169589 6 0.00000 */ }
Es ist logisch, dass man zum Drucken eines Arrays das Array mit einem Bereich von Ticks füllen kann:
void OnStart() { //--- Declare a dynamic array of the MqlTick type MqlTick array[]; //--- If failed to get the last 10 ticks, display the error message and exit the method if(CopyTicks(Symbol(),array,COPY_TICKS_ALL,0,10)!=10) { Print("CopyTicks failed, error: ",(string)GetLastError()); return; } Print("Last 10 tick (ArrayPrint):"); ArrayPrint(array); /* Sample output: Last 10 tick (ArrayPrint): [time] [bid] [ask] [last] [volume] [time_msc] [flags] [volume_real] [0] 2023.07.19 17:24:38 1.28804 1.28808 0.0000 0 1689787478461 6 0.00000 [1] 2023.07.19 17:24:38 1.28806 1.28810 0.0000 0 1689787478602 6 0.00000 [2] 2023.07.19 17:24:38 1.28804 1.28808 0.0000 0 1689787478932 6 0.00000 [3] 2023.07.19 17:24:39 1.28806 1.28810 0.0000 0 1689787479210 6 0.00000 [4] 2023.07.19 17:24:39 1.28807 1.28811 0.0000 0 1689787479765 6 0.00000 [5] 2023.07.19 17:24:39 1.28808 1.28812 0.0000 0 1689787479801 6 0.00000 [6] 2023.07.19 17:24:40 1.28809 1.28813 0.0000 0 1689787480240 6 0.00000 [7] 2023.07.19 17:24:40 1.28807 1.28811 0.0000 0 1689787480288 6 0.00000 [8] 2023.07.19 17:24:40 1.28809 1.28813 0.0000 0 1689787480369 6 0.00000 [9] 2023.07.19 17:24:40 1.28810 1.28814 0.0000 0 1689787480399 6 0.00000 */ }
Auch hier brauchen wir eine aussagekräftigere Darstellung der Werte. Zum Beispiel die Zeit in Millisekunden und Flags. Es ist wahrscheinlich bequemer, sie auf die übliche Weise zu sehen - die Zeit im Zeitformat und die Flags im Format von Enumerationswerte.
Funktionen für die Arbeit mit MqlTick-Strukturdaten.
Implementieren wir die Funktionen für die Arbeit mit MqlTick-Strukturdaten. Genau wie alle bereits erstellten Funktionen für die Arbeit mit der MqlDateTime-Struktur geben auch die Funktionen für die Arbeit mit MqlTick einen formatierten String zurück. Das Zeilenformat umfasst den linken Rand des Textes und die Breite des Header-Feldes. Standardmäßig sind die Werte für Auffüllung und Randbreite gleich Null, d. h. es gibt keine Zuweisungen und die Randbreite ist gleich der Länge des Kopfzeilentextes + 1.
Zusatzfunktionen
Wir haben diese Funktion bereits erstellt, um die Zeit in Millisekunden als String zurückzugeben. Hier ist es nützlich, um die Tickzeit in Millisekunden zurückzugeben. Wenden wir es an:
//+------------------------------------------------------------------+ //| Accept a date in ms, return time in Date Time.Msc format | //+------------------------------------------------------------------+ string TimeMSC(const long time_msc) { return StringFormat("%s.%.3hu",string((datetime)time_msc / 1000),time_msc % 1000); /* Sample output: 2023.07.13 09:31:58.177 */ }
Zeit in der MqlTick-Struktur:
//+------------------------------------------------------------------+ //| Return the time of the last price update as a string | //+------------------------------------------------------------------+ string MqlTickTime(const MqlTick &tick,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Time:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,(string)tick.time); /* Sample output: Time: 2023.07.19 20:58:00 */ }
Geldkurs (Bid) in der MqlTick-Struktur:
//+------------------------------------------------------------------+ //| Return the Bid price as a string | //+------------------------------------------------------------------+ string MqlTickBid(const string symbol,const MqlTick &tick,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Bid:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,tick.bid); /* Sample output: Bid: 1.29237 */ }
Briefkurs (Ask) in der MqlTick-Struktur:
//+------------------------------------------------------------------+ //| Return the Ask price as a string | //+------------------------------------------------------------------+ string MqlTickAsk(const string symbol,const MqlTick &tick,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Ask:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,tick.ask); /* Sample output: Ask: 1.29231 */ }
Letzter Handelskurs in der MqlTick-Struktur:
//+------------------------------------------------------------------+ //| Return the Last price as a string | //+------------------------------------------------------------------+ string MqlTickLast(const string symbol,const MqlTick &tick,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Last:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,tick.last); /* Sample output: Last: 0.00000 */ }
Letztes Preisvolumen in der MqlTick-Struktur:
//+------------------------------------------------------------------+ //| Return the volume for the Last price as a string | //+------------------------------------------------------------------+ string MqlTickVolume(const MqlTick &tick,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Volume:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-I64u",indent,"",w,header,tick.volume); /* Sample output: Volume: 0 */ }
Zeit in Millisekunden in der Struktur MqlTick:
//+------------------------------------------------------------------+ //| Return the time in milliseconds as a string | //+------------------------------------------------------------------+ string MqlTickTimeMSC(const MqlTick &tick,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Time msc:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,TimeMSC(tick.time_msc)); /* Sample output: Time msc: 2023.07.19 21:21:09.732 */ }
Tick-Flags in der MqlTick-Struktur:
//+------------------------------------------------------------------+ //| Return tick flags as a string | //+------------------------------------------------------------------+ string MqlTickFlags(const MqlTick &tick,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Flags:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Define a variable to describe tick flags string flags=""; //--- Parse tick flags into components if((tick.flags & TICK_FLAG_BID)==TICK_FLAG_BID) flags+=(flags.Length()>0 ? "|" : "")+"BID"; if((tick.flags & TICK_FLAG_ASK)==TICK_FLAG_ASK) flags+=(flags.Length()>0 ? "|" : "")+"ASK"; if((tick.flags & TICK_FLAG_LAST)==TICK_FLAG_LAST) flags+=(flags.Length()>0 ? "|" : "")+"LAST"; if((tick.flags & TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME) flags+=(flags.Length()>0 ? "|" : "")+"VOLUME"; if((tick.flags & TICK_FLAG_BUY)==TICK_FLAG_BUY) flags+=(flags.Length()>0 ? "|" : "")+"BUY"; if((tick.flags & TICK_FLAG_SELL)==TICK_FLAG_SELL) flags+=(flags.Length()>0 ? "|" : "")+"SELL"; //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,flags); /* Sample output: Flags: BID|ASK */ }
Letztes Preisvolumen mit erhöhter Genauigkeit in der MqlTick-Struktur:
//+------------------------------------------------------------------+ //| Return the volume for the Last price as a string | //+------------------------------------------------------------------+ string MqlTickVolumeReal(const MqlTick &tick,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Volume Real:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.2f",indent,"",w,header,tick.volume_real); /* Sample output: Volume Real: 0.00 */ }
Beispiele für die Verwendung
Schreiben wir die Funktion zur Anzeige von Tickdaten im Journal. Wir übergeben den Namen des Symbols an die Funktion, um zu wissen, mit welcher Genauigkeit die Kurswerte im Journal angezeigt werden sollen. Da die Felder Volume und Volume Real die Volumina des Last-Preises enthalten, macht es keinen Sinn, die Volumina anzuzeigen, wenn Last Null ist (nicht umgerechnet) - sie sind ebenfalls Null. Um den Index eines Ticks aus einem Array von Ticks angeben und drucken zu können, übergeben wir diesen Index in den Eingabeparametern der Funktion. Standardmäßig ist sein Wert -1, und bei diesem Wert wird der Index nicht gedruckt.
//+------------------------------------------------------------------+ //| Logs descriptions of all fields of the MqlTick structure | //| If Last==0, Last, Volume and Volume Real fields are not displayed| //+------------------------------------------------------------------+ void MqlTickPrint(const string symbol,const MqlTick &tick,const bool short_entry=true,const uint header_width=0,const uint indent=0,int index=WRONG_VALUE) { //--- Declare the variable for storing the result string res=""; //--- Get the number of decimal places int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); string num=(index==WRONG_VALUE ? "" : StringFormat("[%ld] ",index)); //--- If it is a short entry, log the tick data in the Symbol TimeMSC, Bid, Ask, Last, Vol/VolR, Flags format if(short_entry) { //--- If Last is not zero, display Last, Volume and Volume Real, otherwise they are all zero and there is no point in displaying them string last=(tick.last!=0 ? StringFormat(", Last: %.*f, Vol: %I64u/%.2f",dg,tick.last,tick.volume,tick.volume_real) : ""); res=StringFormat("%sTick %s Time: %s, Bid: %.*f, Ask: %.*f%s, %s",num,symbol,TimeMSC(tick.time_msc),dg,tick.bid,dg,tick.ask,last,MqlTickFlags(tick)); Print(res); } /* Sample output (if Last is not zero): Tick GBPUSD Time: 2023.07.20 13:57:31.376, Bid: 1.28947, Ask: 1.28951, Last: 1.28947, Vol: 33/33.45, Flags: BID|ASK Sample output (if Last is zero): Tick GBPUSD Time: 2023.07.20 13:59:33.274, Bid: 1.28956, Ask: 1.28960, Flags: BID|ASK */ //--- Otherwise else { //--- create a string describing all the data of the structure with indents and a given width of the header field res=StringFormat("%s\n%s\n%s%s%s\n%s\n%s%s", MqlTickTime(tick,header_width,indent), MqlTickBid(symbol,tick,header_width,indent), MqlTickAsk(symbol,tick,header_width,indent), (tick.last!=0 ? "\n"+MqlTickLast(symbol,tick,header_width,indent) : ""), (tick.last!=0 ? "\n"+MqlTickVolume(tick,header_width,indent) : ""), MqlTickTimeMSC(tick,header_width,indent), MqlTickFlags(tick,header_width,indent), (tick.last!=0 ? "\n"+MqlTickVolumeReal(tick,header_width,indent) : "") ); //--- Display the obtained string in the journal Print(res); } /* Sample output (if Last is not zero): Time: 2023.07.20 14:42:33 Bid: 1.28958 Ask: 1.28962 Last: 1.28947 Volume: 33 Time msc: 2023.07.20 14:42:33.401 Flags: BID|ASK Volume Real: 33.45 Sample output (if Last is zero): Time: 2023.07.20 14:42:33 Bid: 1.28958 Ask: 1.28962 Time msc: 2023.07.20 14:42:33.401 Flags: BID|ASK */ }
Ein Skript, das die letzten 10 Ticks in Kurzform in das Journal druckt und dabei die Tick-Indizes aus dem Array angibt:
void OnStart() { //--- Declare a dynamic array of the MqlTick type MqlTick array[]; //--- If failed to get the last 10 ticks, display the error message and exit the method if(CopyTicks(Symbol(),array,COPY_TICKS_ALL,0,10)!=10) { Print("CopyTicks failed, error: ",(string)GetLastError()); return; } Print("Last 10 tick (MqlTickPrint):"); for(int i=0;i<(int)array.Size();i++) MqlTickPrint(Symbol(),array[i],true,0,0,i); /* Sample output: Last 10 tick (MqlTickPrint): [0] Tick GBPUSD Time: 2023.07.20 15:36:29.941, Bid: 1.28686, Ask: 1.28690, Flags: BID|ASK [1] Tick GBPUSD Time: 2023.07.20 15:36:29.970, Bid: 1.28688, Ask: 1.28692, Flags: BID|ASK [2] Tick GBPUSD Time: 2023.07.20 15:36:30.061, Bid: 1.28689, Ask: 1.28693, Flags: BID|ASK [3] Tick GBPUSD Time: 2023.07.20 15:36:30.212, Bid: 1.28688, Ask: 1.28692, Flags: BID|ASK [4] Tick GBPUSD Time: 2023.07.20 15:36:30.259, Bid: 1.28689, Ask: 1.28693, Flags: BID|ASK [5] Tick GBPUSD Time: 2023.07.20 15:36:30.467, Bid: 1.28682, Ask: 1.28686, Flags: BID|ASK [6] Tick GBPUSD Time: 2023.07.20 15:36:30.522, Bid: 1.28681, Ask: 1.28685, Flags: BID|ASK [7] Tick GBPUSD Time: 2023.07.20 15:36:30.572, Bid: 1.28673, Ask: 1.28677, Flags: BID|ASK [8] Tick GBPUSD Time: 2023.07.20 15:36:30.574, Bid: 1.28672, Ask: 1.28676, Flags: BID|ASK [9] Tick GBPUSD Time: 2023.07.20 15:36:30.669, Bid: 1.28674, Ask: 1.28678, Flags: BID|ASK */ }
Ein Skript, das die letzten 4 Ticks aus einem Array im Protokoll mit einem linken Einzug von 2 Zeichen und einer Kopffeldbreite von 14 Zeichen ausgibt:
void OnStart() { //--- Declare a dynamic array of the MqlTick type MqlTick array[]; //--- If the last 4 ticks are not received in the array, display an error message and leave if(CopyTicks(Symbol(),array,COPY_TICKS_ALL,0,4)!=4) { Print("CopyTicks failed, error: ",(string)GetLastError()); return; } Print("Last 4 tick (MqlTickPrint):"); for(int i=0;i<(int)array.Size();i++) { PrintFormat("Tick[%lu] %s:",i,Symbol()); MqlTickPrint(Symbol(),array[i],false,14,2); } /* Sample output: Last 4 tick (MqlTickPrint): Tick[0] GBPUSD: Time: 2023.07.20 17:04:51 Bid: 1.28776 Ask: 1.28780 Time msc: 2023.07.20 17:04:51.203 Flags: BID|ASK Tick[1] GBPUSD: Time: 2023.07.20 17:04:51 Bid: 1.28772 Ask: 1.28776 Time msc: 2023.07.20 17:04:51.331 Flags: BID|ASK Tick[2] GBPUSD: Time: 2023.07.20 17:04:51 Bid: 1.28771 Ask: 1.28775 Time msc: 2023.07.20 17:04:51.378 Flags: BID|ASK Tick[3] GBPUSD: Time: 2023.07.20 17:04:51 Bid: 1.28772 Ask: 1.28776 Time msc: 2023.07.20 17:04:51.680 Flags: BID|ASK */ }
Die Struktur MqlRates
Struktur zur Speicherung von Informationen über Preise, Volumen und Spread.
struct MqlRates { datetime time; // period start time double open; // open price double high; // high price for the period double low; // low price for the period double close; // close price long tick_volume; // tick volume int spread; // spread long real_volume; // exchange volume };
Druckmethoden für MqlRates
MqlRates — Struktur zur Speicherung von Daten über einen einzelnen Balken historischer Daten. Die Struktur kann mit der Funktion CopyRates() gefüllt werden. Um die Daten des aktuellen Balkens zu erhalten, können wir die erste Form des Funktionsaufrufs verwenden, wobei wir den Index 0 und die Anzahl der kopierten Balken gleich 1 angeben. In jedem Fall füllt diese Funktion ein Array mit dem Typ MqlRates. Daraus ergibt sich die Schlussfolgerung, dass es praktisch ist, dieses Array mit ArrayPrint() in das Journal zu drucken:
void OnStart() { //--- MqlRates array[]; if(CopyRates(Symbol(),PERIOD_CURRENT,0,1,array)!=1) { Print("CopyRates failed, error: ",(string)GetLastError()); return; } Print("Current bar ",Symbol()," ",StringSubstr(EnumToString(Period()),7)," (ArrayPrint):"); ArrayPrint(array); /* Sample output: Current bar GBPUSD H1 (ArrayPrint): [time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume] [0] 2023.07.21 04:00:00 1.28763 1.28765 1.28663 1.28748 2083 7 0 */ }
Um die letzten zehn Balken zu kopieren, müssen wir also nur die Anzahl der zu kopierenden Daten mit 10 angeben:
void OnStart() { //--- MqlRates array[]; if(CopyRates(Symbol(),PERIOD_CURRENT,0,10,array)!=10) { Print("CopyRates failed, error: ",(string)GetLastError()); return; } Print("Data of the last 10 bars: ",Symbol()," ",StringSubstr(EnumToString(Period()),7)," (ArrayPrint):"); ArrayPrint(array); /* Sample output: Data of the last 10 bars: GBPUSD H1 (ArrayPrint): [time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume] [0] 2023.07.20 20:00:00 1.28530 1.28676 1.28512 1.28641 2699 4 0 [1] 2023.07.20 21:00:00 1.28641 1.28652 1.28557 1.28587 1726 3 0 [2] 2023.07.20 22:00:00 1.28587 1.28681 1.28572 1.28648 2432 3 0 [3] 2023.07.20 23:00:00 1.28648 1.28683 1.28632 1.28665 768 4 0 [4] 2023.07.21 00:00:00 1.28663 1.28685 1.28613 1.28682 396 1 0 [5] 2023.07.21 01:00:00 1.28684 1.28732 1.28680 1.28714 543 8 0 [6] 2023.07.21 02:00:00 1.28714 1.28740 1.28690 1.28721 814 2 0 [7] 2023.07.21 03:00:00 1.28721 1.28774 1.28685 1.28761 2058 5 0 [8] 2023.07.21 04:00:00 1.28763 1.28791 1.28663 1.28774 3480 7 0 [9] 2023.07.21 05:00:00 1.28774 1.28776 1.28769 1.28774 18 7 0 */ }
Hier ist alles gleich — es gibt eine lange Liste von Daten im Journal. Wenn der Tabellenkopf hinter dem oberen Rand des Journals verborgen ist, ist nicht klar, worauf sich die dargestellten Zahlen beziehen.
Schreiben wir unsere eigenen Funktionen, um Beschreibungen der Strukturfelder zurückzugeben und diese Daten im Terminaljournal zu drucken.
Funktionen für die Arbeit mit MqlRates-Strukturdaten.
Unsere nutzerdefinierten Funktionen geben eine Textbeschreibung für jedes Feld in der Struktur zurück. Jede Beschreibung besteht aus einer Überschrift und den eigentlichen Daten. Für die von der Funktion zurückgegebene Zeichenkette können wir den Einzug vom linken Rand und die Breite des Kopffelds festlegen.
Zeit:
Zeit — Startzeit des Zeitraums. Mit anderen Worten, die Öffnungszeit des Balkens auf dem Symbol und der Zeitrahmen des Charts, aus der die in die Struktur geschriebenen Daten angefordert wurden.
//+------------------------------------------------------------------+ //| Return the bar opening time as a string | //+------------------------------------------------------------------+ string MqlRatesTime(const MqlRates &rates,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Time:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,(string)rates.time); /* Sample output: Time: 2023.07.21 06:00:00 */ }
Open:
Der Eröffnungskurs des Balkens für das Symbol und der Zeitrahmen des Charts, aus der die in die Struktur geschriebenen Daten angefordert wurden.
//+------------------------------------------------------------------+ //| Return the bar open price as a string | //+------------------------------------------------------------------+ string MqlRatesOpen(const string symbol,const MqlRates &rates,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Open:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,rates.open); /* Sample output: Open: 1.28812 */ }
High:
Höchstpreis - der höchste Preis des Balkens auf dem Symbol und der Zeitrahmen des Charts, von dem die in die Struktur geschriebenen Daten angefordert wurden.
//+------------------------------------------------------------------+ //| Return the High bar price as a string | //+------------------------------------------------------------------+ string MqlRatesHigh(const string symbol,const MqlRates &rates,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="High:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,rates.high); /* Sample output: High: 1.28859 */ }
Low:
Niedriger Preis - der niedrigste Preis des Balkens auf dem Symbol und der Chart-Periode, von dem die in die Struktur geschriebenen Daten angefordert wurden.
//+------------------------------------------------------------------+ //| Return the bar Low price as a string | //+------------------------------------------------------------------+ string MqlRatesLow(const string symbol,const MqlRates &rates,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Low:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,rates.low); /* Sample output: Low: 1.28757 */ }
Close:
Schlusskurs — der Schlusskurs des Balkens für das Symbol und die Chart-Periode, von dem die in die Struktur geschriebenen Daten angefordert wurden.
Für den aktuellen Balken ist der Schlusskurs gleich dem aktuellen Geld- oder Briefkurs, je nachdem, auf welchem Kurs das Chart basiert.
//+------------------------------------------------------------------+ //| Return the bar close price as a string | //+------------------------------------------------------------------+ string MqlRatesClose(const string symbol,const MqlRates &rates,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Close:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,rates.close); /* Sample output: Close: 1.28770 */ }
TickVolume:
Das Tick Volumen des Balkens.
//+------------------------------------------------------------------+ //| Return the tick volume of a bar as a string | //+------------------------------------------------------------------+ string MqlRatesTickVolume(const MqlRates &rates,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Tick Volume:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-lld",indent,"",w,header,rates.tick_volume); /* Sample output: Tick Volume: 963 */ }
Spread:
Spreizung des Balkens.
//+------------------------------------------------------------------+ //| Return the bar spread as a string | //+------------------------------------------------------------------+ string MqlRatesSpread(const MqlRates &rates,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Spread:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-ld",indent,"",w,header,rates.spread); /* Sample output: Spread: 4 */ }
RealVolume:
Das Volumen innerhalb des Balkens.
//+------------------------------------------------------------------+ //| Return the bar exchange volume as a string | //+------------------------------------------------------------------+ string MqlRatesRealVolume(const MqlRates &rates,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Real Volume:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-lld",indent,"",w,header,rates.real_volume); /* Sample output: Real Volume: 0 */ }
Beispiele für die Verwendung
Erstellen wir das folgende Skript, um die Daten der letzten 10 Balken im Journal zu drucken:
void OnStart() { //--- Copy the last 10 data bars to the MqlRates array MqlRates array[]; if(CopyRates(Symbol(),PERIOD_CURRENT,0,10,array)!=10) { Print("CopyRates failed, error: ",(string)GetLastError()); return; } //--- Set the indexing of the array like a timeseries ArraySetAsSeries(array,true); //--- Print short entries in the journal in a loop through the array with the received bar data for(int i=0;i<(int)array.Size();i++) MqlRatesPrint(Symbol(),PERIOD_CURRENT,array[i],true,0,0,i); /* Sample output: GBPUSD H1[0]: 2023.07.21 14:00:00, O: 1.28451, H: 1.28541, L: 1.28451, C: 1.28501, S: 4, V: 821, RV: 0 GBPUSD H1[1]: 2023.07.21 13:00:00, O: 1.28678, H: 1.28685, L: 1.28418, C: 1.28452, S: 1, V: 3602, RV: 0 GBPUSD H1[2]: 2023.07.21 12:00:00, O: 1.28581, H: 1.28696, L: 1.28557, C: 1.28678, S: 1, V: 4807, RV: 0 GBPUSD H1[3]: 2023.07.21 11:00:00, O: 1.28695, H: 1.28745, L: 1.28401, C: 1.28581, S: 1, V: 7440, RV: 0 GBPUSD H1[4]: 2023.07.21 10:00:00, O: 1.28933, H: 1.28960, L: 1.28651, C: 1.28696, S: 1, V: 8883, RV: 0 GBPUSD H1[5]: 2023.07.21 09:00:00, O: 1.28788, H: 1.29040, L: 1.28753, C: 1.28934, S: 1, V: 5474, RV: 0 GBPUSD H1[6]: 2023.07.21 08:00:00, O: 1.28794, H: 1.28848, L: 1.28713, C: 1.28787, S: 1, V: 1885, RV: 0 GBPUSD H1[7]: 2023.07.21 07:00:00, O: 1.28762, H: 1.28808, L: 1.28744, C: 1.28794, S: 4, V: 878, RV: 0 GBPUSD H1[8]: 2023.07.21 06:00:00, O: 1.28812, H: 1.28859, L: 1.28743, C: 1.28760, S: 3, V: 1112, RV: 0 GBPUSD H1[9]: 2023.07.21 05:00:00, O: 1.28774, H: 1.28820, L: 1.28747, C: 1.28812, S: 7, V: 1671, RV: 0 */ }
Nachdem wir die erforderliche Datenmenge in das Array kopiert haben, indexieren wir es wie eine Zeitreihe, sodass die Daten wie Chart-Balken im Terminal angezeigt werden. Daten mit einem Null-Index entsprechen dem aktuellen Balken.
Dieses Skript druckt die letzten 4 Balken in das Journal in tabellarischer Form aus, wobei das Kopfzeilenfeld um zwei Zeichen nach links eingerückt ist und die Breite des Titelfeldes 14 Zeichen beträgt:
void OnStart() { //--- Copy the last 4 data bars to the MqlRates array MqlRates array[]; if(CopyRates(Symbol(),PERIOD_CURRENT,0,4,array)!=4) { Print("CopyRates failed, error: ",(string)GetLastError()); return; } //--- Set the indexing of the array like a timeseries ArraySetAsSeries(array,true); //--- Print short entries in the journal in a loop through the array with the received bar data for(int i=0;i<(int)array.Size();i++) MqlRatesPrint(Symbol(),PERIOD_CURRENT,array[i],false,14,2,i); /* Sample output: GBPUSD H1[0]: Time: 2023.07.21 14:00:00 Open: 1.28451 High: 1.28541 Low: 1.28451 Close: 1.28491 Tick Volume: 1098 Spread: 4 Real Volume: 0 GBPUSD H1[1]: Time: 2023.07.21 13:00:00 Open: 1.28678 High: 1.28685 Low: 1.28418 Close: 1.28452 Tick Volume: 3602 Spread: 1 Real Volume: 0 GBPUSD H1[2]: Time: 2023.07.21 12:00:00 Open: 1.28581 High: 1.28696 Low: 1.28557 Close: 1.28678 Tick Volume: 4807 Spread: 1 Real Volume: 0 GBPUSD H1[3]: Time: 2023.07.21 11:00:00 Open: 1.28695 High: 1.28745 Low: 1.28401 Close: 1.28581 Tick Volume: 7440 Spread: 1 Real Volume: 0 */ }
Die Struktur MqlBookInfo
Eine Struktur, die die Daten zur Markttiefe liefert.
struct MqlBookInfo { ENUM_BOOK_TYPE type; // order type from ENUM_BOOK_TYPE enumeration double price; // price long volume; // volume double volume_real; // volume with increased accuracy };
Um die Struktur zu verwenden, genügt es, eine Variable dieses Typs zu deklarieren. Die Markttiefe ist nicht für alle Finanzinstrumente verfügbar. Bevor wir die Daten der Markttiefe erhalten, sollten wir sie mit MarketBookAdd() abonnieren. Nach der Beendigung müssen wir uns von der Markttiefe abmelden: MarketBookRelease(). Das EA-Programm sollte die Funktion OnBookEvent() enthalten, um eingehende Benachrichtigungen zu verarbeiten.
Druckmethoden für MqlBookInfo
Jeder Empfang der Markttiefe beinhaltet den Empfang einer Liste von Aufträgen in diesem Markt. Dies ist ein Datenfeld. Daher können wir mit ArrayPrint() einen Schnappschuss der Markttiefe drucken:
void OnStart() { //--- Declare an array to store a snapshot of the market depth MqlBookInfo array[]; //--- If unable to open the market depth and subscribe to its events, inform of that and leave if(!MarketBookAdd(Symbol())) { Print("MarketBookAdd failed, error: ",(string)GetLastError()); return; } //--- If unable to obtain the market depth entries, inform of that and leave if(!MarketBookGet(Symbol(),array)) { Print("MarketBookGet failed, error: ",(string)GetLastError()); return; } //--- Print the header in the journal and the market depth snapshot from the array below Print("MarketBookInfo by ",Symbol(),":"); ArrayPrint(array); //--- If unable to unsubscribe from the market depth, send an error message to the journal if(!MarketBookRelease(Symbol())) Print("MarketBookRelease failed, error: ",(string)GetLastError()); /* Sample output: MarketBookInfo by GBPUSD: [type] [price] [volume] [volume_real] [0] 1 1.28280 100 100.00000 [1] 1 1.28276 50 50.00000 [2] 1 1.28275 20 20.00000 [3] 1 1.28273 10 10.00000 [4] 2 1.28268 10 10.00000 [5] 2 1.28266 20 20.00000 [6] 2 1.28265 50 50.00000 [7] 2 1.28260 100 100.00000 */ }
Wie Sie sehen können, werden die Arten von Anfragen hier in numerischen Werten ausgedrückt, was für die Wahrnehmung ungünstig ist. Schreiben wir Funktionen, um Beschreibungen der Tiefe von Marktfeldern in der bereits für die anderen oben besprochenen Strukturen akzeptierten Weise zurückzugeben.
Funktionen für die Arbeit mit MqlBookInfo-Strukturdaten.
Alle Funktionen, die eine String-Repräsentation der Felder der MqlBookInfo-Struktur zurückgeben, sind im gleichen Stil wie die oben beschriebenen Funktionen zur Beschreibung der Felder der entsprechenden Strukturen. Wenden wir uns dieser Methoden zu.
Die Auftragsart in der MqlBookInfo-Markttiefenstruktur:
//+------------------------------------------------------------------+ //| Return the order type in the market depth as a string | //+------------------------------------------------------------------+ string MqlBookInfoType(const MqlBookInfo &book,const uint header_width=0,const uint indent=0) { //--- Get the value of the order type ENUM_BOOK_TYPE book_type=book.type; //--- "Cut out" the type from the string obtained from enum string type=StringSubstr(EnumToString(book_type),10); //--- Convert all obtained symbols to lower case and replace the first letter from small to capital if(type.Lower()) type.SetChar(0,ushort(type.GetChar(0)-0x20)); //--- Replace all underscore characters with space in the resulting line StringReplace(type,"_"," "); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Type:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,type); /* Sample output: Type: Sell */ }
Der Auftragspreis in der MqlBookInfo-Markttiefenstruktur:
//+------------------------------------------------------------------+ //| Return the order price in the market depth as a string | //+------------------------------------------------------------------+ string MqlBookInfoPrice(const string symbol,const MqlBookInfo &book,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Price:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,book.price); /* Sample output: Price: 1.28498 */ }
Das Auftragsvolumen in der MqlBookInfo-Markttiefenstruktur:
//+------------------------------------------------------------------+ //| Return the order volume in the market depth as a string | //+------------------------------------------------------------------+ string MqlBookInfoVolume(const MqlBookInfo &book,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Volume:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-lld",indent,"",w,header,book.volume); /* Sample output: Volume: 100 */ }
Das Volumen mit erhöhter Genauigkeit:
//+------------------------------------------------------------------+ //| Return the order volume with increased accuracy as a string | //+------------------------------------------------------------------+ string MqlBookInfoVolumeReal(const MqlBookInfo &book,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Volume Real:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.2f",indent,"",w,header,book.volume_real); /* Sample output: Volume Real: 100.00 */ }
Anwendungsbeispiele:
Nun wollen wir eine Funktion schreiben, die alle Daten in der MqlBookInfo-Struktur in das Journal ausgibt. Es wird möglich sein, sie in zwei Modi zu drucken: in einer Zeile und in Tabellenform:
//+------------------------------------------------------------------+ //| Logs a description of all fields of the MqlRates structure | //+------------------------------------------------------------------+ void MqlBookInfoPrint(const string symbol,const MqlBookInfo &book, const bool short_entry=true,const uint header_width=0,const uint indent=0,int index=WRONG_VALUE) { //--- Declare the variable for storing the result string res=""; //--- Get the number of decimal places and the string index value int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); string num=(index==WRONG_VALUE ? "" : StringFormat("[%02ld]",index)); //--- "Cut out" the type from the order type name string obtained from enum string type=StringSubstr(EnumToString(book.type),10); //--- Convert all obtained symbols to lower case and replace the first letter from small to capital if(type.Lower()) type.SetChar(0,ushort(type.GetChar(0)-0x20)); //--- Replace all underscore characters with space in the resulting line StringReplace(type,"_"," "); //--- If it is a short entry, log the market depth data in the [index] Type Price V VR format if(short_entry) { res=StringFormat("%-8s%-11s%- *.*f Volume%- 5lld Real%- 8.2f", num,type,dg+4,dg,book.price,book.volume,book.volume_real); Print(res); } /* Sample output: [00] Sell 1.28598 Volume 100 Real 100.00 */ //--- Otherwise else { //--- create a string describing all the data of the structure with indents and a given width of the header field res=StringFormat("Market Book by %s %s:\n%s\n%s\n%s\n%s",symbol,num, MqlBookInfoType(book,header_width,indent), MqlBookInfoPrice(symbol,book,header_width,indent), MqlBookInfoVolume(book,header_width,indent), MqlBookInfoVolumeReal(book,header_width,indent) ); //--- Display the obtained string in the journal Print(res); } /* Sample output BoolInfo by GBPUSD [00]: Type: Sell Price: 1.28588 Volume: 100 Volume Real: 100.00 */ }
Der Hauptmodus hier sollte die Ausgabe an das Journal in einer Zeile sein, da die Markttiefe nicht eine einzelne Order ist, und wir eine Liste dieser Orders im Array erhalten. Dementsprechend können wir dieses Array mit der folgenden Funktion in das Journal drucken:
//+----------------------------------------------------------------------+ //| Display the market depth entries in the journal in the short format | //+----------------------------------------------------------------------+ void MqlBookInfoPrintShort(const string symbol,const MqlBookInfo &book_array[]) { PrintFormat("Market Book by %s:",symbol); for(int i=0;i<(int)book_array.Size();i++) MqlBookInfoPrint(symbol,book_array[i],true,0,0,i); }
Die Funktion empfängt ein Array von Aufträgen für die Markttiefe und druckt in einer Schleife durch das Array alle Daten der Markttiefe in das Journal unter Verwendung der Kurzausgabe.
Ein Skript, das die Verwendung dieser Funktion und das Ergebnis demonstriert:
void OnStart() { //--- Declare an array to store a snapshot of the market depth MqlBookInfo array[]; //--- If unable to open the market depth and subscribe to its events, inform of that and leave if(!MarketBookAdd(Symbol())) { Print("MarketBookAdd failed, error: ",(string)GetLastError()); return; } //--- If unable to obtain the market depth entries, inform of that and leave if(!MarketBookGet(Symbol(),array)) { Print("MarketBookGet failed, error: ",(string)GetLastError()); return; } //--- Print in the journal a snapshot of the market depth from the array in the form of strings MqlBookInfoPrintShort(Symbol(),array); //--- If unable to unsubscribe from the market depth, send an error message to the journal if(!MarketBookRelease(Symbol())) Print("MarketBookRelease failed, error: ",(string)GetLastError()); /* Sample output: Market Book by GBPUSD: [00] Sell 1.28674 Volume 100 Real 100.00 [01] Sell 1.28668 Volume 50 Real 50.00 [02] Sell 1.28666 Volume 20 Real 20.00 [03] Sell 1.28664 Volume 10 Real 10.00 [04] Buy 1.28657 Volume 10 Real 10.00 [05] Buy 1.28654 Volume 20 Real 20.00 [06] Buy 1.28653 Volume 50 Real 50.00 [07] Buy 1.28646 Volume 100 Real 100.00 */ }
Aber manchmal müssen wir dieselben Daten auch in Tabellenform anzeigen. Dazu können wir die folgende Funktion verwenden:
//+------------------------------------------------------------------------+ //| Display the market depth entries in the journal in the tabular format | //+------------------------------------------------------------------------+ void MqlBookInfoPrintTable(const string symbol,const MqlBookInfo &book_array[],const uint header_width=0,const uint indent=0) { for(int i=0;i<(int)book_array.Size();i++) MqlBookInfoPrint(symbol,book_array[i],false,header_width,indent,i); }
Ein Skript, das die Verwendung dieser Funktion und das Ergebnis demonstriert:
void OnStart() { //--- Declare an array to store a snapshot of the market depth MqlBookInfo array[]; //--- If unable to open the market depth and subscribe to its events, inform of that and leave if(!MarketBookAdd(Symbol())) { Print("MarketBookAdd failed, error: ",(string)GetLastError()); return; } //--- If unable to obtain the market depth entries, inform of that and leave if(!MarketBookGet(Symbol(),array)) { Print("MarketBookGet failed, error: ",(string)GetLastError()); return; } //--- Print in the journal a snapshot of the market depth from the array in the form of strings MqlBookInfoPrintTable(Symbol(),array,14,2); //--- If unable to unsubscribe from the market depth, send an error message to the journal if(!MarketBookRelease(Symbol())) Print("MarketBookRelease failed, error: ",(string)GetLastError()); /* Sample output: Market Book by GBPUSD [00]: Type: Sell Price: 1.28627 Volume: 100 Volume Real: 100.00 Market Book by GBPUSD [01]: Type: Sell Price: 1.28620 Volume: 50 Volume Real: 50.00 Market Book by GBPUSD [02]: Type: Sell Price: 1.28618 Volume: 20 Volume Real: 20.00 Market Book by GBPUSD [03]: Type: Sell Price: 1.28615 Volume: 10 Volume Real: 10.00 Market Book by GBPUSD [04]: Type: Buy Price: 1.28610 Volume: 10 Volume Real: 10.00 Market Book by GBPUSD [05]: Type: Buy Price: 1.28606 Volume: 20 Volume Real: 20.00 Market Book by GBPUSD [06]: Type: Buy Price: 1.28605 Volume: 50 Volume Real: 50.00 Market Book by GBPUSD [07]: Type: Buy Price: 1.28599 Volume: 100 Volume Real: 100.00 */ }
Schlussfolgerung
Wir haben den Druck der Felder der vier Strukturen berücksichtigt: MqlDateTime, MqlTick, MqlRates und MqlBookInfo. Die erstellten Funktionen geben eine Beschreibung der Felder jeder Struktur im „Header-Data“-Format als String zurück, der gedruckt oder in einer anderen Funktion verwendet werden kann. Alle Funktionen sind eigenständig, sofort einsatzbereit und können in nutzerdefinierten Programmen „so wie sie sind“ verwendet werden. Der nächste Schritt ist die Beschreibung und Darstellung der Handelsstrukturen.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/12900
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.