MQL5 Kochbuch — Datenbank für makroökonomische Ereignisse
Einführung
Dieser Artikel befasst sich mit der Gruppierung und Verwaltung von Daten, die makroökonomische Kalenderereignisse beschreiben.
In der modernen Welt ist der Informationsfluss allgegenwärtig. Bei der Analyse von Ereignissen hat man es also mit großen Datenmengen zu tun. Auch wenn der Artikel in größerem Umfang Fragen behandelt, die nicht den Inhalt, sondern die Form betreffen, so scheint es doch, dass die richtige Organisation und Strukturierung von Daten viel dazu beiträgt, dass diese Daten zu Informationen werden.
Wir werden diese Aufgaben mit Hilfe von SQLite lösen. Der Entwickler hat Unterstützung für den Umgang mit SQLite direkt aus MQL5 build 2265 (6. Dezember 2019) hinzugefügt. Zuvor musste man verschiedene Konnektoren verwenden, wie beschrieben z. B. in dem Artikel SQL und MQL5: Mit der SQLite Datenbank arbeiten.
1. Dokumentation und zusätzliche Materialien
Schauen wir uns die Dokumentation an, insbesondere die Abschnitte über die Handhabung von Datenbanken. Der Entwickler hat 26 Funktionen integriert:
- DatabaseOpen();
- DatabaseClose();
- DatabaseImport();
- DatabaseExport();
- DatabasePrint();
- DatabaseTableExists();
- DatabaseExecute();
- DatabasePrepare();
- DatabaseReset();
- DatabaseBind();
- DatabaseBindArray();
- DatabaseRead();
- DatabaseReadBind();
- DatabaseFinalize();
- DatabaseTransactionBegin();
- DatabaseTransactionCommit();
- DatabaseTransactionRollback();
- DatabaseColumnsCount();
- DatabaseColumnName();
- DatabaseColumnType();
- DatabaseColumnSize();
- DatabaseColumnText();
- DatabaseColumnInteger();
- DatabaseColumnLong();
- DatabaseColumnDouble();
- DatabaseColumnBlob().
Es gibt auch Blöcke mit statistischen und mathematischen Funktionen, die kürzlich hinzugefügt wurden. Der Artikel SQLite: Natives Arbeiten mit SQL-Datenbanken in MQL5 kann als Ausgangspunkt für die Untersuchung dieser Funktionen dienen.
2. Die Klasse CDatabase
Erstellen wir die Klasse CDatabase, um die Handhabung von Datenbanken zu erleichtern. Zunächst beschreiben wir die Zusammensetzung der Klasse. Dann überprüfen wir die Funktionsweise anhand von Beispielen.
Zu den Datenelementen der Klasse CDatabase gehören die folgenden:
- m_name - Name der Datenbankdatei (mit der Erweiterung);
- m_handle - Datenbank-Handle;
- m_flags - Kombination von Flags;
- m_table_names - Tabellennamen;
- m_curr_table_name - Name der aktuellen Tabelle;
- m_sql_request_ha - Handle der letzten SQL-Anfrage;
- m_sql_request - letzte SQL-Anfrage.
Was die Methoden angeht, so würde ich sie in mehrere Gruppen unterteilen:
- Methoden, die native Funktionen für den Umgang mit Datenbanken enthalten (API MQL5-Funktionen);
- Methoden zur Handhabung von Tabellen (tables);
- Methoden zur Bearbeitung von Anfragen (requests);
- Methoden für die Arbeit mit Ansichten (views);
- Methoden zum Abrufen von Datenelementwerten (get-Methoden).
SQLite bietet mehrere Anfrageformulare, die sowohl einfach als auch komplex sein können. Mein Ziel ist es nicht, für jedes dieser Formulare eine eigene Methode in der Klasse CDatabase zu erstellen. Wenn die Klasse keine Methode für eine bestimmte Anfrage hat, kann die Anfrage mit der universellen Methode CDatabase::Select() gebildet werden.
Schauen wir uns nun die Beispiele für die Verwendung der CDatabase-Klassenmerkmale an.
2.1 Erstellen einer Datenbank
Erstellen wir unsere erste Kalenderdatenbank mit dem Skript 1_create_calendar_db.mq5. Das Skript soll nur wenige Codezeilen enthalten.
//--- include #include "..\CDatabase.mqh" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { CDatabase db_obj; string file_name="Databases\\test_calendar_db.sqlite"; uint flags=DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE; if(!db_obj.Open(file_name, flags)) ::PrintFormat("Failed to create a calendar database \"%s\"!", file_name); db_obj.Close(); } //+------------------------------------------------------------------+
Nach der Ausführung des Skripts sehen wir, dass die Datenbankdatei test_calendar_db.sqlite in %MQL5\Files\Databases erschienen ist (Abb. 1).
Abb. 1. test_calendar_db.sqlite Datenbankdatei
Wenn wir diese Datei im Code-Editor öffnen, werden wir sehen, dass die Datenbank leer ist (Abb. 2).
Abb. 2. test_calendar_db Datenbank
2.2 Erstellen einer Tabelle
Lassen Sie uns versuchen, die Datenbank zu füllen. Zu diesem Zweck erstellen wir die Tabelle COUNTRIES, in die wir eine Liste der Länder eintragen, deren Kalenderereignisse anschließend von unseren Abfragen verarbeitet werden sollen. Das Skript 2_create_countries_table.mq5 wird diese Aufgabe übernehmen.
//--- include #include "..\CDatabase.mqh" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- open a database CDatabase db_obj; string file_name="Databases\\test_calendar_db.sqlite"; uint flags=DATABASE_OPEN_READWRITE; if(!db_obj.Open(file_name, flags)) { ::PrintFormat("Failed to open a calendar database \"%s\"!", file_name); db_obj.Close(); return; } //--- create a table string table_name="COUNTRIES"; string params[]= { "COUNTRY_ID UNSIGNED BIG INT PRIMARY KEY NOT NULL,", // 1) country ID "NAME TEXT," // 2) country name "CODE TEXT," // 3) country code "CONTINENT TEXT," // 4) country continent "CURRENCY TEXT," // 5) currency code "CURRENCY_SYMBOL TEXT," // 6) currency symbol "URL_NAME TEXT" // 7) country URL }; if(!db_obj.CreateTable(table_name, params)) { ::PrintFormat("Failed to create a table \"%s\"!", table_name); db_obj.Close(); return; } db_obj.Close(); } //+------------------------------------------------------------------+
Nach der Ausführung des Skripts können wir feststellen, dass die Tabelle COUNTRIES in der Datenbank erschienen ist (Abb. 3).
Abb. 3. Die leere Tabelle COUNTRIES
2.30 Füllen der Tabelle
Füllen wir die neue Tabelle mit Daten. Dazu verwenden sie die Funktionen der Klasse CiCalendarInfo. Weitere Details über die Klasse finden Sie im Artikel MQL5 Kochbuch – Wirtschaftskalender. Die Aufgabe wird von dem Skript 3_fill_in_countries_table.mq5 übernommen.
//--- include #include "..\CalendarInfo.mqh" #include "..\CDatabase.mqh" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- open a database CDatabase db_obj; string file_name="Databases\\test_calendar_db.sqlite"; uint flags=DATABASE_OPEN_READWRITE; if(!db_obj.Open(file_name, flags)) { db_obj.Close(); return; } //--- open a table string table_name="COUNTRIES"; if(db_obj.SelectTable(table_name)) if(db_obj.EmptyTable()) { db_obj.FinalizeSqlRequest(); string col_names[]= { "COUNTRY_ID", "NAME", "CODE", "CONTINENT", "CURRENCY", "CURRENCY_SYMBOL", "URL_NAME" }; //--- fill in the table CiCalendarInfo calendar_info; if(calendar_info.Init()) { MqlCalendarCountry calendar_countries[]; if(calendar_info.GetCountries(calendar_countries)) { if(db_obj.TransactionBegin()) for(int c_idx=0; c_idx<::ArraySize(calendar_countries); c_idx++) { MqlCalendarCountry curr_country=calendar_countries[c_idx]; string col_vals[]; ::ArrayResize(col_vals, 7); col_vals[0]=::StringFormat("%I64u", curr_country.id); col_vals[1]=::StringFormat("'%s'", curr_country.name); col_vals[2]=::StringFormat("'%s'", curr_country.code); col_vals[3]="NULL"; SCountryByContinent curr_country_continent_data; if(curr_country_continent_data.Init(curr_country.code)) col_vals[3]=::StringFormat("'%s'", curr_country_continent_data.ContinentDescription()); col_vals[4]=::StringFormat("'%s'", curr_country.currency); col_vals[5]=::StringFormat("'%s'", curr_country.currency_symbol); col_vals[6]=::StringFormat("'%s'", curr_country.url_name); if(!db_obj.InsertSingleRow(col_names, col_vals)) { db_obj.TransactionRollback(); db_obj.Close(); return; } db_obj.FinalizeSqlRequest(); } if(!db_obj.TransactionCommit()) ::PrintFormat("Failed to complete transaction execution, error %d", ::GetLastError()); } //--- print if(db_obj.PrintTable()<0) ::PrintFormat("Failed to print the table \"%s\", error %d", table_name, ::GetLastError()); } } db_obj.Close(); } //+------------------------------------------------------------------+
Drucken wir die Daten der Tabelle COUNTRIES im Protokoll aus.
3_fill_in_countries_table (EURUSD,H1) #| COUNTRY_ID NAME CODE CONTINENT CURRENCY CURRENCY_SYMBOL URL_NAME 3_fill_in_countries_table (EURUSD,H1) --+----------------------------------------------------------------------------------------- 3_fill_in_countries_table (EURUSD,H1) 1| 554 New Zealand NZ Australia/Oceania NZD $ new-zealand 3_fill_in_countries_table (EURUSD,H1) 2| 999 European Union EU Europe EUR € european-union 3_fill_in_countries_table (EURUSD,H1) 3| 392 Japan JP Asia JPY ¥ japan 3_fill_in_countries_table (EURUSD,H1) 4| 124 Canada CA North America CAD $ canada 3_fill_in_countries_table (EURUSD,H1) 5| 36 Australia AU Australia/Oceania AUD $ australia 3_fill_in_countries_table (EURUSD,H1) 6| 156 China CN Asia CNY ¥ china 3_fill_in_countries_table (EURUSD,H1) 7| 380 Italy IT Europe EUR € italy 3_fill_in_countries_table (EURUSD,H1) 8| 702 Singapore SG Asia SGD R$ singapore 3_fill_in_countries_table (EURUSD,H1) 9| 276 Germany DE Europe EUR € germany 3_fill_in_countries_table (EURUSD,H1) 10| 250 France FR Europe EUR € france 3_fill_in_countries_table (EURUSD,H1) 11| 76 Brazil BR South America BRL R$ brazil 3_fill_in_countries_table (EURUSD,H1) 12| 484 Mexico MX North America MXN Mex$ mexico 3_fill_in_countries_table (EURUSD,H1) 13| 710 South Africa ZA Africa ZAR R south-africa 3_fill_in_countries_table (EURUSD,H1) 14| 344 Hong Kong HK Asia HKD HK$ hong-kong 3_fill_in_countries_table (EURUSD,H1) 15| 356 India IN Asia INR ₹ india 3_fill_in_countries_table (EURUSD,H1) 16| 578 Norway NO Europe NOK Kr norway 3_fill_in_countries_table (EURUSD,H1) 17| 840 United States US North America USD $ united-states 3_fill_in_countries_table (EURUSD,H1) 18| 826 United Kingdom GB Europe GBP £ united-kingdom 3_fill_in_countries_table (EURUSD,H1) 19| 756 Switzerland CH Europe CHF ₣ switzerland 3_fill_in_countries_table (EURUSD,H1) 20| 410 South Korea KR Asia KRW ₩ south-korea 3_fill_in_countries_table (EURUSD,H1) 21| 724 Spain ES Europe EUR € spain 3_fill_in_countries_table (EURUSD,H1) 22| 752 Sweden SE Europe SEK Kr sweden 3_fill_in_countries_table (EURUSD,H1) 23| 0 Worldwide WW World ALL worldwide
In MetaEditor sieht die Tabelle wie folgt aus (Abb. 4).
Abb. 4. Gefüllte Tabelle COUNTRIES
2.4 Auswählen einiger Tabellenspalten
Lassen Sie uns nun die Daten der Tabelle COUNTRIES bearbeiten. Angenommen, wir wollen die folgenden Spalten auswählen:
- „COUNTRY_ID“;
- „COUNTRY_NAME“;
- „COUNTRY_CODE“;
- „COUNTRY_CONTINENT“;
- „CURRENCY“.
Wir erstellen eine SQL-Abfrage mit dem Skript 4_select_some_columns.mq5 auf folgende Weise:
//--- include #include "..\CDatabase.mqh" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- open a database CDatabase db_obj; string file_name="Databases\\test_calendar_db.sqlite"; uint flags=DATABASE_OPEN_READONLY; if(!db_obj.Open(file_name, flags)) { db_obj.Close(); return; } //--- check a table string table_name="COUNTRIES"; if(db_obj.SelectTable(table_name)) { string col_names_to_select[]= { "COUNTRY_ID", "NAME", "CODE", "CONTINENT", "CURRENCY" }; if(!db_obj.SelectFrom(col_names_to_select)) { db_obj.Close(); return; } //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest(); } db_obj.Close(); } //+------------------------------------------------------------------+
Beim Ausdrucken der Abfrage erhalten wir:
4_select_some_columns (EURUSD,H1) #| COUNTRY_ID NAME CODE CONTINENT CURRENCY 4_select_some_columns (EURUSD,H1) --+---------------------------------------------------------- 4_select_some_columns (EURUSD,H1) 1| 554 New Zealand NZ Australia/Oceania NZD 4_select_some_columns (EURUSD,H1) 2| 999 European Union EU Europe EUR 4_select_some_columns (EURUSD,H1) 3| 392 Japan JP Asia JPY 4_select_some_columns (EURUSD,H1) 4| 124 Canada CA North America CAD 4_select_some_columns (EURUSD,H1) 5| 36 Australia AU Australia/Oceania AUD 4_select_some_columns (EURUSD,H1) 6| 156 China CN Asia CNY 4_select_some_columns (EURUSD,H1) 7| 380 Italy IT Europe EUR 4_select_some_columns (EURUSD,H1) 8| 702 Singapore SG Asia SGD 4_select_some_columns (EURUSD,H1) 9| 276 Germany DE Europe EUR 4_select_some_columns (EURUSD,H1) 10| 250 France FR Europe EUR 4_select_some_columns (EURUSD,H1) 11| 76 Brazil BR South America BRL 4_select_some_columns (EURUSD,H1) 12| 484 Mexico MX North America MXN 4_select_some_columns (EURUSD,H1) 13| 710 South Africa ZA Africa ZAR 4_select_some_columns (EURUSD,H1) 14| 344 Hong Kong HK Asia HKD 4_select_some_columns (EURUSD,H1) 15| 356 India IN Asia INR 4_select_some_columns (EURUSD,H1) 16| 578 Norway NO Europe NOK 4_select_some_columns (EURUSD,H1) 17| 840 United States US North America USD 4_select_some_columns (EURUSD,H1) 18| 826 United Kingdom GB Europe GBP 4_select_some_columns (EURUSD,H1) 19| 756 Switzerland CH Europe CHF 4_select_some_columns (EURUSD,H1) 20| 410 South Korea KR Asia KRW 4_select_some_columns (EURUSD,H1) 21| 724 Spain ES Europe EUR 4_select_some_columns (EURUSD,H1) 22| 752 Sweden SE Europe SEK 4_select_some_columns (EURUSD,H1) 23| 0 Worldwide WW World ALL
Offensichtlich wurde ohne Sortierung ausgewählt.
2.5 Auswählen einiger Spalten der sortierten Tabelle
Sortieren wir die Daten in der Tabelle nach der Spalte „COUNTRY_ID“. Diese Anfrage hat die folgende Implementierung im Skript5_select_some_sorted_columns.mq5:
//--- include #include "..\CDatabase.mqh" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- open a database CDatabase db_obj; string file_name="Databases\\test_calendar_db.sqlite"; uint flags=DATABASE_OPEN_READONLY; if(!db_obj.Open(file_name, flags)) { db_obj.Close(); return; } //--- check a table string table_name="COUNTRIES"; if(db_obj.SelectTable(table_name)) { string col_names_to_select[]= { "COUNTRY_ID", "NAME", "CODE", "CONTINENT", "CURRENCY" }; string ord_names[1]; ord_names[0]=col_names_to_select[0]; if(!db_obj.SelectFromOrderedBy(col_names_to_select, ord_names)) { db_obj.Close(); return; } //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest(); } db_obj.Close(); } //+------------------------------------------------------------------+
Das Ergebnis der Abfrageausführung erscheint im Protokoll:
5_select_some_sorted_columns (EURUSD,H1) #| COUNTRY_ID NAME CODE CONTINENT CURRENCY 5_select_some_sorted_columns (EURUSD,H1) --+---------------------------------------------------------- 5_select_some_sorted_columns (EURUSD,H1) 1| 0 Worldwide WW World ALL 5_select_some_sorted_columns (EURUSD,H1) 2| 36 Australia AU Australia/Oceania AUD 5_select_some_sorted_columns (EURUSD,H1) 3| 76 Brazil BR South America BRL 5_select_some_sorted_columns (EURUSD,H1) 4| 124 Canada CA North America CAD 5_select_some_sorted_columns (EURUSD,H1) 5| 156 China CN Asia CNY 5_select_some_sorted_columns (EURUSD,H1) 6| 250 France FR Europe EUR 5_select_some_sorted_columns (EURUSD,H1) 7| 276 Germany DE Europe EUR 5_select_some_sorted_columns (EURUSD,H1) 8| 344 Hong Kong HK Asia HKD 5_select_some_sorted_columns (EURUSD,H1) 9| 356 India IN Asia INR 5_select_some_sorted_columns (EURUSD,H1) 10| 380 Italy IT Europe EUR 5_select_some_sorted_columns (EURUSD,H1) 11| 392 Japan JP Asia JPY 5_select_some_sorted_columns (EURUSD,H1) 12| 410 South Korea KR Asia KRW 5_select_some_sorted_columns (EURUSD,H1) 13| 484 Mexico MX North America MXN 5_select_some_sorted_columns (EURUSD,H1) 14| 554 New Zealand NZ Australia/Oceania NZD 5_select_some_sorted_columns (EURUSD,H1) 15| 578 Norway NO Europe NOK 5_select_some_sorted_columns (EURUSD,H1) 16| 702 Singapore SG Asia SGD 5_select_some_sorted_columns (EURUSD,H1) 17| 710 South Africa ZA Africa ZAR 5_select_some_sorted_columns (EURUSD,H1) 18| 724 Spain ES Europe EUR 5_select_some_sorted_columns (EURUSD,H1) 19| 752 Sweden SE Europe SEK 5_select_some_sorted_columns (EURUSD,H1) 20| 756 Switzerland CH Europe CHF 5_select_some_sorted_columns (EURUSD,H1) 21| 826 United Kingdom GB Europe GBP 5_select_some_sorted_columns (EURUSD,H1) 22| 840 United States US North America USD 5_select_some_sorted_columns (EURUSD,H1) 23| 999 European Union EU Europe EUR
Das Skript funktioniert korrekt - die Spalte „COUNTRY_ID“ beginnt bei 0 und endet bei 999.
2.6 Auswahl von gruppierten Ergebnissen einer bestimmten Tabellenspalte
Verwenden wir nun das Skript 6_select_some_grouped_columns.mq5, um nach Kontinenten gruppierte Ländernamen zu erhalten. Die Aufgabe besteht darin, die Anzahl der Länder zu ermitteln, die in jeder Zeile des Kontinents enthalten sind. Die Länder werden in der Spalte „NAME“ ausgewählt. Nach der Ausführung des Skripts erscheinen die folgenden Zeilen im Protokoll:
6_select_some_grouped_columns (EURUSD,H1) #| CONTINENT COUNT(NAME) 6_select_some_grouped_columns (EURUSD,H1) -+------------------------------ 6_select_some_grouped_columns (EURUSD,H1) 1| Africa 1 6_select_some_grouped_columns (EURUSD,H1) 2| Asia 6 6_select_some_grouped_columns (EURUSD,H1) 3| Australia/Oceania 2 6_select_some_grouped_columns (EURUSD,H1) 4| Europe 9 6_select_some_grouped_columns (EURUSD,H1) 5| North America 3 6_select_some_grouped_columns (EURUSD,H1) 6| South America 1 6_select_some_grouped_columns (EURUSD,H1) 7| World 1
„Europe“ umfasst die meisten Länder - 9, während „Africa“ und „South America“ jeweils nur 1 Land umfassen. Außerdem gibt es noch „World“.
2.7 Auswählen eindeutiger Werte einer bestimmten Tabellenspalte
Verwenden wir nun das Skript 7_select_distinct_columns.mq5, um eindeutige Werte in der Spalte CURRENCY zu versammeln. Es gibt Länder, die die gleiche Währung verwenden. Um Wiederholungen zu vermeiden, führen wir das Skript aus. Wir können das folgende Ergebnis sehen:
7_select_distinct_columns (EURUSD,H1) 1| NZD 7_select_distinct_columns (EURUSD,H1) 2| EUR 7_select_distinct_columns (EURUSD,H1) 3| JPY 7_select_distinct_columns (EURUSD,H1) 4| CAD 7_select_distinct_columns (EURUSD,H1) 5| AUD 7_select_distinct_columns (EURUSD,H1) 6| CNY 7_select_distinct_columns (EURUSD,H1) 7| SGD 7_select_distinct_columns (EURUSD,H1) 8| BRL 7_select_distinct_columns (EURUSD,H1) 9| MXN 7_select_distinct_columns (EURUSD,H1) 10| ZAR 7_select_distinct_columns (EURUSD,H1) 11| HKD 7_select_distinct_columns (EURUSD,H1) 12| INR 7_select_distinct_columns (EURUSD,H1) 13| NOK 7_select_distinct_columns (EURUSD,H1) 14| USD 7_select_distinct_columns (EURUSD,H1) 15| GBP 7_select_distinct_columns (EURUSD,H1) 16| CHF 7_select_distinct_columns (EURUSD,H1) 17| KRW 7_select_distinct_columns (EURUSD,H1) 18| SEK 7_select_distinct_columns (EURUSD,H1) 19| ALL
Der Kalender enthält also Ereignisse für insgesamt 18 Währungen und eine Gruppe von Ereignissen, die für alle Währungen gelten.
Es ist leicht zu erkennen, dass die Methoden zur Auswahl gruppierter Ergebnisse und zur Auswahl eindeutiger Werte Ähnlichkeiten aufweisen. Lassen Sie uns dies anhand eines Beispiels demonstrieren.
Das Skript 8_compare_ grouped_and_distinct_columns.mq5 zeigt die folgenden Ergebnisse im Protokoll an:
8_compare_ grouped_and_distinct_columns (EURUSD,H1) 8_compare_ grouped_and_distinct_columns (EURUSD,H1) Method CDatabase::SelectFromGroupBy() 8_compare_ grouped_and_distinct_columns (EURUSD,H1) #| CONTINENT 8_compare_ grouped_and_distinct_columns (EURUSD,H1) -+------------------ 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 1| Africa 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 2| Asia 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 3| Australia/Oceania 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 4| Europe 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 5| North America 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 6| South America 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 7| World 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 8_compare_ grouped_and_distinct_columns (EURUSD,H1) Method CDatabase::SelectDistinctFrom() 8_compare_ grouped_and_distinct_columns (EURUSD,H1) #| CONTINENT 8_compare_ grouped_and_distinct_columns (EURUSD,H1) -+------------------ 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 1| Australia/Oceania 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 2| Europe 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 3| Asia 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 4| North America 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 5| South America 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 6| Africa 8_compare_ grouped_and_distinct_columns (EURUSD,H1) 7| World
Die Methoden haben die gleichen inhaltlichen Ergebnisse geliefert, weil wir die Spalte „CONTINENT“ als Gruppierungsspalte (Feld) für die erste Methode definiert haben. Interessanterweise hat die erste Methode auch die Auswahl für uns sortiert.
2.8 Auswahl von geordneten eindeutigen Werten einer bestimmten Tabellenspalte
Die Werte der Spalte CURRENCY wurden vom Skript 7_select_distinct_columns.mq5 unsortiert angezeigt. Machen wir eine sortierte Auswahl (Skript 9_select_sorted_distinct_columns.mq5). Die Spalte „COUNTRY_ID“ sei das Sortierkriterium. Als Ergebnis der Log-Manipulationen erhalten wir:
9_select_sorted_distinct_columns (EURUSD,H1) #| CURRENCY 9_select_sorted_distinct_columns (EURUSD,H1) --+--------- 9_select_sorted_distinct_columns (EURUSD,H1) 1| ALL 9_select_sorted_distinct_columns (EURUSD,H1) 2| AUD 9_select_sorted_distinct_columns (EURUSD,H1) 3| BRL 9_select_sorted_distinct_columns (EURUSD,H1) 4| CAD 9_select_sorted_distinct_columns (EURUSD,H1) 5| CNY 9_select_sorted_distinct_columns (EURUSD,H1) 6| EUR 9_select_sorted_distinct_columns (EURUSD,H1) 7| HKD 9_select_sorted_distinct_columns (EURUSD,H1) 8| INR 9_select_sorted_distinct_columns (EURUSD,H1) 9| JPY 9_select_sorted_distinct_columns (EURUSD,H1) 10| KRW 9_select_sorted_distinct_columns (EURUSD,H1) 11| MXN 9_select_sorted_distinct_columns (EURUSD,H1) 12| NZD 9_select_sorted_distinct_columns (EURUSD,H1) 13| NOK 9_select_sorted_distinct_columns (EURUSD,H1) 14| SGD 9_select_sorted_distinct_columns (EURUSD,H1) 15| ZAR 9_select_sorted_distinct_columns (EURUSD,H1) 16| SEK 9_select_sorted_distinct_columns (EURUSD,H1) 17| CHF 9_select_sorted_distinct_columns (EURUSD,H1) 18| GBP 9_select_sorted_distinct_columns (EURUSD,H1) 19| USD
Jetzt sind alle Währungen sortiert. Standardmäßig wird die Sortierung in aufsteigender Reihenfolge vorgenommen.
2.9 Auswählen einiger Tabellenspalten nach Bedingungen
Zuvor haben wir bereits eine SQL-Abfrage zur Auswahl von Tabellenspalten erstellt. Jetzt können wir die Spalten abrufen, wenn eine Bedingung erfüllt ist. Angenommen, wir wollen Länder auswählen, deren ID gleich oder größer als 392 und gleich oder kleiner als 840 ist. Diese Aufgabe wird gelöst durch das Skript 10_select_some_columns_where.mq5 gelöst.
Nach der Ausführung des Skripts wird im Protokoll Folgendes angezeigt:
10_select_some_columns_where (EURUSD,H1) #| COUNTRY_ID NAME CODE CONTINENT CURRENCY 10_select_some_columns_where (EURUSD,H1) --+---------------------------------------------------------- 10_select_some_columns_where (EURUSD,H1) 1| 392 Japan JP Asia JPY 10_select_some_columns_where (EURUSD,H1) 2| 410 South Korea KR Asia KRW 10_select_some_columns_where (EURUSD,H1) 3| 484 Mexico MX North America MXN 10_select_some_columns_where (EURUSD,H1) 4| 554 New Zealand NZ Australia/Oceania NZD 10_select_some_columns_where (EURUSD,H1) 5| 578 Norway NO Europe NOK 10_select_some_columns_where (EURUSD,H1) 6| 702 Singapore SG Asia SGD 10_select_some_columns_where (EURUSD,H1) 7| 710 South Africa ZA Africa ZAR 10_select_some_columns_where (EURUSD,H1) 8| 724 Spain ES Europe EUR 10_select_some_columns_where (EURUSD,H1) 9| 752 Sweden SE Europe SEK 10_select_some_columns_where (EURUSD,H1) 10| 756 Switzerland CH Europe CHF 10_select_some_columns_where (EURUSD,H1) 11| 826 United Kingdom GB Europe GBP 10_select_some_columns_where (EURUSD,H1) 12| 840 United States US North America USD
Mit anderen Worten: Die Stichprobe beginnt mit dem Ländercode 392 und endet mit 840.
2.10 Einige der sortierten Tabellenspalten nach Bedingung auswählen
Machen wir das vorherige Problem noch komplizierter. Fügen wir der Stichprobe ein Sortierkriterium hinzu - das ist die Zugehörigkeit des Landes zum Kontinent. Die aktuelle Aufgabe wird mit dem Skript 11_select_some_sorted_columns_where.mq5 gelöst. Nach der Ausführung sehen wir die folgenden Zeilen im Protokoll:
11_select_some_sorted_columns_where (EURUSD,H1) #| COUNTRY_ID NAME CODE CONTINENT CURRENCY 11_select_some_sorted_columns_where (EURUSD,H1) --+---------------------------------------------------------- 11_select_some_sorted_columns_where (EURUSD,H1) 1| 710 South Africa ZA Africa ZAR 11_select_some_sorted_columns_where (EURUSD,H1) 2| 392 Japan JP Asia JPY 11_select_some_sorted_columns_where (EURUSD,H1) 3| 410 South Korea KR Asia KRW 11_select_some_sorted_columns_where (EURUSD,H1) 4| 702 Singapore SG Asia SGD 11_select_some_sorted_columns_where (EURUSD,H1) 5| 554 New Zealand NZ Australia/Oceania NZD 11_select_some_sorted_columns_where (EURUSD,H1) 6| 578 Norway NO Europe NOK 11_select_some_sorted_columns_where (EURUSD,H1) 7| 724 Spain ES Europe EUR 11_select_some_sorted_columns_where (EURUSD,H1) 8| 752 Sweden SE Europe SEK 11_select_some_sorted_columns_where (EURUSD,H1) 9| 756 Switzerland CH Europe CHF 11_select_some_sorted_columns_where (EURUSD,H1) 10| 826 United Kingdom GB Europe GBP 11_select_some_sorted_columns_where (EURUSD,H1) 11| 484 Mexico MX North America MXN 11_select_some_sorted_columns_where (EURUSD,H1) 12| 840 United States US North America USD
Folglich steht „South Africa“ in der Stichprobe an erster Stelle, da der Kontinent „Africa“ in der Liste der Kontinente an erster Stelle steht.
2.11 Aktualisieren einiger Tabellenspalten nach Bedingungen
Nehmen wir an, dass wir die Zeilen in den ausgewählten Spalten aktualisieren müssen. Außerdem müssen wir dies nach Erfüllung einer Vorbedingung tun.
Nehmen wir die asiatischen Länder und setzen die Werte für sie in den Spalten CURRENCY und CURRENCY_SYMBOL zurück. Die Aufgabe wird vom Skript 12_update_some_columns.mq5 ausgeführt.
Als Ergebnis der Ausführung erhalten wir die folgende Tabelle:
12_update_some_columns (EURUSD,H1) #| COUNTRY_ID NAME CODE CONTINENT CURRENCY CURRENCY_SYMBOL URL_NAME 12_update_some_columns (EURUSD,H1) --+----------------------------------------------------------------------------------------- 12_update_some_columns (EURUSD,H1) 1| 554 New Zealand NZ Australia/Oceania NZD $ new-zealand 12_update_some_columns (EURUSD,H1) 2| 999 European Union EU Europe EUR € european-union 12_update_some_columns (EURUSD,H1) 3| 392 Japan JP Asia None None japan 12_update_some_columns (EURUSD,H1) 4| 124 Canada CA North America CAD $ canada 12_update_some_columns (EURUSD,H1) 5| 36 Australia AU Australia/Oceania AUD $ australia 12_update_some_columns (EURUSD,H1) 6| 156 China CN Asia None None china 12_update_some_columns (EURUSD,H1) 7| 380 Italy IT Europe EUR € italy 12_update_some_columns (EURUSD,H1) 8| 702 Singapore SG Asia None None singapore 12_update_some_columns (EURUSD,H1) 9| 276 Germany DE Europe EUR € germany 12_update_some_columns (EURUSD,H1) 10| 250 France FR Europe EUR € france 12_update_some_columns (EURUSD,H1) 11| 76 Brazil BR South America BRL R$ brazil 12_update_some_columns (EURUSD,H1) 12| 484 Mexico MX North America MXN Mex$ mexico 12_update_some_columns (EURUSD,H1) 13| 710 South Africa ZA Africa ZAR R south-africa 12_update_some_columns (EURUSD,H1) 14| 344 Hong Kong HK Asia None None hong-kong 12_update_some_columns (EURUSD,H1) 15| 356 India IN Asia None None india 12_update_some_columns (EURUSD,H1) 16| 578 Norway NO Europe NOK Kr norway 12_update_some_columns (EURUSD,H1) 17| 840 United States US North America USD $ united-states 12_update_some_columns (EURUSD,H1) 18| 826 United Kingdom GB Europe GBP £ united-kingdom 12_update_some_columns (EURUSD,H1) 19| 756 Switzerland CH Europe CHF ₣ switzerland 12_update_some_columns (EURUSD,H1) 20| 410 South Korea KR Asia None None south-korea 12_update_some_columns (EURUSD,H1) 21| 724 Spain ES Europe EUR € spain 12_update_some_columns (EURUSD,H1) 22| 752 Sweden SE Europe SEK Kr sweden 12_update_some_columns (EURUSD,H1) 23| 0 Worldwide WW World ALL worldwide
2.12 Ersetzen und Hinzufügen einiger Tabellenzeilen
Fahren wir mit der Arbeit an den Tabellen fort. Lassen Sie uns nun versuchen, einige Zeilen in der ausgewählten Tabelle zu ersetzen.
Angenommen, wir müssen das aktuelle Symbol „Mex$“ durch „Peso mexicano“ für „Mexiko“ in der Spalte CURRENCY_SYMBOL ersetzen. Das Skript 13_replace_some_rows.mq5 wird das ausführen.
In der aktuellen Version der LÄNDERTABELLE hat Mexiko den folgenden Eintrag:
COUNTRY_ID | NAME | CODE | CONTINENT | CURRENCY | CURRENCY_SYMBOL | URL_NAME |
---|---|---|---|---|---|---|
484 | Mexico | MX | North America | MXN | Mex$ |
|
Um diese Zeile in der Tabelle zu ersetzen, müssen wir einen eindeutigen Wert für die ausgewählte Zeile festlegen. Andernfalls wird SQLite nicht verstehen, was wir ersetzen wollen.
Nehmen wir an, dass dieser Wert der Name des Landes ist (Spalte NAME). Dann wird die Ersetzungsfunktion im Code wie folgt dargestellt:
//--- the replaced row for "COUNTRY_NAME=Mexico" string col_names[]= { "NAME", "CURRENCY_SYMBOL" }; string col_vals[2]; col_vals[0]=::StringFormat("'%s'", "Mexico"); col_vals[1]=::StringFormat("'%s'", "Peso mexicano"); if(!db_obj.Replace(col_names, col_vals)) { db_obj.Close(); return; }
Bei der Ausführung des Skripts wird folgende Fehlermeldung angezeigt:
11_replace_some_rows (EURUSD,H1) database error, NOT NULL constraint failed: COUNTRIES.COUNTRY_ID 11_replace_some_rows (EURUSD,H1) CDatabase::Replace: failed with code 5619
Offensichtlich ist die Beschränkung NOT NULL verletzt worden. Bei der Erstellung der Tabelle wurde ursprünglich festgelegt, dass die Spalte COUNTRY_ID nicht Null enthalten darf. Es ist also notwendig, einen Wert für diese Spalte hinzuzufügen. Um keine halbleere Zeile zu erhalten, fügen wir Werte für alle Spalten hinzu.
//--- the replaced row for "COUNTRY_NAME=Mexico" string col_names[]= { "COUNTRY_ID", "NAME", "CODE", "CONTINENT", "CURRENCY", "CURRENCY_SYMBOL", "URL_NAME" }; string col_vals[7]; col_vals[0]=::StringFormat("%I64u", 484); col_vals[1]=::StringFormat("'%s'", "Mexico"); col_vals[2]=::StringFormat("'%s'", "MX"); col_vals[3]=::StringFormat("'%s'", "North America"); col_vals[4]=::StringFormat("'%s'", "MXN"); col_vals[5]=::StringFormat("'%s'", "Peso mexicano"); col_vals[6]=::StringFormat("'%s'", "mexico"); if(!db_obj.Replace(col_names, col_vals)) { db_obj.Close(); return; }
Jetzt funktioniert das Skript einwandfrei. Die folgenden Einträge erscheinen im Protokoll:
13_replace_some_rows (EURUSD,H1) 'Mexico' row before replacement 13_replace_some_rows (EURUSD,H1) #| COUNTRY_ID NAME CODE CONTINENT CURRENCY CURRENCY_SYMBOL URL_NAME 13_replace_some_rows (EURUSD,H1) -+----------------------------------------------------------------------- 13_replace_some_rows (EURUSD,H1) 1| 484 Mexico MX North America MXN Mex$ mexico 13_replace_some_rows (EURUSD,H1) 13_replace_some_rows (EURUSD,H1) 'Mexico' row after replacement 13_replace_some_rows (EURUSD,H1) #| COUNTRY_ID NAME CODE CONTINENT CURRENCY CURRENCY_SYMBOL URL_NAME 13_replace_some_rows (EURUSD,H1) -+----------------------------------------------------------------------- 13_replace_some_rows (EURUSD,H1) 1| 484 Mexico MX North America MXN Peso mexicano mexico
Wenn es keine Zeile mit Daten über Mexiko gäbe, würde sie einfach hinzugefügt werden. Mit anderen Worten: Das Ersetzen ist auch die Operation zum Hinzufügen von Tabellenzeilen.
2.13 Löschen einiger Zeilen der Tabelle
Nun wollen wir sehen, wie wir die Anzahl der Tabellenzeilen verringern können, anstatt sie zu erhöhen. Dazu erstellen wir das Skript 14_delete_some_rows.mq5, das auf Anfrage die Zeilen mit Bezug zu Asien aus der ausgewählten Tabelle löscht.
Nach der Ausführung des Skripts wird die Abschlusstabelle angezeigt:
14_delete_some_rows (EURUSD,H1) #| COUNTRY_ID NAME CODE CONTINENT CURRENCY CURRENCY_SYMBOL URL_NAME 14_delete_some_rows (EURUSD,H1) --+----------------------------------------------------------------------------------------- 14_delete_some_rows (EURUSD,H1) 1| 554 New Zealand NZ Australia/Oceania NZD $ new-zealand 14_delete_some_rows (EURUSD,H1) 2| 999 European Union EU Europe EUR € european-union 14_delete_some_rows (EURUSD,H1) 3| 124 Canada CA North America CAD $ canada 14_delete_some_rows (EURUSD,H1) 4| 36 Australia AU Australia/Oceania AUD $ australia 14_delete_some_rows (EURUSD,H1) 5| 380 Italy IT Europe EUR € italy 14_delete_some_rows (EURUSD,H1) 6| 276 Germany DE Europe EUR € germany 14_delete_some_rows (EURUSD,H1) 7| 250 France FR Europe EUR € france 14_delete_some_rows (EURUSD,H1) 8| 76 Brazil BR South America BRL R$ brazil 14_delete_some_rows (EURUSD,H1) 9| 710 South Africa ZA Africa ZAR R south-africa 14_delete_some_rows (EURUSD,H1) 10| 578 Norway NO Europe NOK Kr norway 14_delete_some_rows (EURUSD,H1) 11| 840 United States US North America USD $ united-states 14_delete_some_rows (EURUSD,H1) 12| 826 United Kingdom GB Europe GBP £ united-kingdom 14_delete_some_rows (EURUSD,H1) 13| 756 Switzerland CH Europe CHF ₣ switzerland 14_delete_some_rows (EURUSD,H1) 14| 724 Spain ES Europe EUR € spain 14_delete_some_rows (EURUSD,H1) 15| 752 Sweden SE Europe SEK Kr sweden 14_delete_some_rows (EURUSD,H1) 16| 0 Worldwide WW World ALL worldwide 14_delete_some_rows (EURUSD,H1) 17| 484 Mexico MX North America MXN Peso mexicano mexico
Es wurden keine asienbezogenen Zeilen gefunden.
2.14 Hinzufügen von Spalten zur Tabelle
Das Hinzufügen neuer Spalten zu einer Tabelle ist ebenfalls eine recht häufige Aufgabe.
Angenommen, wir müssen unsere Tabelle COUNTRIES erweitern und eine Spalte hinzufügen, die die Anzahl der makroökonomischen Ereignisse enthält, die in den Kalender fallen.
Die Aufgabe wird von dem Skript 15_add_new_column.mq5 ausgeführt.
Überprüfen wir nach der Ausführung des Skripts die Tabelle (Abb. 5). Sie enthält jetzt die neue Spalte EVENTS_NUM.
Abb. 5. Die neue Spalte EVENTS_NUM in der Tabelle COUNTRIES
2.15 Spalten in der Tabelle umbenennen
Das Umbenennen von Spalten erfolgt mit CDatabase::RenameColumn(const string _curr_name, const string _new_name). Wir geben den aktuellen und den neuen Spaltennamen als Parameter an. Das Skript 16_rename_column.mq5 ersetzt den Spaltennamen EVENTS_NUM durch EVENTS_NUMBER.
Abb. 6. Die umbenannte Spalte EVENTS_NUMBER in der Tabelle COUNTRIES
Die Tabelle sieht nun wie folgt aus (Abb. 6).
2.16 Verkettung von Zeilen
Angenommen, wir müssen die Stichprobenergebnisse in einer einzigen Tabelle verketten. Dies kann mit der Methode CDatabase::Union() erreicht werden. Diese Aufgabe erledigt das Skript 17_union_some_columns.mq5.
Angenommen, wir haben zwei Tabellen - EUROPEAN_COUNTRIES und NORTH_AMERICAN_COUNTRIES. Die erste Tabelle enthält die europäischen Länder, die zweite die nordamerikanischen Länder. Erstellen wir zunächst Tabellen, um dann ihre Zeilen zu verketten. Jede der Tabellen ist die resultierende Auswahl aus der Tabelle COUNTRIES. Im Code sieht das wie folgt aus:
//--- create 2 tables string table1_name, table2_name, sql_request; table1_name="EUROPEAN_COUNTRIES"; table2_name="NORTH_AMERICAN_COUNTRIES"; sql_request="SELECT COUNTRY_ID AS id, NAME AS name, CURRENCY " "as currency FROM COUNTRIES " "WHERE CONTINENT='North America'"; if(!db_obj.CreateTableAs(table2_name, sql_request, true)) { db_obj.Close(); return; } db_obj.FinalizeSqlRequest(); sql_request="SELECT COUNTRY_ID AS id, NAME AS name, CURRENCY " "as currency FROM COUNTRIES " "WHERE CONTINENT='Europe'"; if(!db_obj.CreateTableAs(table1_name, sql_request, true)) { db_obj.Close(); return; } db_obj.FinalizeSqlRequest();
Bei der Ausführung des Skripts werden die folgenden Einträge im Protokoll angezeigt:
16_union_some_columns (EURUSD,H1) #| id name currency 16_union_some_columns (EURUSD,H1) --+---------------------------- 16_union_some_columns (EURUSD,H1) 1| 124 Canada CAD 16_union_some_columns (EURUSD,H1) 2| 250 France EUR 16_union_some_columns (EURUSD,H1) 3| 276 Germany EUR 16_union_some_columns (EURUSD,H1) 4| 380 Italy EUR 16_union_some_columns (EURUSD,H1) 5| 484 Mexico MXN 16_union_some_columns (EURUSD,H1) 6| 578 Norway NOK 16_union_some_columns (EURUSD,H1) 7| 724 Spain EUR 16_union_some_columns (EURUSD,H1) 8| 752 Sweden SEK 16_union_some_columns (EURUSD,H1) 9| 756 Switzerland CHF 16_union_some_columns (EURUSD,H1) 10| 826 United Kingdom GBP 16_union_some_columns (EURUSD,H1) 11| 840 United States USD 16_union_some_columns (EURUSD,H1) 12| 999 European Union EUR
Die resultierende Stichprobe umfasst europäische und nordamerikanische Länder.
2.17 Unterschied zwischen den Stichproben
Nehmen wir an, wir haben zwei Stichproben. Wir müssen Einträge in der ersten Stichprobe finden, die in der zweiten Stichprobe nicht vorhanden sind. Dies kann mit der Methode CDatabase::Except() erreicht werden.
Nehmen wir als Beispiel die Tabellen COUNTRIES und EUROPEAN_COUNTRIES. Schauen wir uns an, welche Länder übrig bleiben, wenn der EXCEPT-Operator auf die erste Tabelle angewendet wird.
Die Lösung bietet das Skript 18_except_some_columns.mq5.
Die folgenden Zeilen werden im Protokoll als Ergebnis der Skriptausführung angezeigt:
18_except_some_columns (EURUSD,H1) #| COUNTRY_ID NAME CURRENCY 18_except_some_columns (EURUSD,H1) -+---------------------------------- 18_except_some_columns (EURUSD,H1) 1| 0 Worldwide ALL 18_except_some_columns (EURUSD,H1) 2| 36 Australia AUD 18_except_some_columns (EURUSD,H1) 3| 76 Brazil BRL 18_except_some_columns (EURUSD,H1) 4| 124 Canada CAD 18_except_some_columns (EURUSD,H1) 5| 484 Mexico MXN 18_except_some_columns (EURUSD,H1) 6| 554 New Zealand NZD 18_except_some_columns (EURUSD,H1) 7| 710 South Africa ZAR 18_except_some_columns (EURUSD,H1) 8| 840 United States USD
Wie wir sehen können, enthält die Stichprobe keine europäischen Länder. Die Asiaten fehlen ebenfalls, da sie zuvor entfernt wurden.
2.18 Beispiel einer Schnittmenge
Nun wollen wir herausfinden, welche gemeinsamen Merkmale die Muster haben. Mit anderen Worten: Die Aufgabe besteht darin, gemeinsame Zeilen in den Stichproben zu finden.
Zunächst aktualisieren wir die Tabelle COUNTRIES und bringen sie in ihre ursprüngliche Form zurück, in der die asiatischen Länder enthalten waren.
Wir erstellen zwei temporäre Tabellen mit den Spalten „id“, „name“ und „currency“. Die erste enthält Länder, deren Wert in der Spalte COUNTRY_ID nicht höher als 578 ist, und die zweite enthält Länder, deren Wert in derselben Spalte mindestens 392 beträgt.
//--- create temporary tables string table1_name, table2_name, sql_request; table1_name="Table1"; table2_name="Table2"; sql_request="SELECT COUNTRY_ID AS id, NAME AS name, CURRENCY " "as currency FROM COUNTRIES " "WHERE COUNTRY_ID<=578"; if(!db_obj.CreateTableAs(table1_name, sql_request, true, true)) { db_obj.Close(); return; } db_obj.FinalizeSqlRequest(); //--- print the temporary table string temp_col_names[]= {"*"}; if(db_obj.SelectTable(table1_name, true)) if(db_obj.SelectFrom(temp_col_names)) { ::Print(" \nTable #1: "); db_obj.PrintSqlRequest(); db_obj.FinalizeSqlRequest(); } sql_request="SELECT COUNTRY_ID AS id, NAME AS name, CURRENCY " "as currency FROM COUNTRIES " "WHERE COUNTRY_ID>=392"; if(!db_obj.CreateTableAs(table2_name, sql_request, true, true)) { db_obj.Close(); return; } db_obj.FinalizeSqlRequest(); //--- print the temporary table if(db_obj.SelectTable(table2_name, true)) if(db_obj.SelectFrom(temp_col_names)) { ::Print(" \nTable #2: "); db_obj.PrintSqlRequest(); db_obj.FinalizeSqlRequest(); }
Verwenden wir die Funktionen der Methode CDatabase::Intersect() im Skript 19_intersect_some_columns.mq5. Als Ergebnis erhalten wir die folgenden Zeilen im Protokoll:
19_intersect_some_columns (EURUSD,H1) #| id name currency 19_intersect_some_columns (EURUSD,H1) -+------------------------- 19_intersect_some_columns (EURUSD,H1) 1| 392 Japan JPY 19_intersect_some_columns (EURUSD,H1) 2| 410 South Korea KRW 19_intersect_some_columns (EURUSD,H1) 3| 484 Mexico MXN 19_intersect_some_columns (EURUSD,H1) 4| 554 New Zealand NZD 19_intersect_some_columns (EURUSD,H1) 5| 578 Norway NOK
Das Skript hat korrekt funktioniert. Wir erhalten eine Liste von Ländern, deren kleinste ID 392 und größte 578 beträgt.
2.19 Erstellen von Ansichten
Ein View (Ansicht) ist eine Art virtueller Tisch. Der Vorteil ist, dass Sie Daten aus jeder anderen Tabelle anzeigen können.
Wir werden Ansichten mit den Methoden bool CDatabase::CreateView() und bool CDatabase::CreateViewWhere() erstellen, wobei die erste eine Art unbedingte Ansicht erstellt, während die zweite eine Ansicht gemäß einer bestimmten Bedingung erstellt.
Betrachten wir folgendes Beispiel. Wir haben die Tabelle COUNTRIES. Nehmen wir an, dass wir für die neue virtuelle Tabelle alle Länder nach den Spalten NAME, CONTINENT und CURRENCY auswählen müssen.
Lösen wir dieses Problem mit dem Skript 20_create_view.mq5. Das Ergebnis ist die Ansicht „All_countries“ (Abb. 7).
Abb. 7. Ansicht „Alle_Länder“
Verkomplizieren wir das Beispiel und wählen wir nur europäische Länder aus. Das Skript 21_create_view_where.mq5 wird das erledigen. Als Ergebnis haben wir eine virtuelle Tabelle, die nur europäische Länder enthält (Abb. 8).
Abb. 8. Ansicht „Europa“
Ansichten (views) sind keine vollwertigen Tabellen, da wir in ihnen keine Zeilen hinzufügen, löschen oder aktualisieren können. Sie können jedoch verwendet werden, um die Ergebnisse komplexer Abfragen bequem zu aggregieren und einzelne Spalten auszuwählen, wobei die Namen geändert werden können, ohne die Beziehungen zwischen den Tabellen selbst zu beeinträchtigen.
2.20 Entfernen von Ansichten
Mit der Methode CDatabase::DropView() können wir eine zuvor erstellte Ansicht entfernen.
Die Methode ähnelt ihrem Gegenstück DropTable(), das die Tabellen entfernt. In den vorherigen Beispielen wurde die Methode zum Löschen der Ansicht aufgerufen, bevor die Ansicht erstellt wurde.
Nun ist es an der Zeit, ein paar Worte über die IF EXISTS-Konstruktion zu verlieren. Wenn wir versuchen, eine nicht existierende Ansicht mit dieser Konstruktion zu löschen, gibt die Methode „true“ zurück, andernfalls „false“.
Schauen wir uns an, wie das Skript 22_drop_view.mq5 funktioniert.
//--- drop a view string table_name="COUNTRIES"; if(db_obj.SelectTable(table_name)) for(int idx=0; idx<2; idx++) { string view_name=::StringFormat("European%d", idx+1); bool if_exists=idx; if(db_obj.DropView(view_name, if_exists)) ::PrintFormat("A view \"%s\" has been successfully dropped!", view_name); db_obj.FinalizeSqlRequest(); }
Zunächst wird versucht, die nicht existierende Ansicht „European_countries1“ zu entfernen, ohne IF EXISTS aufzurufen. Als Ergebnis erhalten wir den Fehler 5601:
22_drop_view (EURUSD,H1) database error, no such view: European1 22_drop_view (EURUSD,H1) CDatabase::Select: failed with code 5601 22_drop_view (EURUSD,H1) A view "European2" has been successfully dropped!
Danach versucht das Skript, die ebenfalls nicht existierende Ansicht „European_countries2“ mit IF EXISTS zu löschen. Das Löschen der zweiten Ansicht wird erfolgreich sein, auch wenn keine Löschung stattfindet.
2.21 Umbenennen einer Tabelle
Nehmen wir an, wir stehen vor der Aufgabe, die Tabelle selbst umzubenennen. Wenden wir uns dazu der Methode CDatabase::RenameTable() zu. Die Umbenennung erfolgt durch das Skript 23_rename_table.mq5 Skript.
Abb. 9. Umbenannte Tabelle COUNTRIES1
Infolgedessen erhält die aktuelle Tabelle den Namen COUNTRIES1 (Abb. 9).
3. Datenbank für makroökonomische Ereignisse
In diesem Abschnitt schlage ich vor, mit dem Aufbau einer relationalen Datenbank der im Kalender erfassten makroökonomischen Ereignisse zu beginnen.
Erstellen wir also zunächst eine Tabellenstruktur, aus der die künftige Datenbank bestehen wird. Im Artikel „MQL5 Kochbuch - Wirtschaftskalender“ wurden bereits Kalenderstrukturen besprochen. Daher ist es in unserem Fall recht einfach, Datenbanktabellen zu erstellen und Beziehungen für sie festzulegen.
3.1 Tabellen und relationale Verbindungen
Die Datenbank soll drei Quelltabellen enthalten:
- COUNTRIES;
- EVENTS;
- EVENT_VALUES.
Die relationalen Verbindungen zwischen den Tabellen sind in Abb. 10 dargestellt.
Abb. 10. Die Struktur der Verbindungen zwischen den Tabellen in der Datenbank Calendar_DB
Die Tabelle COUNTRIES wird zur übergeordneten Tabelle für die Tabelle EVENTS. Letztere wiederum wird von der Ersteren abgeleitet.
Der Primärschlüssel für die Tabelle COUNTRIES ist die Spalte COUNTRY_ID (Feld). In der Abbildung ist ihm das „+“-Zeichen vorangestellt. Für die Tabelle EVENTS ist der Schlüssel die Spalte EVENT_ID, während die Spalte COUNTRY_ID ein externer Fremdschlüssel ist. In der Struktur ist ihm das Symbol „#“ vorangestellt.
Die Tabelle EVENTS wird zur übergeordneten Tabelle der Tabelle EVENT_VALUES, während die zweite Tabelle zur untergeordneten Tabelle der ersten Tabelle wird.
In der Tabelle EVENT_VALUES ist der Primärschlüssel die Spalte (Feld) VALUE_ID, der externe Schlüssel ist EVENT_ID.
Die Schlüssel werden benötigt, um die Beziehungen zwischen den oben genannten Tabellen herzustellen. Die Beziehungen tragen ihrerseits zur Integrität der Daten in der Datenbank bei.
Die Beziehungen zwischen den drei Tabellen sind in der Form „one-to-many“ (eins-zu-vielen, 1..*). Ich glaube, es wird nicht schwer sein, sie zu entschlüsseln. Die erste Verbindung zwischen Ländern und Ereignissen kann wie folgt dargestellt werden: Ein Land hat viele makroökonomische Ereignisse, während ein Ereignis nur ein Land hat. Der zweite Zusammenhang zwischen Ereignissen und Ereigniswerten lässt sich wie folgt veranschaulichen: Ein Ereignis hat viele Werte, während jeder Wert nur ein Ereignis hat.
Kommen wir nun zum Code. Das Skript sCreateAndFillCalendarDB.mq5 umfasst folgende Schritte:
- Erstellen einer Kalenderdatenbank;
- Erstellen der Datenbanktabellen;
- Füllen der Tabellen.
Schauen wir uns zum Beispiel an, wie die Tabelle EVENTS erstellt wird. Die endgültige Abfrage zur Erstellung dieser Tabelle sieht wie folgt aus:
CREATE TABLE IF NOT EXISTS EVENTS ( EVENT_ID [UNSIGNED BIG INT] PRIMARY KEY NOT NULL, TYPE TEXT, SECTOR TEXT, FREQUENCY TEXT, TIME_MODE TEXT, COUNTRY_ID [UNSIGNED BIG INT] NOT NULL, UNIT TEXT, IMPORTANCE TEXT, MULTIPLIER TEXT, DIGITS [UNSIGNED INT], SOURCE TEXT, CODE TEXT, NAME TEXT, FOREIGN KEY ( COUNTRY_ID ) REFERENCES COUNTRIES (COUNTRY_ID) ON UPDATE CASCADE ON DELETE CASCADE )
Von besonderem Interesse sind die Zeichenfolgen, in denen der externe Schlüssel erstellt wird. Die Zeile FOREIGN KEY (COUNTRY_ID) bedeutet, dass die Tabelle über einen externen Schlüssel mit dem Feld COUNTRY_ID verfügt. Die Konstruktion REFERENCES COUNTRIES(COUNTRY_ID) wird verwendet, um auf die übergeordnete Tabelle COUNTRIES zu verweisen.
Die Ausdrücke ON UPDATE CASCADE und ON DELETE CASCADE bedeuten, dass, wenn eine Bezugszeile aus der übergeordneten Tabelle gelöscht oder geändert wird, die Zeilen in der untergeordneten Tabelle ebenfalls gelöscht oder geändert werden.
Was das Füllen von Tabellen betrifft, so ist unten ein Codeblock zu sehen, in dem die Tabelle COUNTRIES gefüllt wird.
//--- Table 1 MqlCalendarCountry calendar_countries[]; table_name="COUNTRIES"; if(db_obj.SelectTable(table_name)) if(db_obj.EmptyTable()) { db_obj.FinalizeSqlRequest(); string col_names[]= { "COUNTRY_ID", // 1 "NAME", // 2 "CODE", // 3 "CONTINENT", // 4 "CURRENCY", // 5 "CURRENCY_SYMBOL",// 6 "URL_NAME" // 7 }; CiCalendarInfo calendar_info; if(calendar_info.Init()) { if(calendar_info.GetCountries(calendar_countries)) { if(db_obj.TransactionBegin()) for(int c_idx=0; c_idx<::ArraySize(calendar_countries); c_idx++) { MqlCalendarCountry curr_country=calendar_countries[c_idx]; string col_vals[]; ::ArrayResize(col_vals, 7); col_vals[0]=::StringFormat("%I64u", curr_country.id); col_vals[1]=::StringFormat("'%s'", curr_country.name); col_vals[2]=::StringFormat("'%s'", curr_country.code); col_vals[3]="NULL"; SCountryByContinent curr_country_continent_data; if(curr_country_continent_data.Init(curr_country.code)) col_vals[3]=::StringFormat("'%s'", curr_country_continent_data.ContinentDescription()); col_vals[4]=::StringFormat("'%s'", curr_country.currency); col_vals[5]=::StringFormat("'%s'", curr_country.currency_symbol); col_vals[6]=::StringFormat("'%s'", curr_country.url_name); if(!db_obj.InsertSingleRow(col_names, col_vals)) { db_obj.TransactionRollback(); db_obj.Close(); return; } db_obj.FinalizeSqlRequest(); } if(!db_obj.TransactionCommit()) ::PrintFormat("Failed to complete transaction execution, error %d", ::GetLastError()); } //--- print if(db_obj.PrintTable()<0) ::PrintFormat("Failed to print the table \"%s\", error %d", table_name, ::GetLastError()); } }
Um mit der Tabelle weiterarbeiten zu können, müssen wir sie zunächst mit der Methode CDatabase::SelectTable() auswählen. Hier können wir eine Analogie dazu ziehen, wie eine Handelsposition mit Hilfe der nativen Funktion ::PositionSelect() für ihre weitere Verarbeitung ausgewählt wird.
Anschließend wird die Tabelle mit der Methode CDatabase::EmptyTable() vorläufig geleert.
Gehen Sie dann in einer Schleife durch die Länder und füllen Sie die Tabelle nach Spalten
- „COUNTRY_ID“,
- „COUNTRY_NAME“,
- „COUNTRY_CODE“,
- „CONTINENT“,
- „CURRENCY“,
- „CURRENCY_SYMBOL“,
- „URL_NAME“.
Die letzte Zeile wird mit der Methode CDatabase::InsertSingleRow() in die Tabelle eingefügt. Das Füllen der Tabelle erfolgt über einen transaktionalen Mechanismus. Weitere Informationen finden Sie im Abschnitt „Beschleunigung von Transaktionen durch Einhüllen in DatabaseTransactionBegin()/DatabaseTransactionCommit()“.
Das Füllen der drei Tabellen führte zu folgenden Ergebnissen: Die Tabelle COUNTRIES enthält 23 Einträge, die Tabelle EVENTS enthält 1500 Einträge und die Tabelle EVENT_VALUES 158 696 Einträge (Abb. 11).
Abb. 11. Gefüllte Tabelle EVENT_VALUES
Da wir nun die Daten haben, können wir mit der Erstellung der Abfragen beginnen.
3.2 Datenbankabfragen
Im Großen und Ganzen lassen sich alle Datenbankabfragen in zwei Gruppen einteilen:
1) Anfragen, die Daten aus der Datenbank abrufen;
2) Anfragen, die Daten in der Datenbank verändern.
Lassen Sie uns zunächst die Beispiele für den Abruf von Informationen aus der Kalenderdatenbank behandeln.
3.2.1 Stichprobenartige Anzahl von Ereignissen nach Ländern
Fragen wir zunächst die Datenbank, wie viele makroökonomische Ereignisse es in jedem Land gibt. Wir erstellen die folgende Abfrage unter Bezugnahme auf die Tabelle „EVENTS“:
SELECT COUNTRY_ID AS id, COUNT(EVENT_ID) AS events_num FROM EVENTS GROUP BY COUNTRY_ID
Im MQL5-Code ist eine solche Anfrage wie folgt implementiert:
//--- 1) group events number by country id string table_name="EVENTS"; if(db_obj.SelectTable(table_name)) { string col_names_to_select[]= { "COUNTRY_ID AS id", "COUNT(EVENT_ID) AS events_num" }; string gr_names[]= { "COUNTRY_ID" }; if(!db_obj.SelectFromGroupBy(col_names_to_select, gr_names)) { db_obj.Close(); return; } //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest();
Das Ergebnis ist die folgende Auswahl nach den Quellspalten COUNTRY_ID und COUNT(EVENT_ID), die im Terminalprotokoll angezeigt wird:
sRequest1 (EURUSD,H1) #| id events_num sRequest1 (EURUSD,H1) --+--------------- sRequest1 (EURUSD,H1) 1| 0 7 sRequest1 (EURUSD,H1) 2| 36 85 sRequest1 (EURUSD,H1) 3| 76 55 sRequest1 (EURUSD,H1) 4| 124 74 sRequest1 (EURUSD,H1) 5| 156 40 sRequest1 (EURUSD,H1) 6| 250 43 sRequest1 (EURUSD,H1) 7| 276 62 sRequest1 (EURUSD,H1) 8| 344 26 sRequest1 (EURUSD,H1) 9| 356 57 sRequest1 (EURUSD,H1) 10| 380 52 sRequest1 (EURUSD,H1) 11| 392 124 sRequest1 (EURUSD,H1) 12| 410 36 sRequest1 (EURUSD,H1) 13| 484 47 sRequest1 (EURUSD,H1) 14| 554 82 sRequest1 (EURUSD,H1) 15| 578 47 sRequest1 (EURUSD,H1) 16| 702 27 sRequest1 (EURUSD,H1) 17| 710 54 sRequest1 (EURUSD,H1) 18| 724 39 sRequest1 (EURUSD,H1) 19| 752 59 sRequest1 (EURUSD,H1) 20| 756 40 sRequest1 (EURUSD,H1) 21| 826 115 sRequest1 (EURUSD,H1) 22| 840 247 sRequest1 (EURUSD,H1) 23| 999 82
Die Auswahl sieht nicht sehr lesbar aus, weil die Spalte „id“ eine Länder-ID und kein Ländername ist. Die Ländernamen sind in der Tabelle LÄNDER zu finden.
Um den Namen des Landes und die Anzahl der Länderereignisse zu erhalten, müssen wir eine zusammengesetzte Abfrage erstellen (eine Abfrage innerhalb einer Abfrage).
Die erste Version einer solchen Verbundabfrage sieht wie folgt aus:
SELECT c.NAME AS country, ev.events_num AS events_number FROM COUNTRIES c JOIN ( SELECT COUNTRY_ID AS id, COUNT(EVENT_ID) AS events_num FROM EVENTS GROUP BY COUNTRY_ID ) AS ev ON c.COUNTRY_ID = ev.id
Diese Option verwendet die Abfrage, die wir zu Beginn erstellt haben. Aber jetzt ist sie Teil einer anderen Abfrage geworden, wodurch sich ihre Form in die Form einer Unterabfrage geändert hat.
Die zweite Version der Anfrage kann in Form von CTE umgesetzt werden.
WITH ev_cnt AS ( SELECT COUNTRY_ID AS id, COUNT(EVENT_ID) AS events_num FROM EVENTS GROUP BY COUNTRY_ID ) SELECT c.NAME AS country, ev.events_num AS events_number FROM COUNTRIES c INNER JOIN ev_cnt AS ev ON c.COUNTRY_ID = ev.id
Im MQL5-Code ist eine zusammengesetzte Abfrage wie folgt implementiert:
//--- 2) group events number by country name using a subquery ::Print("\nGroup events number by country name using a subquery:\n"); string subquery=db_obj.SqlRequest(); string new_sql_request=::StringFormat("SELECT c.NAME AS country," "ev.events_num AS events_number FROM COUNTRIES c " "JOIN(%s) AS ev " "ON c.COUNTRY_ID=ev.id", subquery); if(!db_obj.Select(new_sql_request)) { db_obj.Close(); return; } //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest();
Der Tabellenbefehl (CTE) ist wie folgt implementiert:
//--- 3) group events number by country name using CTE ::Print("\nGroup events number by country name using CTE:\n"); new_sql_request=::StringFormat("WITH ev_cnt AS (%s)" "SELECT c.NAME AS country," "ev.events_num AS events_number FROM COUNTRIES c " "INNER JOIN ev_cnt AS ev ON c.COUNTRY_ID=ev.id", subquery); if(!db_obj.Select(new_sql_request)) { db_obj.Close(); return; } //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest();
Beide Optionen geben die folgenden Abfrageergebnisse im Protokoll aus:
sRequest1 (EURUSD,H1) #| country events_number sRequest1 (EURUSD,H1) --+----------------------------- sRequest1 (EURUSD,H1) 1| Worldwide 7 sRequest1 (EURUSD,H1) 2| Australia 85 sRequest1 (EURUSD,H1) 3| Brazil 55 sRequest1 (EURUSD,H1) 4| Canada 74 sRequest1 (EURUSD,H1) 5| China 40 sRequest1 (EURUSD,H1) 6| France 43 sRequest1 (EURUSD,H1) 7| Germany 62 sRequest1 (EURUSD,H1) 8| Hong Kong 26 sRequest1 (EURUSD,H1) 9| India 57 sRequest1 (EURUSD,H1) 10| Italy 52 sRequest1 (EURUSD,H1) 11| Japan 124 sRequest1 (EURUSD,H1) 12| South Korea 36 sRequest1 (EURUSD,H1) 13| Mexico 47 sRequest1 (EURUSD,H1) 14| New Zealand 82 sRequest1 (EURUSD,H1) 15| Norway 47 sRequest1 (EURUSD,H1) 16| Singapore 27 sRequest1 (EURUSD,H1) 17| South Africa 54 sRequest1 (EURUSD,H1) 18| Spain 39 sRequest1 (EURUSD,H1) 19| Sweden 59 sRequest1 (EURUSD,H1) 20| Switzerland 40 sRequest1 (EURUSD,H1) 21| United Kingdom 115 sRequest1 (EURUSD,H1) 22| United States 247 sRequest1 (EURUSD,H1) 23| European Union 82
Es ist leicht zu erkennen, dass der Kalender den Ereignissen in den USA die größte Aufmerksamkeit schenkt - es sind 247 an der Zahl.
Erschweren wir die Aufgabe ein wenig und fügen wir der Stichprobe eine Spalte hinzu, in der wir berechnen, wie viele wichtige Ereignisse in einem bestimmten Land stattfinden. Die Wichtigkeit wird in der Spalte IMPORTANCE definiert. Es werden nur die Ereignisse ausgewählt, die den Wert Hoch haben.
Lassen Sie uns zunächst mit der Tabelle EVENTS arbeiten. Hier müssen wir zwei Muster erstellen. Die erste Stichprobe ist eine Zählung der Anzahl der Ereignisse nach Ländern. Diese Aufgabe wurde bereits oben erledigt. Die zweite Stichprobe ist eine Zählung der Anzahl der wichtigen Ereignisse nach Ländern. Schließlich müssen wir beide Stichproben kombinieren.
Der SQL-Code der Abfrage sieht wie folgt aus:
SELECT evn.COUNTRY_ID AS id, COUNT(EVENT_ID) AS events_num, imp.high AS imp_events_num FROM EVENTS evn JOIN ( SELECT COUNTRY_ID AS id, COUNT(IMPORTANCE) AS high FROM EVENTS WHERE IMPORTANCE = 'High' GROUP BY COUNTRY_ID ) AS imp ON evn.COUNTRY_ID = imp.id GROUP BY COUNTRY_ID
Was die MQL5-Implementierung betrifft, so sieht der Code wie folgt aus:
//--- 5) important events - ids, events number and important events number ::Print("\nGroup events number and important events number by country id"); subquery=db_obj.SqlRequest(); string new_sql_request4=::StringFormat("SELECT ev.COUNTRY_ID AS id, COUNT(EVENT_ID) AS events_num," "imp.high AS imp_events_num " "FROM EVENTS ev JOIN (%s) AS imp " "ON ev.COUNTRY_ID=imp.id GROUP BY COUNTRY_ID", subquery); if(!db_obj.Select(new_sql_request4)) { db_obj.Close(); return; } //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest();
Als Ergebnis erhalten wir die folgenden Protokolleinträge:
sRequest1 (EURUSD,H1) Group events number and important events number by country id: sRequest1 (EURUSD,H1) sRequest1 (EURUSD,H1) #| id events_num imp_events_num sRequest1 (EURUSD,H1) --+------------------------------ sRequest1 (EURUSD,H1) 1| 0 7 2 sRequest1 (EURUSD,H1) 2| 36 85 5 sRequest1 (EURUSD,H1) 3| 76 55 2 sRequest1 (EURUSD,H1) 4| 124 74 10 sRequest1 (EURUSD,H1) 5| 156 40 5 sRequest1 (EURUSD,H1) 6| 250 43 1 sRequest1 (EURUSD,H1) 7| 276 62 3 sRequest1 (EURUSD,H1) 8| 344 26 1 sRequest1 (EURUSD,H1) 9| 356 57 2 sRequest1 (EURUSD,H1) 10| 392 124 7 sRequest1 (EURUSD,H1) 11| 410 36 2 sRequest1 (EURUSD,H1) 12| 484 47 2 sRequest1 (EURUSD,H1) 13| 554 82 8 sRequest1 (EURUSD,H1) 14| 578 47 2 sRequest1 (EURUSD,H1) 15| 702 27 1 sRequest1 (EURUSD,H1) 16| 710 54 2 sRequest1 (EURUSD,H1) 17| 752 59 1 sRequest1 (EURUSD,H1) 18| 756 40 4 sRequest1 (EURUSD,H1) 19| 826 115 13 sRequest1 (EURUSD,H1) 20| 840 247 20 sRequest1 (EURUSD,H1) 21| 999 82 11
In der endgültigen Auswahl muss nur noch die Spalte „id“ durch „country“ ersetzt werden.
Lassen Sie uns wieder eine zusammengesetzte Abfrage erstellen. Wir werden uns die Tatsache zunutze machen, dass seine Teile früher geschrieben wurden. Am Ende sortieren wir die Stichprobe in absteigender Reihenfolge nach den Werten in der Spalte „imp_events_number“. Die zusammengesetzte Abfrage sieht wie folgt aus:
SELECT c.NAME AS country, ev.events_num AS events_number, ev.imp_events_num AS imp_events_number FROM COUNTRIES c JOIN ( SELECT ev.COUNTRY_ID AS id, COUNT(EVENT_ID) AS events_num, imp.high AS imp_events_num FROM EVENTS ev JOIN ( SELECT COUNTRY_ID AS id, COUNT(IMPORTANCE) AS high FROM EVENTS WHERE IMPORTANCE = 'High' GROUP BY COUNTRY_ID ) AS imp ON ev.COUNTRY_ID = imp.id GROUP BY COUNTRY_ID ) AS ev ON c.COUNTRY_ID = ev.id ORDER BY imp_events_number DESC
Im MQL5-Code ist die Anfrage wie folgt implementiert:
//--- 6) important events - countries, events number and important events number ::Print("\nGroup events number and important events number by country:\n"); subquery=db_obj.SqlRequest(); string new_sql_request5=::StringFormat("SELECT c.NAME AS country," "ev.events_num AS events_number," "ev.imp_events_num AS imp_events_number " "FROM COUNTRIES c " "JOIN(%s) AS ev " "ON c.COUNTRY_ID=ev.id " "ORDER BY imp_events_number DESC", subquery); if(!db_obj.Select(new_sql_request5)) { db_obj.Close(); return; } //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest();
Jetzt erhalten wir das gewünschte Muster im Protokoll:
sRequest1 (EURUSD,H1) Group events number and important events number by country: sRequest1 (EURUSD,H1) sRequest1 (EURUSD,H1) #| country events_number imp_events_number sRequest1 (EURUSD,H1) --+----------------------------------------------- sRequest1 (EURUSD,H1) 1| United States 247 20 sRequest1 (EURUSD,H1) 2| United Kingdom 115 13 sRequest1 (EURUSD,H1) 3| European Union 82 11 sRequest1 (EURUSD,H1) 4| Canada 74 10 sRequest1 (EURUSD,H1) 5| New Zealand 82 8 sRequest1 (EURUSD,H1) 6| Japan 124 7 sRequest1 (EURUSD,H1) 7| Australia 85 5 sRequest1 (EURUSD,H1) 8| China 40 5 sRequest1 (EURUSD,H1) 9| Switzerland 40 4 sRequest1 (EURUSD,H1) 10| Germany 62 3 sRequest1 (EURUSD,H1) 11| Worldwide 7 2 sRequest1 (EURUSD,H1) 12| Brazil 55 2 sRequest1 (EURUSD,H1) 13| India 57 2 sRequest1 (EURUSD,H1) 14| South Korea 36 2 sRequest1 (EURUSD,H1) 15| Mexico 47 2 sRequest1 (EURUSD,H1) 16| Norway 47 2 sRequest1 (EURUSD,H1) 17| South Africa 54 2 sRequest1 (EURUSD,H1) 18| France 43 1 sRequest1 (EURUSD,H1) 19| Hong Kong 26 1 sRequest1 (EURUSD,H1) 20| Singapore 27 1 sRequest1 (EURUSD,H1) 21| Sweden 59 1
Wie aus der Stichprobe hervorgeht, haben die Vereinigten Staaten die meisten wichtigen Ereignisse - 20. An zweiter Stelle steht das Vereinigte Königreich - 13. Den dritten Platz belegt die EU mit 11. Japan belegt 6. Platz - 7.
Verwenden wir eine Abfrage, um die Länder zu finden, in denen keine wichtigen Ereignisse stattfinden. Zu diesem Zweck müssen wir die Differenz zwischen den beiden Stichproben ermitteln. Die erste Stichprobe enthält alle Länder aus der Tabelle COUNTRIES, die zweite - die Spalte mit den Ländern aus der vorherigen zusammengesetzten Abfrage.
In diesem Fall sieht der SQL-Code wie folgt aus:
SELECT NAME FROM COUNTRIES EXCEPT SELECT country FROM ( SELECT c.NAME AS country, ev.events_num AS events_number, ev.imp_events_num AS imp_events_number FROM COUNTRIES c JOIN ( SELECT ev.COUNTRY_ID AS id, COUNT(EVENT_ID) AS events_num, imp.high AS imp_events_num FROM EVENTS ev JOIN ( SELECT COUNTRY_ID AS id, COUNT(IMPORTANCE) AS high FROM EVENTS WHERE IMPORTANCE = 'High' GROUP BY COUNTRY_ID ) AS imp ON ev.COUNTRY_ID = imp.id GROUP BY COUNTRY_ID ) AS ev ON c.COUNTRY_ID = ev.id )
Der MQL5-Code sieht einfacher aus, da wir uns die Tatsache zunutze machen, dass die vorherige Abfrage zu unserer neuen Unterabfrage wird.
//--- 7) countries having no important events ::Print("\nCountries having no important events:\n"); string last_request=db_obj.SqlRequest(); string new_sql_request6=::StringFormat("SELECT NAME FROM COUNTRIES " "EXCEPT SELECT country FROM (%s)", last_request); if(!db_obj.Select(new_sql_request6)) { db_obj.Close(); return; } //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest();
Nach Abschluss der Codeausführung erhalten wir folgende Einträge im Protokoll:
sRequest1 (EURUSD,H1) Countries having no important events: sRequest1 (EURUSD,H1) sRequest1 (EURUSD,H1) #| NAME sRequest1 (EURUSD,H1) -+------ sRequest1 (EURUSD,H1) 1| Italy sRequest1 (EURUSD,H1) 2| Spain
Von allen Ländern haben also nur Italien und Spanien keine wichtigen Ereignisse. Anfragen über Länderereignisse in MQL5 wurden im Skript sRequest1.mq5 ausgeführt.
3.2.2 Stichprobe der BIP-Werte nach Ländern
In diesem Beispiel werden wir eine Datenbankabfrage durchführen, um eine Auswahl von BIP-Werten für verschiedene Länder zu erhalten. Als Wert des BIP nehmen wir den Parameter „Bruttoinlandsprodukt (BIP) q/q“ (für das 3. Quartal).
Es wird mehrere Proben geben, sodass die Abfrage zusammengesetzt sein wird.
Zunächst wollen wir herausfinden, in welchen Ländern es einen vierteljährlichen BIP-Indikator gibt.
Der SQL-Code sieht wie folgt aus:
SELECT COUNTRY_ID, EVENT_ID FROM EVENTS WHERE (NAME LIKE 'GDP q/q' AND SECTOR = 'Gross Domestic Product')
Die MQL5-Implementierung sieht wie folgt aus (Skript sRequest2.mq5):
//--- 1) countries by id where the indicator '%GDP q/q%' exists string col_names[]= {"COUNTRY_ID", "EVENT_ID"}; string where_condition="(NAME LIKE 'GDP q/q' AND SECTOR='Gross Domestic Product')"; if(!db_obj.SelectFromWhere(col_names, where_condition)) { db_obj.Close(); return; } ::Print("\nCountries by id where the indicator 'GDP q/q' exists:\n"); //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest();
Nachfolgend finden Sie einen Ausdruck aus dem Protokoll, nachdem die Abfrage ausgeführt wurde:
sRequest2 (EURUSD,H1) Countries by id where the indicator 'GDP q/q' exists: sRequest2 (EURUSD,H1) sRequest2 (EURUSD,H1) #| COUNTRY_ID EVENT_ID sRequest2 (EURUSD,H1) --+--------------------- sRequest2 (EURUSD,H1) 1| 554 554010024 sRequest2 (EURUSD,H1) 2| 999 999030016 sRequest2 (EURUSD,H1) 3| 392 392010001 sRequest2 (EURUSD,H1) 4| 124 124010022 sRequest2 (EURUSD,H1) 5| 36 36010019 sRequest2 (EURUSD,H1) 6| 156 156010004 sRequest2 (EURUSD,H1) 7| 380 380010020 sRequest2 (EURUSD,H1) 8| 702 702010004 sRequest2 (EURUSD,H1) 9| 276 276010008 sRequest2 (EURUSD,H1) 10| 250 250010005 sRequest2 (EURUSD,H1) 11| 76 76010010 sRequest2 (EURUSD,H1) 12| 484 484020016 sRequest2 (EURUSD,H1) 13| 710 710060009 sRequest2 (EURUSD,H1) 14| 344 344020002 sRequest2 (EURUSD,H1) 15| 578 578020012 sRequest2 (EURUSD,H1) 16| 840 840010007 sRequest2 (EURUSD,H1) 17| 826 826010037 sRequest2 (EURUSD,H1) 18| 756 756040001 sRequest2 (EURUSD,H1) 19| 410 410010011 sRequest2 (EURUSD,H1) 20| 724 724010005 sRequest2 (EURUSD,H1) 21| 752 752010019
Wie wir sehen können, gibt es den erforderlichen Indikator in 21 Ländern. Der Indikator wird in Indien nicht als globaler Indikator verwendet („Worldwide“).
Nun müssen wir eine Stichprobe von Indikatorwerten für das 3. Quartal erhalten und diese mit der ersten Auswahl nach Ereignis-ID verknüpfen.
Die SQL-Abfrage sieht wie folgt aus:
SELECT evs.COUNTRY_ID AS country_id, evals.EVENT_ID AS event_id, evals.VALUE_ID AS value_id, evals.PERIOD AS period, evals.TIME AS time, evals.ACTUAL AS actual FROM EVENT_VALUES evals JOIN ( SELECT COUNTRY_ID, EVENT_ID FROM EVENTS WHERE (NAME LIKE 'GDP q/q' AND SECTOR = 'Gross Domestic Product') ) AS evs ON evals.event_id = evs.EVENT_ID WHERE (period = '2022.07.01 00:00' )
Was den MQL5-Code betrifft, so ist die verbundene Abfrage wie folgt implementiert:
//--- 2) 'GDP y/y' event and last values string subquery=db_obj.SqlRequest(); string new_sql_request1=::StringFormat("SELECT evs.COUNTRY_ID AS country_id," "evals.EVENT_ID AS event_id," "evals.VALUE_ID AS value_id," "evals.PERIOD AS period," "evals.TIME AS time," "evals.ACTUAL AS actual " "FROM EVENT_VALUES evals " "JOIN(%s) AS evs ON evals.event_id = evs.event_id " " WHERE (period = \'2022.07.01 00:00\')", subquery); if(!db_obj.Select(new_sql_request1)) { db_obj.Close(); return; } ::Print("\n'GDP y/y' event and last values:\n"); //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest();
Nach der Ausführung erscheinen die folgenden Zeilen im Protokoll:
sRequest2 (EURUSD,H1) 'GDP q/q' event and last values: sRequest2 (EURUSD,H1) sRequest2 (EURUSD,H1) #| country_id event_id value_id period time actual sRequest2 (EURUSD,H1) --+----------------------------------------------------------------------- sRequest2 (EURUSD,H1) 1| 554 554010024 168293 2022.07.01 00:00 2022.12.14 23:45 2.0 sRequest2 (EURUSD,H1) 2| 999 999030016 158836 2022.07.01 00:00 2022.10.31 12:00 0.2 sRequest2 (EURUSD,H1) 3| 999 999030016 158837 2022.07.01 00:00 2022.11.15 12:00 0.2 sRequest2 (EURUSD,H1) 4| 999 999030016 158838 2022.07.01 00:00 2022.12.07 12:00 0.3 sRequest2 (EURUSD,H1) 5| 392 392010001 165181 2022.07.01 00:00 2022.11.15 01:50 -0.3 sRequest2 (EURUSD,H1) 6| 392 392010001 165182 2022.07.01 00:00 2022.12.08 01:50 -0.2 sRequest2 (EURUSD,H1) 7| 124 124010022 161963 2022.07.01 00:00 2022.11.29 15:30 0.7 sRequest2 (EURUSD,H1) 8| 36 36010019 173679 2022.07.01 00:00 2022.12.07 02:30 0.6 sRequest2 (EURUSD,H1) 9| 156 156010004 172459 2022.07.01 00:00 2022.10.24 04:00 3.9 sRequest2 (EURUSD,H1) 10| 380 380010020 162296 2022.07.01 00:00 2022.10.31 11:00 0.5 sRequest2 (EURUSD,H1) 11| 380 380010020 162297 2022.07.01 00:00 2022.11.30 11:00 0.5 sRequest2 (EURUSD,H1) 12| 702 702010004 167581 2022.07.01 00:00 2022.10.14 02:00 1.5 sRequest2 (EURUSD,H1) 13| 702 702010004 174527 2022.07.01 00:00 2022.11.23 02:00 1.1 sRequest2 (EURUSD,H1) 14| 276 276010008 172410 2022.07.01 00:00 2022.10.28 10:00 0.3 sRequest2 (EURUSD,H1) 15| 276 276010008 157759 2022.07.01 00:00 2022.11.25 09:00 0.4 sRequest2 (EURUSD,H1) 16| 250 250010005 169062 2022.07.01 00:00 2022.10.28 07:30 0.2 sRequest2 (EURUSD,H1) 17| 250 250010005 169389 2022.07.01 00:00 2022.11.30 09:45 0.2 sRequest2 (EURUSD,H1) 18| 76 76010010 173825 2022.07.01 00:00 2022.12.01 14:00 0.4 sRequest2 (EURUSD,H1) 19| 484 484020016 166108 2022.07.01 00:00 2022.10.31 14:00 1.0 sRequest2 (EURUSD,H1) 20| 484 484020016 166109 2022.07.01 00:00 2022.11.25 14:00 0.9 sRequest2 (EURUSD,H1) 21| 710 710060009 175234 2022.07.01 00:00 2022.12.06 11:30 1.6 sRequest2 (EURUSD,H1) 22| 344 344020002 155337 2022.07.01 00:00 2022.10.31 10:30 -2.6 sRequest2 (EURUSD,H1) 23| 344 344020002 155338 2022.07.01 00:00 2022.11.11 10:30 -2.6 sRequest2 (EURUSD,H1) 24| 578 578020012 172320 2022.07.01 00:00 2022.11.18 09:00 1.5 sRequest2 (EURUSD,H1) 25| 840 840010007 163417 2022.07.01 00:00 2022.10.27 14:30 2.6 sRequest2 (EURUSD,H1) 26| 840 840010007 163418 2022.07.01 00:00 2022.11.30 15:30 2.9 sRequest2 (EURUSD,H1) 27| 840 840010007 163419 2022.07.01 00:00 2022.12.22 15:30 3.2 sRequest2 (EURUSD,H1) 28| 826 826010037 157174 2022.07.01 00:00 2022.11.11 09:00 -0.2 sRequest2 (EURUSD,H1) 29| 826 826010037 157175 2022.07.01 00:00 2022.12.22 09:00 -0.3 sRequest2 (EURUSD,H1) 30| 756 756040001 159276 2022.07.01 00:00 2022.11.29 10:00 0.2 sRequest2 (EURUSD,H1) 31| 410 410010011 161626 2022.07.01 00:00 2022.10.27 01:00 0.3 sRequest2 (EURUSD,H1) 32| 410 410010011 161627 2022.07.01 00:00 2022.12.01 01:00 0.3 sRequest2 (EURUSD,H1) 33| 724 724010005 159814 2022.07.01 00:00 2022.10.28 09:00 0.2 sRequest2 (EURUSD,H1) 34| 724 724010005 159815 2022.07.01 00:00 2022.12.23 10:00 0.1 sRequest2 (EURUSD,H1) 35| 752 752010019 170359 2022.07.01 00:00 2022.10.28 08:00 0.7 sRequest2 (EURUSD,H1) 36| 752 752010019 171381 2022.07.01 00:00 2022.11.29 09:00 0.6
Es ist leicht zu erkennen, dass es in der Stichprobe mehrere Werte für einige Ereignisse mit der gleichen event_id gibt. Die Einträge 2-4 beziehen sich zum Beispiel auf den Parameter EU. Mehrere Zahlen des BIP wurden geschätzt, sodass es mehrere Parameterwerte gibt. Im Ergebnis enthält die endgültige Stichprobe 36 Einträge, was deutlich mehr ist als die Anzahl der Länder, für die der Parameter berechnet wurde.
Wenn wir eine Stichprobe erstellen wollen, indem wir nur die neuesten Werte für ein bestimmtes Ereignis abrufen, müssen wir in der Abfrage die Möglichkeit zum Gruppieren und Sortieren von Gruppenergebnissen hinzufügen. Dann erhalten wir die folgende zusammengesetzte SQL-Abfrage:
SELECT evs.COUNTRY_ID AS country_id, evals.EVENT_ID AS event_id, evals.VALUE_ID AS value_id, evals.PERIOD AS period, evals.TIME AS time, evals.ACTUAL AS actual FROM EVENT_VALUES evals JOIN ( SELECT COUNTRY_ID, EVENT_ID FROM EVENTS WHERE (NAME LIKE 'GDP q/q' AND SECTOR = 'Gross Domestic Product') ) AS evs ON evals.event_id = evs.EVENT_ID WHERE (period = '2022.07.01 00:00' ) GROUP BY evals.event_id HAVING MAX(value_id)
Die Einträge werden nach der Spalte „event_id“ (Feld) gruppiert. Wenn es mehrere Einträge gibt, wird derjenige mit dem höchsten Wert in der Spalte „value_id“ (Feld) verwendet. Daher wird in diesem Fall nur einer der drei Einträge für die EU ausgewählt:
country_id | event_id | value_id | period | time | actual |
---|---|---|---|---|---|
999 | 999030016 | 158838 | 2022.07.01 00:00 | 2022.12.07 12:00 | 0.3 |
Infolgedessen erscheinen die folgenden Einträge im Protokoll:
sRequest2 (EURUSD,H1) 'GDP q/q' event and grouped last values: sRequest2 (EURUSD,H1) sRequest2 (EURUSD,H1) #| country_id event_id value_id period time actual sRequest2 (EURUSD,H1) --+----------------------------------------------------------------------- sRequest2 (EURUSD,H1) 1| 36 36010019 173679 2022.07.01 00:00 2022.12.07 02:30 0.6 sRequest2 (EURUSD,H1) 2| 76 76010010 173825 2022.07.01 00:00 2022.12.01 14:00 0.4 sRequest2 (EURUSD,H1) 3| 124 124010022 161963 2022.07.01 00:00 2022.11.29 15:30 0.7 sRequest2 (EURUSD,H1) 4| 156 156010004 172459 2022.07.01 00:00 2022.10.24 04:00 3.9 sRequest2 (EURUSD,H1) 5| 250 250010005 169389 2022.07.01 00:00 2022.11.30 09:45 0.2 sRequest2 (EURUSD,H1) 6| 276 276010008 172410 2022.07.01 00:00 2022.10.28 10:00 0.3 sRequest2 (EURUSD,H1) 7| 344 344020002 155338 2022.07.01 00:00 2022.11.11 10:30 -2.6 sRequest2 (EURUSD,H1) 8| 380 380010020 162297 2022.07.01 00:00 2022.11.30 11:00 0.5 sRequest2 (EURUSD,H1) 9| 392 392010001 165182 2022.07.01 00:00 2022.12.08 01:50 -0.2 sRequest2 (EURUSD,H1) 10| 410 410010011 161627 2022.07.01 00:00 2022.12.01 01:00 0.3 sRequest2 (EURUSD,H1) 11| 484 484020016 166109 2022.07.01 00:00 2022.11.25 14:00 0.9 sRequest2 (EURUSD,H1) 12| 554 554010024 168293 2022.07.01 00:00 2022.12.14 23:45 2.0 sRequest2 (EURUSD,H1) 13| 578 578020012 172320 2022.07.01 00:00 2022.11.18 09:00 1.5 sRequest2 (EURUSD,H1) 14| 702 702010004 174527 2022.07.01 00:00 2022.11.23 02:00 1.1 sRequest2 (EURUSD,H1) 15| 710 710060009 175234 2022.07.01 00:00 2022.12.06 11:30 1.6 sRequest2 (EURUSD,H1) 16| 724 724010005 159815 2022.07.01 00:00 2022.12.23 10:00 0.1 sRequest2 (EURUSD,H1) 17| 752 752010019 171381 2022.07.01 00:00 2022.11.29 09:00 0.6 sRequest2 (EURUSD,H1) 18| 756 756040001 159276 2022.07.01 00:00 2022.11.29 10:00 0.2 sRequest2 (EURUSD,H1) 19| 826 826010037 157175 2022.07.01 00:00 2022.12.22 09:00 -0.3 sRequest2 (EURUSD,H1) 20| 840 840010007 163419 2022.07.01 00:00 2022.12.22 15:30 3.2 sRequest2 (EURUSD,H1) 21| 999 999030016 158838 2022.07.01 00:00 2022.12.07 12:00 0.3
Nun sind 21 Einträge in der Stichprobe vorhanden. Schließlich müssen wir den Ländercode durch seinen Namen ersetzen. Ändern wir die vorherige SLQ-Abfrage wie folgt:
SELECT c.NAME AS country, ev_evals.event_id AS event_id, ev_evals.value_id AS value_id, ev_evals.period AS period, ev_evals.TIME AS time, ev_evals.ACTUAL AS actual FROM COUNTRIES c JOIN ( SELECT evs.COUNTRY_ID AS country_id, evals.EVENT_ID AS event_id, evals.VALUE_ID AS value_id, evals.PERIOD AS period, evals.TIME AS time, evals.ACTUAL AS actual FROM EVENT_VALUES evals JOIN ( SELECT COUNTRY_ID, EVENT_ID FROM EVENTS WHERE (NAME LIKE 'GDP q/q' AND SECTOR = 'Gross Domestic Product') ) AS evs ON evals.event_id = evs.EVENT_ID WHERE (period = '2022.07.01 00:00') GROUP BY evals.event_id HAVING MAX(value_id) ) AS ev_evals ON c.COUNTRY_ID = ev_evals.country_id
Wir implementieren auf dem Weg dorthin die folgende zusammengesetzte Abfrage in MQL5:
//--- 4) 'GDP q/q' event and grouped last values with country names subquery=db_obj.SqlRequest(); string new_sql_request3=::StringFormat("SELECT c.NAME AS country," "ev_evals.event_id AS event_id," "ev_evals.value_id AS value_id," "ev_evals.period AS period," "ev_evals.TIME AS time," "ev_evals.ACTUAL AS actual " "FROM COUNTRIES c JOIN (%s) " "AS ev_evals ON c.COUNTRY_ID = ev_evals.country_id", subquery); if(!db_obj.Select(new_sql_request3)) { db_obj.Close(); return; } ::Print("\n'GDP q/q' event and grouped last values with country names:\n"); //--- print the SQL request if(db_obj.PrintSqlRequest()<0) ::PrintFormat("Failed to print the SQL request, error %d", ::GetLastError()); db_obj.FinalizeSqlRequest();
Das gewünschte Muster wird ins Journal ausgedruckt:
sRequest2 (EURUSD,H1) 'GDP q/q' event and grouped last values with country names: sRequest2 (EURUSD,H1) sRequest2 (EURUSD,H1) #| country event_id value_id period time actual sRequest2 (EURUSD,H1) --+--------------------------------------------------------------------------- sRequest2 (EURUSD,H1) 1| Australia 36010019 173679 2022.07.01 00:00 2022.12.07 02:30 0.6 sRequest2 (EURUSD,H1) 2| Brazil 76010010 173825 2022.07.01 00:00 2022.12.01 14:00 0.4 sRequest2 (EURUSD,H1) 3| Canada 124010022 161963 2022.07.01 00:00 2022.11.29 15:30 0.7 sRequest2 (EURUSD,H1) 4| China 156010004 172459 2022.07.01 00:00 2022.10.24 04:00 3.9 sRequest2 (EURUSD,H1) 5| France 250010005 169389 2022.07.01 00:00 2022.11.30 09:45 0.2 sRequest2 (EURUSD,H1) 6| Germany 276010008 172410 2022.07.01 00:00 2022.10.28 10:00 0.3 sRequest2 (EURUSD,H1) 7| Hong Kong 344020002 155338 2022.07.01 00:00 2022.11.11 10:30 -2.6 sRequest2 (EURUSD,H1) 8| Italy 380010020 162297 2022.07.01 00:00 2022.11.30 11:00 0.5 sRequest2 (EURUSD,H1) 9| Japan 392010001 165182 2022.07.01 00:00 2022.12.08 01:50 -0.2 sRequest2 (EURUSD,H1) 10| South Korea 410010011 161627 2022.07.01 00:00 2022.12.01 01:00 0.3 sRequest2 (EURUSD,H1) 11| Mexico 484020016 166109 2022.07.01 00:00 2022.11.25 14:00 0.9 sRequest2 (EURUSD,H1) 12| New Zealand 554010024 168293 2022.07.01 00:00 2022.12.14 23:45 2.0 sRequest2 (EURUSD,H1) 13| Norway 578020012 172320 2022.07.01 00:00 2022.11.18 09:00 1.5 sRequest2 (EURUSD,H1) 14| Singapore 702010004 174527 2022.07.01 00:00 2022.11.23 02:00 1.1 sRequest2 (EURUSD,H1) 15| South Africa 710060009 175234 2022.07.01 00:00 2022.12.06 11:30 1.6 sRequest2 (EURUSD,H1) 16| Spain 724010005 159815 2022.07.01 00:00 2022.12.23 10:00 0.1 sRequest2 (EURUSD,H1) 17| Sweden 752010019 171381 2022.07.01 00:00 2022.11.29 09:00 0.6 sRequest2 (EURUSD,H1) 18| Switzerland 756040001 159276 2022.07.01 00:00 2022.11.29 10:00 0.2 sRequest2 (EURUSD,H1) 19| United Kingdom 826010037 157175 2022.07.01 00:00 2022.12.22 09:00 -0.3 sRequest2 (EURUSD,H1) 20| United States 840010007 163419 2022.07.01 00:00 2022.12.22 15:30 3.2 sRequest2 (EURUSD,H1) 21| European Union 999030016 158838 2022.07.01 00:00 2022.12.07 12:00 0.3
Obwohl das Problem in mehreren Ansätzen gelöst wurde, war es durch die Möglichkeit, eine Abfrage in eine andere einzubinden, viel einfacher.
Schlussfolgerung
Ich hoffe, dass der Artikel das Interesse derjenigen Händler und Entwickler wecken wird, die makroökonomische Daten für ihre Strategien nutzen. Ich würde es aber wagen zu behaupten, dass auch keine Makro-Parameter den Aufbau einer guten Strategie ermöglichen. Sie können jedoch als Ergänzung zu den ursprünglichen Daten des neuronalen Netzes nützlich sein.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/11977
- 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.