English Русский 中文 Español 日本語 Português
preview
MQL5 Kochbuch – Der Wirtschaftskalender

MQL5 Kochbuch – Der Wirtschaftskalender

MetaTrader 5Beispiele | 14 Januar 2022, 09:57
707 0
Denis Kirichenko
Denis Kirichenko

Einführung

Das MetaTrader 5-Terminal und die MQL5-Programmiersprache entwickeln sich ständig weiter und erweitern ihre Marktanalysefunktionen, Werkzeuge zur Entwicklung komplexerer Handelsroboter usw. Eines der neuen Arbeitsmittel des Terminals ist der Wirtschaftskalender, der sowohl manuell als auch von Robotern verwendet werden kann.

Der integrierte Kalender ist flexibel genug. Sie können ihn auf der Registerkarte des Terminals Kalender konfigurieren, ihn auf Ihrer Website installieren oder die mobile Version herunterladen. Da ich ein algorithmischer Händler bin, interessieren mich vor allem die Programmierfunktionen des Hilfsmittels.

In diesem Artikel werde ich versuchen, sie herauszuarbeiten.


1. Der Wirtschaftskalender — was steht in derDokumentation?

Werfen wir zunächst einen kurzen Blick auf die dokumentierten Funktionen. Im Allgemeinen sind sie ziemlich einfach. Wie so oft bei der MQL5-Ressource werden die Informationen konsistent dargestellt und durch kleine Beispiele illustriert.


1.1 Die Funktionen für den Wirtschaftskalender

Die Dokumentation beschreibt 10 Kalender-Funktionen:

  1. CalendarCountryById();
  2. CalendarEventById();
  3. CalendarValueById();
  4. CalendarCountries();
  5. CalendarEventByCountry();
  6. CalendarEventByCurrency();
  7. CalendarValueHistoryByEvent();
  8. CalendarValueHistory();
  9. CalendarValueLastByEvent();
  10. CalendarValueLast().

Diese Funktionen geben im Allgemeinen entweder Kalendereigenschaften (Land, Ereignis, Wert) oder historische Ereigniswerte zurück.


1.2 Struktur des Wirtschaftskalenders

Der Entwickler schlägt vor, drei Strukturen zu verwenden: MqlCalendarCountry, MqlCalendarEvent und MqlCalendarValue.


1.2.1  MqlCalendarCountry

Die Struktur liefert detaillierte Informationen über ein Land und die Ereignisse, an denen wir interessiert sind.

Derzeit habe ich die Website Kalender bei mehreren Brokern überprüft: Es gibt Daten für 21 Länder, die Europäische Union und die ganze Welt (globale Ereignisse).

[id]           [name] [code] [currency] [currency_symbol]       [url_name] [reserved]
[ 0]  999 "European Union" "EU"   "EUR"      "€"               "european-union"        ...
[ 1]  124 "Canada"         "CA"   "CAD"      "$"               "canada"                ...
[ 2]   36 "Australia"      "AU"   "AUD"      "$"               "australia"             ...
[ 3]  554 "New Zealand"    "NZ"   "NZD"      "$"               "new-zealand"           ...
[ 4]  392 "Japan"          "JP"   "JPY"      "¥"               "japan"                 ...
[ 5]  156 "China"          "CN"   "CNY"      "¥"               "china"                 ...
[ 6]  276 "Germany"        "DE"   "EUR"      "€"               "germany"               ...
[ 7]  250 "France"         "FR"   "EUR"      "€"               "france"                ...
[ 8]  380 "Italy"          "IT"   "EUR"      "€"               "italy"                 ...
[ 9]   76 "Brazil"         "BR"   "BRL"      "R$"              "brazil"                ...
[10]  344 "Hong Kong"      "HK"   "HKD"      "HK$"             "hong-kong"             ...
[11]  702 "Singapore"      "SG"   "SGD"      "R$"              "singapore"             ...
[12]  484 "Mexico"         "MX"   "MXN"      "Mex$"            "mexico"                ...
[13]  710 "South Africa"   "ZA"   "ZAR"      "R"               "south-africa"          ...
[14]  356 "India"          "IN"   "INR"      "₹"               "india"                 ...
[15]  578 "Norway"         "NO"   "NOK"      "Kr"              "norway"                ...
[16]    0 "Worldwide"      "WW"   "ALL"      ""                "worldwide"             ...
[17]  840 "United States"  "US"   "USD"      "$"               "united-states"         ...
[18]  826 "United Kingdom" "GB"   "GBP"      "£"               "united-kingdom"        ...
[19]  756 "Switzerland"    "CH"   "CHF"      "₣"               "switzerland"           ...
[20]  410 "South Korea"    "KR"   "KRW"      "₩"               "south-korea"           ...
[21]  724 "Spain"          "ES"   "EUR"      "€"               "spain"                 ...
[22]  752 "Sweden"         "SE"   "SEK"      "Kr"              "sweden"                ...

Es ist ein wenig seltsam, dass Russland nicht auf dieser Liste steht. Hoffentlich wird es bald erscheinen.


1.2.2 MqlCalendarEvent

Die Struktur liefert detaillierte Informationen über ein Ereignis. Die Struktur hat eine ganze Reihe von Eigenschaften. Möglicherweise ist dies ein gutes Werkzeug für eine umfassende grundlegende Analyse. Später werde ich überlegen, wie man Ereignisse nach einem bestimmten Kriterium sortieren kann.


1.2.3 MqlCalendarValue

Die Struktur liefert detaillierte Informationen über einen Ereigniswert. Es gibt frühere, aktuelle und voraussichtliche Werte.

Bei der Arbeit mit der Struktur sind die folgenden Feinheiten zu beachten.

Die Feldwerte actual_value, forecast_value, prev_value und revised_prev_value werden millionenfach vergrößert gespeichert. Wenn ein Feldwert nicht gesetzt ist, speichert das Feld LONG_MIN (-9223372036854775808). Wenn der Feldwert jedoch gesetzt ist, sollte er durch 1.000.000 (Million) geteilt werden.

Die Struktur MqlCalendarValue hat ihre eigenen Methoden, die die Arbeit mit den Werten der angegebenen Felder vereinfachen.

Die Methoden lassen sich in zwei Gruppen einteilen.

Die erste Gruppe prüft, ob ein bestimmter Wert angegeben ist:

HasActualValue(void) — gibt true zurück, wenn der aktuelle Wert gesetzt ist; andernfalls wird false zurückgegeben.
HasForecastValue(void) — gibt true zurück, wenn der prognostizierte Wert gesetzt ist; andernfalls wird false zurückgegeben.
HasPreviousValue(void) — gibt true zurück, wenn der vorherige Wert gesetzt ist; andernfalls wird false zurückgegeben.
HasRevisedValue(void) — liefert true, wenn der revidierte Wert gesetzt ist; andernfalls liefert false.

Die zweite Gruppe erhält direkt einen bestimmten Wert:

GetActualValue(void) — liefert den aktuellen Wert eines Ereignisses (double) oder nan (not a number), wenn der entsprechende Wert nicht gesetzt ist.
GetForecastValue(void) — gibt den prognostizierten Wert eines Ereignisses zurück (double) oder nan, wenn der entsprechende Wert nicht gesetzt ist.
GetPreviousValue(void) — gibt den vorherigen Wert eines Ereignisses zurück (double) oder nan, wenn der entsprechende Wert nicht gesetzt ist.
GetRevisedValue(void) — gibt den revidierten Wert eines Ereignisses zurück (double) oder nan, wenn der entsprechende Wert nicht gesetzt ist.

Schauen wir uns an, wie die Struktur MqlCalendarValue ihre Feldwerte empfängt und überprüft. Wir werden uns auf die letzte Zinsentscheidung der Bank of Japan (BoJ) konzentrieren. Wir zeigen die erforderlichen Daten im Journal an, indem wir das Skript Test_empty_value.mq5 verwenden, das drei Ansätze zur Ermittlung des Wertes bietet. 

//+------------------------------------------------------------------+
//| LongDouble                                                       |
//+------------------------------------------------------------------+
union LongDouble
  {
   long   long_value;
   double double_value;
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Bank of Japan (BoJ) Interest Rate Decision on 22 Sep 2021 02:47 GMT
   ulong event_id = 392060022; // "boj-interest-rate-decision"
   MqlCalendarValue values[];
   datetime date_from, date_to;
   date_from = D'22.09.2021';
   date_to = date_from + PeriodSeconds(PERIOD_D1);
   if(::CalendarValueHistoryByEvent(event_id, values, date_from, date_to))
     {
      LongDouble forecast_val;
      //--- 1) "forecast_value" field
      forecast_val.long_value = values[0].forecast_value;
      ::PrintFormat("\"forecast_value\" field: %I64d", forecast_val.long_value);
      //--- 2) MqlCalendarValue::GetForecastValue()
      forecast_val.double_value = values[0].GetForecastValue();
      ::PrintFormat("MqlCalendarValue::GetForecastValue(): %g", forecast_val.double_value);
      //--- 3) MqlCalendarValue::HasForecastValue()
      if(!values[0].HasForecastValue())
         ::PrintFormat("MqlCalendarValue::HasForecastValue(): %s", (string)false);
     }
  }
//+------------------------------------------------------------------+

Beim ersten Ansatz wird einfach der Prognosewert ermittelt. Da es keine Prognose gab, erhalten wir LONG_MIN (-9223372036854775808). Der zweite Ansatz verwendet bereits die Strukturmethode MqlCalendarValue::GetForecastValue(). Sie gibt 'nan' zurück. Der dritte Ansatz ist der vorsichtigste, da er überprüft, ob der Prognosewert überhaupt vorhanden ist. 

Nach dem Start des Skripts erscheinen die folgenden Einträge im Journal:

GR      0       21:23:36.076    Test_empty_value (USDCAD,H1)    "forecast_value" field: -9223372036854775808
LH      0       21:23:36.080    Test_empty_value (USDCAD,H1)    MqlCalendarValue::GetForecastValue(): nan
HM      0       21:23:36.080    Test_empty_value (USDCAD,H1)    MqlCalendarValue::HasForecastValue(): false


1.2.4 Strukturelle Beziehungen

Die Strukturen sind durch die folgenden Beziehungen miteinander verbunden (Abb. 1).

Beziehungen der Enumerationen des Kalenders

Abb. 1. Beziehung der Struktur des Kalenders


Die Struktur MqlCalendarCountry ist mit MqlCalendarEvent über eine Länder-ID verknüpft. "One-to-many"-Beziehungsform (1..*).

Die Struktur MqlCalendarEvent ist über eine Ereignis-ID mit MqlCalendarValue verknüpft. "One-to-many"-Beziehungsform (1..*).


1.3 Fehler

Der Entwickler vergibt bei der Arbeit mit dem Wirtschaftskalender die Gruppe Laufzeitfehler. Dabei handelt es sich um die folgenden Anfragen:

Wirtschaftskalender


ERR_CALENDAR_MORE_DATA
5400 Arraygröße ist zu klein für die Übernahme aller Werte
ERR_CALENDAR_TIMEOUT
5401 Zeitlimit der Anforderung ist überschritten
ERR_CALENDAR_NO_DATA
5402 Land wurde nicht gefunden



2. Hilfsstrukturen und die Klasse CiCalendarInfo

Meine Sympathien liegen eher auf der OOP-Seite. Deshalb werde ich ein Beispiel für eine Klasse vorstellen, die Zugriff auf die Kalendereigenschaften bietet.

Denken Sie daran, dass der Kalender ein ziemlich eklektisches Ding ist. Ich bin kein Datenbankspezialist, aber soweit ich weiß, ist der Kalender im Allgemeinen eine relationale Datenbank mit mehreren Tabellen.

Die angebotene Implementierung der Klasse CiCalendarInfo zielt neben dem Abrufen der Eigenschaften auch auf die Erstellung der Zeitreihe eines ausgewählten Ereignisses ab.

Werfen wir zunächst einen Blick auf die Hilfsstrukturen.


2.1 Struktur der Zeitreihe

Da wir Daten für TS (time series, Zeitreihen) abrufen werden, sollten wir deren programmatische Essenz erstellen. Dafür ist die Struktur SiTimeSeries zuständig.

//+------------------------------------------------------------------+
//| Time series structure                                            |
//+------------------------------------------------------------------+
struct SiTimeSeries
  {
   private:
      bool              init;        // is initialized?
      uint              size;
      datetime          timevals[];  // time values
      double            datavals[];  // data values
      string            name;        // ts name
   public:
      //--- constructor
      void              SiTimeSeries(void);
      //--- destructor
      void             ~SiTimeSeries(void);
      //--- copy consructor
      void              SiTimeSeries(const SiTimeSeries &src_ts);
      //--- assignment operator
      void              operator=(const SiTimeSeries &src_ts);
      //--- equality operator
      bool              operator==(const SiTimeSeries &src_ts);
      //--- indexing operator
      SiTsObservation   operator[](const uint idx) const;
      //--- initialization
      bool              Init(datetime &ts_times[], const double &ts_values[],
                             const string ts_name);
      //--- get series properties
      bool              GetSeries(datetime &dst_times[], double &dst_values[], string &dst_name);
      bool              GetSeries(SiTsObservation &dst_observations[], string &dst_name);
      //--- service
      bool              IsInit(void) const
        {
         return init;
        };
      uint              Size(void) const
        {
         return size;
        };
      void              Print(const int digs = 2, const uint step = 0);
  };
//+------------------------------------------------------------------+

Die Hauptelemente der Struktur sind die Arrays timevals[] und datavals[]. Das erste enthält die Zeitreihen, das zweite die Wertreihen.

Die Struktur ist so implementiert, dass ihre Elemente im privaten Bereich deklariert wurde. Das bedeutet, dass die Zeitreihe nach ihrer Erstellung nicht mehr geändert werden kann.

Im folgenden Beispiel soll die Struktur der Zeitreihe behandelt werden. Das Skript Test_TS.mq5 empfängt Daten zu den US-Arbeitsmarktzahlen vom 1. Januar 2016 bis zum 1. November 2021 und stellt sie in einem wissenschaftlichen Diagramm dar. Das Diagramm soll zwei Kurven enthalten - die tatsächlichen und die prognostizierten Werte. Wir werden den Ereignisberichtszeitraum als Zeitleiste verwenden.

Nach dem Start des Skripts werden erstens die Zeitreihenwerte im Journal angezeigt und zweitens das Diagramm gezeichnet (Abb. 2).


Außerlandwirtschaftliche Daten (2016-2021)

Abb. 2. US-Beschäftigtenzahlen außerhalb der Landwirtschaft (2016-2021)

 

Das Skript hat die folgenden Zeilen, die die Zeitreihenwerte eingetragen:

//--- prepare time and data values for the timeseries
for(int v_idx = 0; v_idx < nfp_values_size; v_idx++)
   {
    MqlCalendarValue curr_nfp_val = nfp_values[v_idx];
    datetime curr_nfp_time = curr_nfp_val.period;
    timevals[v_idx] = curr_nfp_time;
    double curr_nfp_dataval = curr_nfp_val.GetActualValue();
    datavals1[v_idx] = curr_nfp_dataval;
    curr_nfp_dataval = curr_nfp_val.GetForecastValue();
    datavals2[v_idx] = curr_nfp_dataval;
   }

Verwenden Sie die Funktionen MqlCalendarValue::GetActualValue() und MqlCalendarValue::GetForecastValue(), um sofort die erforderlichen Werte zu erhalten.


2.2 Die Struktur der Zeitreihe Beobachtung

Jede Zeitreihe besteht aus Beobachtungen. Für die Beobachtung wurde die folgende einfache Struktur SiTsObservation erstellt.

//+------------------------------------------------------------------+
//| Time series observation structure                                |
//+------------------------------------------------------------------+
struct SiTsObservation
  {
   datetime          time; // timestamp
   double            val;  // value
   //--- constructor
   void              SiTsObservation(void): time(0), val(EMPTY_VALUE) {}
  };
//+------------------------------------------------------------------+

Der Indexierungsoperator wurde in der Zeitreihenstruktur SiTimeSeries deklariert. Er gibt die erforderliche Reihenbeobachtung zurück. Im obigen Beispiel (Zeichnen von Werten auf Nicht-Farmen) besteht die Reihe aus 70 Werten. In diesem Fall können die erste und die letzte Beobachtung auf folgende Weise ermittelt werden:

SiTsObservation first_observation, last_observation;
first_observation = nfp_ts1[0];
last_observation = nfp_ts1[nfp_values_size - 1];
string time_str = ::TimeToString(first_observation.time, TIME_DATE);
string data_str = ::DoubleToString(first_observation.val, 0);
::PrintFormat("\nFirst observation: %s, %s", time_str, data_str);
time_str = ::TimeToString(last_observation.time, TIME_DATE);
data_str = ::DoubleToString(last_observation.val, 0);
::PrintFormat("Last observation: %s, %s", time_str, data_str);

Nach dem Ausführen der angegebenen Code-Zeilen im Journal erhalten wir folgende Einträge:

KJ      0       21:27:16.386    Test_ts (USDCAD,H1)     First observation: 2015.12.01, 292
HO      0       21:27:17.225    Test_ts (USDCAD,H1)     Last observation: 2021.09.01, 194


2.3 Die Klasse CiCalendarInfo

Ich werde die Kontinuität bewahren, indem ich annehme, dass die Klasse für einen vereinfachten Zugriff auf die Kalendereigenschaften und den Erhalt der Ereigniswerte erstellt wird (ähnlich wie CAccountInfo, CSymbolInfo und andere Handelsklassen).

Die Klassendeklaration ist unten angegeben.

//+------------------------------------------------------------------+
//| Class CiCalendarInfo.                                            |
//| Appointment: Class for access to calendar info.                  |
//|              Derives from class CObject.                         |
//+------------------------------------------------------------------+
class CiCalendarInfo : public CObject
  {
      //--- === Data members === ---
   protected:
      string            m_currency;
      ulong             m_country_id;
      MqlCalendarCountry m_country_description;
      ulong             m_event_id;
      MqlCalendarEvent  m_event_description;
      static MqlCalendarCountry m_countries[];
      bool              m_is_init;
      //--- === Methods === ---
   public:
      //--- constructor/destructor
      void           CiCalendarInfo(void);
      void          ~CiCalendarInfo(void) {};
      //--- initialization
      bool           Init
      (
         const string currency = NULL,         // country currency code name
         const ulong country_id = WRONG_VALUE, // country ID
         const ulong event_id = WRONG_VALUE,   // event ID
         const bool to_log = true              // to log?
      );
      void           Deinit(void);
      //--- Сalendar structures descriptions
      bool           CountryDescription(MqlCalendarCountry &country, const bool to_log = false);
      bool           EventDescription(MqlCalendarEvent &event, const bool to_log = false);
      bool           ValueDescription(ulong value_id, MqlCalendarValue &value,
                                      const bool to_log = false);
      bool           EventsByCountryDescription(MqlCalendarEvent &events[], const bool to_log = false);
      bool           EventsByCurrencyDescription(MqlCalendarEvent &events[], const bool to_log = false);
      bool           EventsBySector(const ENUM_CALENDAR_EVENT_SECTOR event_sector,
                                    MqlCalendarEvent &events[], const bool to_log = false);
      //--- Сalendar enum descriptions
      string         EventTypeDescription(const ENUM_CALENDAR_EVENT_TYPE event_type);
      string         EventSectorDescription(const ENUM_CALENDAR_EVENT_SECTOR event_sector);
      string         EventFrequencyDescription(const ENUM_CALENDAR_EVENT_FREQUENCY event_frequency);
      string         EventTimeModeDescription(const ENUM_CALENDAR_EVENT_TIMEMODE event_time_mode);
      string         EventUnitDescription(const ENUM_CALENDAR_EVENT_UNIT event_unit);
      string         EventImportanceDescription(const ENUM_CALENDAR_EVENT_IMPORTANCE event_importance);
      string         EventMultiplierDescription(const ENUM_CALENDAR_EVENT_MULTIPLIER event_multiplier);
      string         ValueImpactDescription(const ENUM_CALENDAR_EVENT_IMPACT event_impact);
      //--- history
      bool           ValueHistorySelectByEvent
      (
         MqlCalendarValue &values[], // array for value descriptions
         datetime datetime_from,     // left border of a time range
         datetime datetime_to = 0    // right border of a time range
      )                 const;
      bool           ValueHistorySelectByEvent
      (
         SiTimeSeries &dst_ts,       // timeseries for value descriptions
         datetime datetime_from,     // left border of a time range
         datetime datetime_to = 0    // right border of a time range
      )                 const;
      bool           ValueHistorySelect
      (
         MqlCalendarValue &values[], // array for value descriptions
         datetime datetime_from,     // left border of a time range
         datetime datetime_to = 0    // right border of a time range
      )                 const;
      bool           ValueHistorySelect
      (
         SiTimeSeries &dst_ts[],     // array of timeseries for value descriptions
         datetime datetime_from,     // left border of a time range
         datetime datetime_to = 0    // right border of a time range
      );
      //--- the calendar database status
      int            ValueLastSelectByEvent
      (
         ulong&               change_id,     // Calendar change ID
         MqlCalendarValue&    values[]       // array for value descriptions
      )                 const;
      int            ValueLastSelect
      (
         ulong&               change_id,     // Calendar change ID
         MqlCalendarValue&    values[]       // array for value descriptions
      )                 const;
      //--- countries and continents
      bool           GetCountries(CArrayString &countries_arr);
      bool           GetCountries(MqlCalendarCountry &countries[]);
      bool           GetUniqueContinents(string &continents[]);
      bool           GetCountriesByContinent(const ENUM_CONTINENT src_continent,
                                             CArrayString &countries_arr);
      string         GetCountryNameById(const ulong country_id);
      //--- events
      bool           GetEventsByName(CArrayString &events_arr, const string name = NULL);
      bool           GetEventsByName(MqlCalendarEvent &events[], const string name = NULL);
      bool           FilterEvents(MqlCalendarEvent &filtered_events[],
                                  MqlCalendarEvent &src_events[], const ulong filter);
      //--- print
      void           PrintCountryDescription(const MqlCalendarCountry &country);
      void           PrintEventDescription(const MqlCalendarEvent &event);
      void           PrintValueDescription(const MqlCalendarValue &value);
      //---
   private:
      bool           ValidateProperties(void);
      bool           CountryById(const ulong country_id);
      bool           EventId(void);
  };
MqlCalendarCountry CiCalendarInfo::m_countries[];

Die Klasse besteht aus den folgenden Klassenvariablen:

  1. m_currency Länderkennung der Währung;
  2. m_country_id Länderkennung nach ISO 3166-1;
  3. m_country_description Landbeschreibung;
  4. m_event_id Ereignis-ID;
  5. m_event_description Ereignisbeschreibung;
  6. m_countries Array von Beschreibungen für die im Kalender verfügbaren Länder;
  7. m_is_init Initialisierungsflag.

m_currency, m_country_id and m_event_id member data sind eine Reihe von Kriterien für die Erstellung von Datenanforderungen aus der Kalenderdatenbank.

m_country_description and m_event_description bieten einen schnellen Zugriff auf Beschreibungen, wenn ein Land und ein Ereignis bekannt sind.

m_countries sind statisch. Die Länderdaten sind konstant, so dass sie nicht jedes Mal beim Initialisieren eines neuen CiCalendarInfo-Objekts abgefragt werden müssen.

Nun werde ich einige der Methoden beschreiben.


2.3.1 Initialisierungsverfahren

Diese Methode ermöglicht es uns, mit der Handhabung des Klassenobjekts zu beginnen. Die Methode ist wichtig, um die Kalenderdaten zu erhalten. Die Methode nimmt eine Reihe von Kriterien als Parameter (currency code, country ID, event ID) und einen Parameter, der die Anzeige von Initialisierungsdaten im Journal ermöglicht. Die Kriterien ermöglichen es, den Zugriff auf den Kalender zu präzisieren.

//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
bool CiCalendarInfo::Init(const string currency = NULL,         // country currency code name
                          const ulong country_id = WRONG_VALUE, // country ID
                          const ulong event_id = WRONG_VALUE,   // event ID
                          const bool to_log = true              // to log?
                         )
  {
//--- check reinitialization
   if(m_is_init)
     {
      ::PrintFormat(__FUNCTION__ + ": CiCalendarInfo object already initialized!");
      return false;
     }
//--- check countries
   int countries_cnt = ::ArraySize(m_countries);
   if(countries_cnt < 1)
     {
      ::ResetLastError();
      countries_cnt = ::CalendarCountries(m_countries);
      if(countries_cnt < 1)
        {
         ::PrintFormat(__FUNCTION__ + ": CalendarCountries() returned 0! Error %d",
                       ::GetLastError());
         return false;
        }
     }
   for(int c_idx = 0; c_idx < countries_cnt; c_idx++)
     {
      MqlCalendarCountry curr_country = m_countries[c_idx];
      //--- check currency
      if(!::StringCompare(curr_country.currency, currency))
        {
         m_currency = currency;
        }
      //--- check country
      if(country_id != WRONG_VALUE)
         if(curr_country.id == country_id)
           {
            m_country_id = country_id;
           }
     }
//--- check event
   if(event_id != WRONG_VALUE)
     {
      m_event_id = event_id;
     }
//--- validate properties
   if(!this.ValidateProperties())
      return false;
//---
   if(to_log)
     {
      ::Print("\n---== New Calendar Info object ==---");
      if(m_currency != NULL)
         ::PrintFormat("   Currency: %s", m_currency);
      if(m_country_id != WRONG_VALUE)
         ::PrintFormat("   Country id: %I64u", m_country_id);
      if(m_event_id != WRONG_VALUE)
         ::PrintFormat("   Event id: %I64u", m_event_id);
     }
   m_is_init = true;
   return true;
  }
//+------------------------------------------------------------------+

Wir wollen die Funktionsweise der Methode anhand eines einfachen Skripts Test_initialization.mq5 veranschaulichen.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- TRUE
//--- 1) all currencies, all countries, all events
   CiCalendarInfo calendar_info1;
   bool is_init = calendar_info1.Init();
//--- 2) EUR, all countries, all events
   CiCalendarInfo calendar_info2;
   is_init = calendar_info2.Init("EUR");
//--- 3) EUR, Germany, all events
   CiCalendarInfo calendar_info3;
   is_init = calendar_info3.Init("EUR", 276);
//--- 4) EUR, Germany, HICP m/m
   CiCalendarInfo calendar_info4;
   is_init = calendar_info4.Init("EUR", 276, 276010022);
//--- FALSE
//--- 5) EUR, Germany, nonfarm-payrolls
   CiCalendarInfo calendar_info5;
   is_init = calendar_info5.Init("EUR", 276, 840030016);
//--- 6) EUR, US, nonfarm-payrolls
   CiCalendarInfo calendar_info6;
   is_init = calendar_info6.Init("EUR", 840, 840030016);
//--- 7) EUR, all countries, nonfarm-payrolls
   CiCalendarInfo calendar_info7;
   is_init = calendar_info7.Init("EUR", WRONG_VALUE, 840030016);
  }
//+------------------------------------------------------------------+

Nach dem Start des Skripts sehen wir die folgenden Einträge im Journal:

DO      0       21:30:19.703    Test_initialization (USDCAD,H1) ---== New Calendar Info object ==---
GE      0       21:30:19.703    Test_initialization (USDCAD,H1) 
LL      0       21:30:19.703    Test_initialization (USDCAD,H1) ---== New Calendar Info object ==---
FI      0       21:30:19.703    Test_initialization (USDCAD,H1)    Currency: EUR
GO      0       21:30:19.703    Test_initialization (USDCAD,H1) 
LJ      0       21:30:19.703    Test_initialization (USDCAD,H1) ---== New Calendar Info object ==---
FS      0       21:30:19.703    Test_initialization (USDCAD,H1)    Currency: EUR
KO      0       21:30:19.703    Test_initialization (USDCAD,H1)    Country id: 276
CH      0       21:30:19.703    Test_initialization (USDCAD,H1) 
PI      0       21:30:19.703    Test_initialization (USDCAD,H1) ---== New Calendar Info object ==---
JF      0       21:30:19.703    Test_initialization (USDCAD,H1)    Currency: EUR
OL      0       21:30:19.703    Test_initialization (USDCAD,H1)    Country id: 276
HD      0       21:30:19.703    Test_initialization (USDCAD,H1)    Event id: 276010022
HR      0       21:30:19.703    Test_initialization (USDCAD,H1) CiCalendarInfo::ValidateProperties: failed! Country ids must be the same!
OP      0       21:30:19.703    Test_initialization (USDCAD,H1) CiCalendarInfo::ValidateProperties: failed! Currencies must be the same!
GP      0       21:30:19.703    Test_initialization (USDCAD,H1) CiCalendarInfo::ValidateProperties: failed! Currencies must be the same!

Die Methode der Initialisierung prüft die angegebenen Parameter in Bezug auf ihre Zugehörigkeit zu einem einzigen Land oder Währung. Daher werden die folgenden Kombinationen zurückgegeben "false": EUR - Deutschland - Nonfarm-Payrolls, EUR - US - Nonfarm-Payrolls und EUR - alle Länder - Nonfarm-Payrolls.

Ganz am Anfang der Initialisierungsmethode befindet sich ein Schutz gegen Reinitialisierung. Das Kalenderobjekt kann immer noch reinitialisiert werden, aber zuerst sollten wir die Deinitialisierungsmethode aufrufen. Zum Beispiel legen wir zunächst fest, dass das Kalenderobjekt Daten über EUR-Ereignisse sammelt. Dann sollte das Objekt auf USD umgestellt werden. Das Skript Test_reinitialization.mq5 zeigt beide Lösungen für diese Aufgabe, die falsche und die richtige.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
   {
//--- ERROR
   CiCalendarInfo calendar_info1;
   bool is_init = calendar_info1.Init("EUR");
   is_init = calendar_info1.Init("USD");
//--- OK
   CiCalendarInfo calendar_info2;
   is_init = calendar_info2.Init("EUR");
   calendar_info2.Deinit();
   is_init = calendar_info2.Init("USD");
   }
//+------------------------------------------------------------------+

Im falschen Fall wird der folgende Eintrag angezeigt:

MP      0       21:34:19.397    Test_reinitialization (USDCAD,H1)       
FQ      0       21:34:19.397    Test_reinitialization (USDCAD,H1)       ---== New Calendar Info object ==---
HO      0       21:34:19.397    Test_reinitialization (USDCAD,H1)          Currency: EUR
KI      0       21:34:19.397    Test_reinitialization (USDCAD,H1)       CiCalendarInfo::Init: CiCalendarInfo object already initialized!
EI      0       21:34:19.397    Test_reinitialization (USDCAD,H1)       
NO      0       21:34:19.397    Test_reinitialization (USDCAD,H1)       ---== New Calendar Info object ==---
PF      0       21:34:19.397    Test_reinitialization (USDCAD,H1)          Currency: EUR
QL      0       21:34:19.397    Test_reinitialization (USDCAD,H1)       
RD      0       21:34:19.397    Test_reinitialization (USDCAD,H1)       ---== New Calendar Info object ==---
DS      0       21:34:19.397    Test_reinitialization (USDCAD,H1)          Currency: USD


2.3.2 Die Methoden zum Empfang der Struktur der Kalenderbeschreibungen

Bis zu einem gewissen Grad sind diese Methoden Wrapper, die den Aufruf von Standard-Kalenderfunktionen ermöglichen. Die Methoden CiCalendarInfo::CountryDescription() und CiCalendarInfo::EventDescription() geben Länder- und Ereignisbeschreibungen zurück, wenn sie bei der Initialisierung des Kalenderobjekts bestätigt wurden. 

Außerdem ermöglichen die Methoden die Anzeige der angeforderten Eigenschaftsbeschreibung im Journal.

Veranschaulichen wir die Arbeit der Methoden, die Beschreibungen erhalten, anhand des einfachen Skripts Test_structures_descriptions.mq5.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- 1) events by country
   CiCalendarInfo calendar_info;
   ulong country_id = 276; // Germany
   if(calendar_info.Init(NULL, country_id))
     {
      MqlCalendarEvent events[];
      if(calendar_info.EventsByCountryDescription(events))
        {
         Print("\n---== Events selected by country ==---");
         PrintFormat("   Country id: %I64u", country_id);
         PrintFormat("   Events number: %d", ::ArraySize(events));
        }
     }
   calendar_info.Deinit();
//--- 2) events by currency
   string country_currency = "EUR";
   if(calendar_info.Init(country_currency))
     {
      MqlCalendarEvent events[];
      if(calendar_info.EventsByCurrencyDescription(events))
        {
         Print("\n---== Events selected by currency ==---");
         PrintFormat("   Currency: %s", country_currency);
         PrintFormat("   Events number: %d", ::ArraySize(events));
        }
     }
  }
//+------------------------------------------------------------------+

Im Journal finden wir die folgenden Zeilen:

MK      0       21:36:35.659    Test_structures_descriptions (USDCAD,H1)        
DM      0       21:36:35.659    Test_structures_descriptions (USDCAD,H1)        ---== New Calendar Info object ==---
MP      0       21:36:35.659    Test_structures_descriptions (USDCAD,H1)           Country id: 276
FH      0       21:36:35.793    Test_structures_descriptions (USDCAD,H1)        
ON      0       21:36:35.793    Test_structures_descriptions (USDCAD,H1)        ---== Events selected by country ==---
RR      0       21:36:35.793    Test_structures_descriptions (USDCAD,H1)           Country id: 276
GD      0       21:36:35.793    Test_structures_descriptions (USDCAD,H1)           Events number: 61
FP      0       21:36:35.793    Test_structures_descriptions (USDCAD,H1)        
OG      0       21:36:35.793    Test_structures_descriptions (USDCAD,H1)        ---== New Calendar Info object ==---
KI      0       21:36:35.793    Test_structures_descriptions (USDCAD,H1)           Currency: EUR
MN      0       21:36:35.794    Test_structures_descriptions (USDCAD,H1)        
QE      0       21:36:35.794    Test_structures_descriptions (USDCAD,H1)        ---== Events selected by currency ==---
FO      0       21:36:35.794    Test_structures_descriptions (USDCAD,H1)           Currency: EUR
FJ      0       21:36:35.794    Test_structures_descriptions (USDCAD,H1)           Events number: 276

Dies bedeutet, dass 61 Ereignisse für Deutschland und 276 Ereignisse für Euro-Länder gefunden wurden.


2.3.3 Die Methoden zum Empfang der Beschreibungen der Enumerationen des Kalenders

Die Kalenderstrukturen enthalten acht Enumerationen:

  1. ENUM_CALENDAR_EVENT_TYPE;
  2. ENUM_CALENDAR_EVENT_SECTOR;
  3. ENUM_CALENDAR_EVENT_FREQUENCY;
  4. ENUM_CALENDAR_EVENT_TIMEMODE;
  5. ENUM_CALENDAR_EVENT_UNIT;
  6. ENUM_CALENDAR_EVENT_IMPORTANCE;
  7. ENUM_CALENDAR_EVENT_MULTIPLIER;
  8. ENUM_CALENDAR_EVENT_IMPACT.

Die ersten sieben Enumerationen beziehen sich auf die Struktur MqlCalendarEvent, die letzte auf die Struktur MqlCalendarValue.

Die Klasse CiCalendarInfo definiert acht Methoden, die den aus der vorgeschlagenen Liste ausgewählten Enumerationswert beschreiben. Testen wir die Methoden mit Hilfe des Skripts Test_enums_descriptions.mq5. Das Skript wählt zufällig 10 UK-Ereignisse aus und zeigt Daten zu jedem Kriterium im Journal an.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
   {
   CiCalendarInfo calendar_info;
   ulong country_id = 826; // UK
   if(calendar_info.Init(NULL, country_id))
      {
      MqlCalendarEvent events[];
      if(calendar_info.EventsByCountryDescription(events))
         {
         ::MathSrand(77);
         int events_num =::ArraySize(events);
         int n = 10;
         MqlCalendarEvent events_selected[];
         ::ArrayResize(events_selected, n);
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            int rand_val =::MathRand();
            int rand_idx = rand_val % events_num;
            events_selected[ev_idx] = events[rand_idx];
            }
         //--- 0) name
         ::Print("\n---== Name ==---");
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            MqlCalendarEvent curr_event = events_selected[ev_idx];
            ::PrintFormat("   [%d] - %s", ev_idx + 1, curr_event.name);
            }
         //--- 1) type
         ::Print("\n---== Type ==---");
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            MqlCalendarEvent curr_event = events_selected[ev_idx];
            ::PrintFormat("   [%d] - %s", ev_idx + 1,
                          calendar_info.EventTypeDescription(curr_event.type));
            }
         //--- 2) sector
         ::Print("\n---== Sector ==---");
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            MqlCalendarEvent curr_event = events_selected[ev_idx];
            ::PrintFormat("   [%d] - %s", ev_idx + 1,
                          calendar_info.EventSectorDescription(curr_event.sector));
            }
         //--- 3) frequency
         ::Print("\n---== Frequency ==---");
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            MqlCalendarEvent curr_event = events_selected[ev_idx];
            ::PrintFormat("   [%d] - %s", ev_idx + 1,
                          calendar_info.EventFrequencyDescription(curr_event.frequency));
            }
         //--- 3) time mode
         ::Print("\n---== Time mode ==---");
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            MqlCalendarEvent curr_event = events_selected[ev_idx];
            ::PrintFormat("   [%d] - %s", ev_idx + 1,
                          calendar_info.EventTimeModeDescription(curr_event.time_mode));
            }
         //--- 4) unit
         ::Print("\n---== Unit ==---");
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            MqlCalendarEvent curr_event = events_selected[ev_idx];
            ::PrintFormat("   [%d] - %s", ev_idx + 1,
                          calendar_info.EventUnitDescription(curr_event.unit));
            }
         //--- 5) importance
         ::Print("\n---== Importance ==---");
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            MqlCalendarEvent curr_event = events_selected[ev_idx];
            ::PrintFormat("   [%d] - %s", ev_idx + 1,
                          calendar_info.EventImportanceDescription(curr_event.importance));
            }
         //--- 6) multiplier
         ::Print("\n---== Multiplier ==---");
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            MqlCalendarEvent curr_event = events_selected[ev_idx];
            ::PrintFormat("   [%d] - %s", ev_idx + 1,
                          calendar_info.EventMultiplierDescription(curr_event.multiplier));
            }
         //--- 7) impact
         MqlCalendarValue values_by_event[];
         datetime start_dt, stop_dt;
         start_dt = D'01.01.2021';
         stop_dt = D'01.11.2021';
         ::Print("\n---== Impact ==---");
         for(int ev_idx = 0; ev_idx < n; ev_idx++)
            {
            MqlCalendarEvent curr_event = events_selected[ev_idx];
            CiCalendarInfo event_info;
            MqlCalendarValue ev_values[];
            if(event_info.Init(NULL, WRONG_VALUE, curr_event.id))
               if(event_info.ValueHistorySelectByEvent(ev_values, start_dt, stop_dt))
                  {
                  int ev_values_size =::ArraySize(ev_values);
                  ::PrintFormat("   [%d] - %s", ev_idx + 1,
                                calendar_info.ValueImpactDescription(ev_values[--ev_values_size].impact_type));
                  }
            }
         }
      }
   }
//+------------------------------------------------------------------+

Um das erhaltene Ergebnis zu reproduzieren, setzen wir den Anfangszustand des Pseudo-Zufallsgenerators für ganze Zahlen auf eine bestimmte Zahl (::MathSrand(77)). Das Skript hat die folgenden Ereignisse ausgewählt:

  1. BoE Housing Equity Withdrawal q/q;
  2. BoE Deputy Governor Markets and Banking Ramsden Speech;
  3. Claimant Count Change;
  4. Core CPI y/y;
  5. Average Weekly Earnings, Total Pay y/y;
  6. Easter Monday;
  7. BoE Mortgage Lending m/m;
  8. BoE MPC Member Vlieghe Speech;
  9. Core RPI y/y;
  10. Claimant Count Change.

Die folgenden Beschreibungen erscheinen im Journal:

FP      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     ---== Type ==---
CG      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [1] - Indicator
EN      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [2] - Event
EI      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [3] - Indicator
LP      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [4] - Indicator
OK      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [5] - Indicator
OD      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [6] - Holiday
EL      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [7] - Indicator
GG      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [8] - Event
ON      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [9] - Indicator
CJ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [10] - Indicator
DO      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     
PE      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     ---== Sector ==---
JR      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [1] - Money
KJ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [2] - Money
NQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [3] - Labor market
QS      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [4] - Prices
HD      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [5] - Labor market
JP      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [6] - Holidays
OI      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [7] - Housing
EQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [8] - Money
LD      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [9] - Prices
JR      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [10] - Labor market
RS      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     
NF      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     ---== Frequency ==---
ML      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [1] - Quarterly
QH      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [2] - None
MN      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [3] - Monthly
PI      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [4] - Monthly
OP      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [5] - Monthly
CE      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [6] - None
CR      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [7] - Monthly
CS      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [8] - None
GE      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [9] - Monthly
OO      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [10] - Monthly
PI      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     
NQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     ---== Time mode ==---
FE      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [1] - Exact time
MS      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [2] - Exact time
PH      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [3] - Exact time
CQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [4] - Exact time
RO      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [5] - Exact time
PF      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [6] - Takes all day
NR      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [7] - Exact time
MK      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [8] - Exact time
DQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [9] - Exact time
RM      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [10] - Exact time
FK      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     
HP      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     ---== Unit ==---
CI      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [1] - National currency
OO      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [2] - None
MG      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [3] - People
CO      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [4] - Percentage
NE      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [5] - Percentage
OK      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [6] - None
KQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [7] - National currency
CH      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [8] - None
LQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [9] - Percentage
CE      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [10] - People
LL      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     
PD      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     ---== Importance ==---
FS      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [1] - Low
PD      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [2] - Moderate
DK      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [3] - High
EM      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [4] - Low
QJ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [5] - Moderate
GQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [6] - None
PG      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [7] - Low
RO      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [8] - Moderate
LI      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [9] - Low
FM      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [10] - High
ND      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     
CM      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     ---== Multiplier ==---
HE      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [1] - Billions
MK      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [2] - None
IM      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [3] - Thousands
MI      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [4] - None
HQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [5] - None
OH      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [6] - None
DN      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [7] - Billions
IF      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [8] - None
LN      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [9] - None
OH      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [10] - Thousands
DM      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     
FF      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)     ---== Impact ==---
OK      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [1] - Positive
OR      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [2] - None
EJ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [3] - Positive
RQ      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [4] - Negative
CG      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [5] - Negative
KN      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [6] - None
JF      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [7] - None
EM      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [8] - None
GD      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [9] - Positive
QH      0       21:14:19.340    Test_enums_descriptions (USDCAD,H1)        [10] - Positive

Zum Beispiel wird das erste Ereignis "BoE Housing Equity Withdrawal q/q" wie folgt beschrieben:

  1. "Type" - Indicator;
  2. "Sector" - Money;
  3. "Frequency" - Quarterly;
  4. "Time mode" - Exact time;
  5. "Unit" - National currency;
  6. "Importance" - Low;
  7. "Multiplier" - Billions;
  8. "Impact" - Positive.

Das letzte Ereignis "Claimant Count Change" wird wie folgt beschrieben:

  1. "Type" - Indicator;
  2. "Sector" - Labor;
  3. "Frequency" - Quarterly;
  4. "Time mode" - Exact time;
  5. "Unit" - National currency;
  6. "Importance" - Low;
  7. "Multiplier" - Billions;
  8. "Impact" - Positive.


2.3.4 Methoden für den Zugriff auf die Historie

Die Methoden verwenden auch die eingebauten Kalenderfunktionen und erhalten Daten über Ereigniswerte. Zum Beispiel wird die Funktion ::CalendarValueHistoryByEvent() durch zwei überladene Methoden CiCalendarInfo::ValueHistorySelectByEvent() aufgerufen. Die erste gibt das Array von Werten für alle Ereignisse innerhalb des angegebenen Zeitbereichs durch eine Ereignis-ID in Form der MqlCalendarValue-Struktur zurück, während die zweite ein Array von Werten ist, die in eine Zeitreihe transformiert wurden.

Werfen wir einen Blick auf die CiCalendarInfo::ValueHistorySelectByEvent() Methodenoperation im Skript Test_value_history_by_event.mq5.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- NFP
   CiCalendarInfo nfp_info;
   ulong nfp_id = 840030016;
   if(nfp_info.Init(NULL, WRONG_VALUE, nfp_id))
     {
      SiTimeSeries nfp_ts;
      if(nfp_info.ValueHistorySelectByEvent(nfp_ts, 0, ::TimeTradeServer()))
         nfp_ts.Print(0);
     }
  }
//+------------------------------------------------------------------+

Wählen Sie die gesamte Historie für United States Nonfarm Payrolls.

Die folgenden Einträge erscheinen im Journal:

PL      0       21:45:03.581    Test_value_history_by_event (USDCAD,H1) ---== New Calendar Info object ==---
NI      0       21:45:03.581    Test_value_history_by_event (USDCAD,H1)    Event id: 840030016
OM      0       21:45:03.581    Test_value_history_by_event (USDCAD,H1) 
HG      0       21:45:03.581    Test_value_history_by_event (USDCAD,H1) ---== Times series - Nonfarm Payrolls==---
CJ      0       21:45:03.581    Test_value_history_by_event (USDCAD,H1) [1]: time - 2007.03.09 16:30, value - 97
RE      0       21:45:03.581    Test_value_history_by_event (USDCAD,H1) [2]: time - 2007.04.06 15:30, value - 177
MS      0       21:45:03.581    Test_value_history_by_event (USDCAD,H1) [3]: time - 2007.05.04 15:30, value - 80
FL      0       21:45:03.581    Test_value_history_by_event (USDCAD,H1) [4]: time - 2007.06.01 15:30, value - 190
LH      0       21:45:03.581    Test_value_history_by_event (USDCAD,H1) [5]: time - 2007.07.06 15:30, value - 69
...
JE      0       21:45:03.583    Test_value_history_by_event (USDCAD,H1) [172]: time - 2021.06.04 15:30, value - 559
JP      0       21:45:03.583    Test_value_history_by_event (USDCAD,H1) [173]: time - 2021.07.02 15:30, value - 850
IO      0       21:45:03.583    Test_value_history_by_event (USDCAD,H1) [174]: time - 2021.08.06 15:30, value - 943
NJ      0       21:45:03.583    Test_value_history_by_event (USDCAD,H1) [175]: time - 2021.09.03 15:30, value - 235
HI      0       21:45:03.583    Test_value_history_by_event (USDCAD,H1) [176]: time - 2021.10.08 15:30, value - 194

*Hier habe ich die ersten und letzten fünf Ereigniswerte angegeben, um den Artikel nicht zu überfrachten.


2.3.5 Methoden zur Überprüfung des Status der Kalenderdatenbank

Die Methoden verwenden ebenfalls die entsprechenden eingebauten Kalenderfunktionen. Ein Fehler wird nur gemeldet, wenn die Anzahl der erhaltenen Ereigniswerte gleich Null ist, während der Fehler selbst größer als Null ist. 

Ein Beispiel für die Methode CiCalendarInfo::ValueLastSelectByEvent() wird im dritten Abschnitt "Indikator für nichtkommerzielle Nettopositionen" betrachtet, in dem es darum geht, das Auftreten eines neuen Wertes zu erkennen.


2.3.6 Methoden zum Abrufen von Länder- und Kontinentdaten

Die Methoden geben bestimmte Länderdaten zurück. Ich werde jede von ihnen kurz beschreiben.

Die Methode CiCalendarInfo::GetCountries(CArrayString &countries_arr) gibt die Liste der Länder zurück, die während der Initialisierung als ein dynamisches Array von Variablen vom Typ String erhalten wurde.

Die Methode CiCalendarInfo::GetCountries(MqlCalendarCountry &countries[]) gibt die Liste der Länder zurück, die während der Initialisierung als ein Array von MqlCalendarCountry Typ Variablen erhalten wurde.

Die Methode CiCalendarInfo::GetUniqueContinents(string & continents[]) liefert die Liste der Kontinente, auf denen sich die Länder befinden. Letztere wurden auch bei der Initialisierung ermittelt.

Die Methode CiCalendarInfo:: GetCountriesByContinent(const ENUM_CONTINENT src_continent, CArrayString &countries_arr) liefert die Liste der Länder nach einem angegebenen Kontinent.

Die Methode CiCalendarInfo::GetCountryNameById(const ulong country_id) gibt einen eindeutigen Ländernamen nach seiner ID zurück.

Die Enumeration ENUM_CONTINENT ermöglicht die Arbeit mit Kontinenten. Sie beschreibt die folgenden Kontinente:

  1. World;
  2. Asia;
  3. Africa;
  4. Europe;
  5. North America;
  6. South America;
  7. Australia/Oceania;
  8. Antarctica.

Es mag komisch erscheinen, dass ich die Antarktis in die Enumerationen aufgenommen habe. Aber ich wollte eine vollständige Liste aller Kontinente haben, also habe ich sie dort belassen. Die Konstante 'World' ist als eigener Kontinent angelegt.

Außerdem habe ich die Struktur SCountryByContinent erstellt, um mit Kontinenten zu arbeiten. Die Initialisierungsmethode enthält konstante Arrays der Kennungen der Länder, die Namen und die entsprechenden Kontinente. Die aktuelle Version enthält 197 Länder, darunter die EU und die ganze Welt.

Erstellen wir das Skript Test_get_countries.mq5, um die Funktionsweise der Methoden zum Erhalten von Länder-und Kontinentdaten zu überprüfen.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   CiCalendarInfo country_calendar_info;
   if(country_calendar_info.Init())
     {
      //--- 1) get countries (CArrayString)
      CArrayString countries_arr;
      if(country_calendar_info.GetCountries(countries_arr))
        {
         int countries_num = countries_arr.Total();
         if(countries_num > 0)
           {
            ::Print("\n---== CArrayString list ==---");
            ::PrintFormat("   Countries list consists of %d countries.", countries_num);
            ::PrintFormat("   First country: %s", countries_arr.At(0));
            ::PrintFormat("   Last country: %s", countries_arr.At(countries_num - 1));
           }
        }
      //--- 2) get countries (MqlCalendarCountry)
      MqlCalendarCountry countries[];
      if(country_calendar_info.GetCountries(countries))
        {
         int countries_num = ::ArraySize(countries);
         if(countries_num > 0)
           {
            ::Print("\n---== MqlCalendarCountry array ==---");
            ::PrintFormat("   Countries array consists of %d countries.", countries_num);
            ::PrintFormat("   First country: %s", countries[0].name);
            ::PrintFormat("   Last country: %s", countries[countries_num - 1].name);
           }
        }
      //--- 3) get unique continents
      string continent_names[];
      int continents_num = 0;
      if(country_calendar_info.GetUniqueContinents(continent_names))
        {
         continents_num = ::ArraySize(continent_names);
         if(continents_num > 0)
           {
            ::Print("\n---== Unique continent names ==---");
            for(int c_idx = 0; c_idx < continents_num; c_idx++)
              {
               string curr_continent_name = continent_names[c_idx];
               ::PrintFormat("   [%d] - %s", c_idx + 1, curr_continent_name);
              }
           }
        }
      //--- 4) get countries by continent
      if(continents_num)
        {
         ENUM_CONTINENT continents[];
         ::ArrayResize(continents, continents_num);
         ::Print("\n---== Countries by continent ==---");
         for(int c_idx = 0; c_idx < continents_num; c_idx++)
           {
            ENUM_CONTINENT curr_continent =
               SCountryByContinent::ContinentByDescription(continent_names[c_idx]);
            if(countries_arr.Shutdown())
               if(country_calendar_info.GetCountriesByContinent(curr_continent, countries_arr))
                 {
                  int countries_by_continent = countries_arr.Total();
                  ::PrintFormat("   Continent \"%s\" includes %d country(-ies):",
                                continent_names[c_idx], countries_by_continent);
                  for(int c_jdx = 0; c_jdx < countries_by_continent; c_jdx++)
                    {
                     ::PrintFormat("   [%d] - %s", c_jdx + 1,
                                   countries_arr.At(c_jdx));
                    }
                 }
           }
        }
      //--- 5) get country description
      string country_code = "RU";
      SCountryByContinent country_continent_data;
      if(country_continent_data.Init(country_code))
        {
         ::Print("\n---== Country ==---");
         ::PrintFormat("   Name: %s", country_continent_data.Country());
         ::PrintFormat("   Code: %s", country_continent_data.Code());
         ENUM_CONTINENT curr_continent = country_continent_data.Continent();
         ::PrintFormat("   Continent enum: %s", ::EnumToString(curr_continent));
         ::PrintFormat("   Continent description: %s",
                       country_continent_data.ContinentDescription());
        }
     }
  }
//+------------------------------------------------------------------+

Die folgenden Informationen erscheinen im Journal als Ergebnis des gelaufenen Skripts:

EH      0       23:05:16.492    Test_get_countries (USDCAD,H1)  ---== New Calendar Info object ==---
HR      0       23:05:16.492    Test_get_countries (USDCAD,H1)  
QH      0       23:05:16.492    Test_get_countries (USDCAD,H1)  ---== CArrayString list ==---
NR      0       23:05:16.492    Test_get_countries (USDCAD,H1)     Countries list consists of 23 countries.
NP      0       23:05:16.492    Test_get_countries (USDCAD,H1)     First country: European Union
LF      0       23:05:16.492    Test_get_countries (USDCAD,H1)     Last country: Norway
LQ      0       23:05:16.492    Test_get_countries (USDCAD,H1)  
GG      0       23:05:16.492    Test_get_countries (USDCAD,H1)  ---== MqlCalendarCountry array ==---
IL      0       23:05:16.492    Test_get_countries (USDCAD,H1)     Countries array consists of 23 countries.
JP      0       23:05:16.492    Test_get_countries (USDCAD,H1)     First country: European Union
HG      0       23:05:16.492    Test_get_countries (USDCAD,H1)     Last country: Norway
OR      0       23:05:16.493    Test_get_countries (USDCAD,H1)  
FJ      0       23:05:16.493    Test_get_countries (USDCAD,H1)  ---== Unique continent names ==---
KS      0       23:05:16.493    Test_get_countries (USDCAD,H1)     [1] - Africa
NK      0       23:05:16.493    Test_get_countries (USDCAD,H1)     [2] - Asia
HR      0       23:05:16.493    Test_get_countries (USDCAD,H1)     [3] - Australia/Oceania
HM      0       23:05:16.493    Test_get_countries (USDCAD,H1)     [4] - Europe
RE      0       23:05:16.493    Test_get_countries (USDCAD,H1)     [5] - North America
CO      0       23:05:16.493    Test_get_countries (USDCAD,H1)     [6] - South America
GH      0       23:05:16.493    Test_get_countries (USDCAD,H1)     [7] - World
GP      0       23:05:18.606    Test_get_countries (USDCAD,H1)  
LE      0       23:05:18.606    Test_get_countries (USDCAD,H1)  ---== Countries by continent ==---
HO      0       23:05:18.608    Test_get_countries (USDCAD,H1)     Continent "Africa" includes 1 country(-ies):
RR      0       23:05:18.608    Test_get_countries (USDCAD,H1)     [1] - South Africa
NH      0       23:05:18.610    Test_get_countries (USDCAD,H1)     Continent "Asia" includes 6 country(-ies):
CM      0       23:05:18.610    Test_get_countries (USDCAD,H1)     [1] - China
RK      0       23:05:18.610    Test_get_countries (USDCAD,H1)     [2] - Hong Kong
CL      0       23:05:18.610    Test_get_countries (USDCAD,H1)     [3] - India
LJ      0       23:05:18.610    Test_get_countries (USDCAD,H1)     [4] - South Korea
LJ      0       23:05:18.610    Test_get_countries (USDCAD,H1)     [5] - Japan
IR      0       23:05:18.610    Test_get_countries (USDCAD,H1)     [6] - Singapore
OK      0       23:05:18.614    Test_get_countries (USDCAD,H1)     Continent "Australia/Oceania" includes 2 country(-ies):
RM      0       23:05:18.614    Test_get_countries (USDCAD,H1)     [1] - Australia
NJ      0       23:05:18.614    Test_get_countries (USDCAD,H1)     [2] - New Zealand
MM      0       23:05:18.616    Test_get_countries (USDCAD,H1)     Continent "Europe" includes 9 country(-ies):
LO      0       23:05:18.616    Test_get_countries (USDCAD,H1)     [1] - European Union
DF      0       23:05:18.616    Test_get_countries (USDCAD,H1)     [2] - Germany
OQ      0       23:05:18.616    Test_get_countries (USDCAD,H1)     [3] - France
CE      0       23:05:18.616    Test_get_countries (USDCAD,H1)     [4] - United Kingdom
OM      0       23:05:18.616    Test_get_countries (USDCAD,H1)     [5] - Switzerland
RS      0       23:05:18.616    Test_get_countries (USDCAD,H1)     [6] - Spain
FE      0       23:05:18.616    Test_get_countries (USDCAD,H1)     [7] - Sweden
JS      0       23:05:18.616    Test_get_countries (USDCAD,H1)     [8] - Italy
DD      0       23:05:18.616    Test_get_countries (USDCAD,H1)     [9] - Norway
LR      0       23:05:18.618    Test_get_countries (USDCAD,H1)     Continent "North America" includes 3 country(-ies):
LK      0       23:05:18.618    Test_get_countries (USDCAD,H1)     [1] - Canada
HS      0       23:05:18.618    Test_get_countries (USDCAD,H1)     [2] - United States
CK      0       23:05:18.618    Test_get_countries (USDCAD,H1)     [3] - Mexico
GL      0       23:05:18.619    Test_get_countries (USDCAD,H1)     Continent "South America" includes 1 country(-ies):
EQ      0       23:05:18.619    Test_get_countries (USDCAD,H1)     [1] - Brazil
DH      0       23:05:18.622    Test_get_countries (USDCAD,H1)     Continent "World" includes 1 country(-ies):
JK      0       23:05:18.622    Test_get_countries (USDCAD,H1)     [1] - Worldwide
QM      0       23:05:18.622    Test_get_countries (USDCAD,H1)  
KH      0       23:05:18.622    Test_get_countries (USDCAD,H1)  ---== Country ==---
PQ      0       23:05:18.622    Test_get_countries (USDCAD,H1)     Name: Russian Federation
KG      0       23:05:18.622    Test_get_countries (USDCAD,H1)     Code: RU
MR      0       23:05:18.622    Test_get_countries (USDCAD,H1)     Continent enum: CONTINENT_EUROPE
MI      0       23:05:18.622    Test_get_countries (USDCAD,H1)     Continent description: Europe

Die aktuelle Version des Kalenders beschreibt also Ereignisse im Zusammenhang mit den Volkswirtschaften von 23 Ländern auf 7 Kontinenten (vorausgesetzt, die Konstante "Welt" wird berücksichtigt). 


2.3.7  Methoden zur Beschaffung von Ereignisdaten

Die Methoden ermöglichen die Auswahl von Ereignissen nach einem bestimmten Kriterium. 

Die Methode CiCalendarInfo::GetEventsByName(CArrayString &events_arr, const string name = NULL) führt eine Auswahl als dynamisches Array von Variablen vom Typ string durch. Ein Ereignisname dient als Auswahlkriterium.

Die Methode CiCalendarInfo::GetEventsByName(MqlCalendarEvent & events[], const string name = NULL) ähnelt der vorherigen. Der einzige Unterschied ist, dass sie eine Auswahl in Form eines Arrays von Variablen des Typs MqlCalendarCountry bildet. 

Die Methode CiCalendarInfo::FilterEvents(MqlCalendarEvent &filtered_events[], MqlCalendarEvent &src_events[], const ulong filter) bildet ebenfalls eine Auswahl als das Array von MqlCalendarCountry Typvariablen. Hier gibt es bereits ein Mehrfachkriterium, das in einer Reihe von Flags implementiert ist. Insgesamt gibt es 49 solcher Kriterien. Sie decken alle Enumerationswerte ab: ENUM_CALENDAR_EVENT_TYPE, ENUM_CALENDAR_EVENT_SECTOR, ENUM_CALENDAR_EVENT_FREQUENCY, ENUM_CALENDAR_EVENT_TIMEMODE, ENUM_CALENDAR_EVENT_UNIT, ENUM_CALENDAR_EVENT_IMPORTANCE, ENUM_CALENDAR_EVENT_MULTIPLIER.

Das Erstellen einer neuen übergreifenden Mega-Enumeration scheint unmöglich, da der Typ "enum" ein 4-Byte-Datentyp (32 Bits) ist, während in diesem Fall 49 Bits erforderlich sind. Andererseits gibt es den Typ 'long', der 64 Bits bietet.

Der folgende Code wird zur Lösung des Problems verwendet:

//--- defines for events filtering
//--- 1) type (3)
#define FILTER_BY_TYPE_EVENT           0x1              // 1 by type "event"
#define FILTER_BY_TYPE_INDICATOR       0x2              // 2 by type "indicator"
#define FILTER_BY_TYPE_HOLIDAY         0x4              // 3 by type "holiday"
//--- 2) sector (13)
#define FILTER_BY_SECTOR_NONE          0x8              // 4 by sector "none"
#define FILTER_BY_SECTOR_MARKET        0x10             // 5 by sector "market"
#define FILTER_BY_SECTOR_GDP           0x20             // 6 by sector "GDP"
#define FILTER_BY_SECTOR_JOBS          0x40             // 7 by sector "jobs"
#define FILTER_BY_SECTOR_PRICES        0x80             // 8 by sector "prices"
#define FILTER_BY_SECTOR_MONEY         0x100            // 9 by sector "money"
#define FILTER_BY_SECTOR_TRADE         0x200            // 10 by sector "trade"
#define FILTER_BY_SECTOR_GOVERNMENT    0x400            // 11 by sector "government"
#define FILTER_BY_SECTOR_BUSINESS      0x800            // 12 by sector "business"
#define FILTER_BY_SECTOR_CONSUMER      0x1000           // 13 by sector "consumer"
#define FILTER_BY_SECTOR_HOUSING       0x2000           // 14 by sector "housing"
#define FILTER_BY_SECTOR_TAXES         0x4000           // 15 by sector "taxes"
#define FILTER_BY_SECTOR_HOLIDAYS      0x8000           // 16 by sector "holidays"
//--- 3) frequency (6)
#define FILTER_BY_FREQUENCY_NONE       0x10000          // 17 by frequency "none"
#define FILTER_BY_FREQUENCY_WEEK       0x20000          // 18 by frequency "week"
#define FILTER_BY_FREQUENCY_MONTH      0x40000          // 19 by frequency "month"
#define FILTER_BY_FREQUENCY_QUARTER    0x80000          // 20 by frequency "quarter"
#define FILTER_BY_FREQUENCY_YEAR       0x100000         // 21 by frequency "year"
#define FILTER_BY_FREQUENCY_DAY        0x200000         // 22 by frequency "day"
//--- 4) importance (4)
#define FILTER_BY_IMPORTANCE_NONE      0x400000         // 23 by importance "none"
#define FILTER_BY_IMPORTANCE_LOW       0x800000         // 24 by importance "low"
#define FILTER_BY_IMPORTANCE_MODERATE  0x1000000        // 25 by importance "medium"
#define FILTER_BY_IMPORTANCE_HIGH      0x2000000        // 26 by importance "high"
//--- 5) unit (14)
#define FILTER_BY_UNIT_NONE            0x4000000        // 27 by unit "none"
#define FILTER_BY_UNIT_PERCENT         0x8000000        // 28 by unit "percentage"
#define FILTER_BY_UNIT_CURRENCY        0x10000000       // 29 by unit "currency"
#define FILTER_BY_UNIT_HOUR            0x20000000       // 30 by unit "hours"
#define FILTER_BY_UNIT_JOB             0x40000000       // 31 by unit "jobs"
#define FILTER_BY_UNIT_RIG             0x80000000       // 32 by unit "drilling rigs"
#define FILTER_BY_UNIT_USD             0x100000000      // 33 by unit "USD"
#define FILTER_BY_UNIT_PEOPLE          0x200000000      // 34 by unit "people"
#define FILTER_BY_UNIT_MORTGAGE        0x400000000      // 35 by unit "mortgage loans"
#define FILTER_BY_UNIT_VOTE            0x800000000      // 36 by unit "votes"
#define FILTER_BY_UNIT_BARREL          0x1000000000     // 37 by unit "barrels"
#define FILTER_BY_UNIT_CUBICFEET       0x2000000000     // 38 by unit "cubic feet"
#define FILTER_BY_UNIT_POSITION        0x4000000000     // 39 by unit "net positions"
#define FILTER_BY_UNIT_BUILDING        0x8000000000     // 40 by unit "buildings"
//--- 6) multiplier (5)
#define FILTER_BY_MULTIPLIER_NONE      0x10000000000    // 41 by multiplier "none"
#define FILTER_BY_MULTIPLIER_THOUSANDS 0x20000000000    // 42 by multiplier "thousands"
#define FILTER_BY_MULTIPLIER_MILLIONS  0x40000000000    // 43 by multiplier "millions"
#define FILTER_BY_MULTIPLIER_BILLIONS  0x80000000000    // 44 by multiplier "billions"
#define FILTER_BY_MULTIPLIER_TRILLIONS 0x100000000000   // 45 by multiplier "trillions"
//--- 7) time mode (4)
#define FILTER_BY_TIMEMODE_DATETIME    0x200000000000   // 46 by time mode "na"
#define FILTER_BY_TIMEMODE_DATE        0x400000000000   // 47 by time mode "positive"
#define FILTER_BY_TIMEMODE_NOTIME      0x800000000000   // 48 by time mode "negative"
#define FILTER_BY_TIMEMODE_TENTATIVE   0x1000000000000  // 49 by time mode "na"
//--- type
#define IS_TYPE_EVENT(filter) ((filter&FILTER_BY_TYPE_EVENT)!=0)
#define IS_TYPE_INDICATOR(filter) ((filter&FILTER_BY_TYPE_INDICATOR)!=0)
#define IS_TYPE_HOLIDAY(filter) ((filter&FILTER_BY_TYPE_HOLIDAY)!=0)
//--- sector
#define IS_SECTOR_NONE(filter) ((filter&FILTER_BY_SECTOR_NONE)!=0)
#define IS_SECTOR_MARKET(filter) ((filter&FILTER_BY_SECTOR_MARKET)!=0)
#define IS_SECTOR_GDP(filter) ((filter&FILTER_BY_SECTOR_GDP)!=0)
#define IS_SECTOR_JOBS(filter) ((filter&FILTER_BY_SECTOR_JOBS)!=0)
#define IS_SECTOR_PRICES(filter) ((filter&FILTER_BY_SECTOR_PRICES)!=0)
#define IS_SECTOR_MONEY(filter) ((filter&FILTER_BY_SECTOR_MONEY)!=0)
#define IS_SECTOR_TRADE(filter) ((filter&FILTER_BY_SECTOR_TRADE)!=0)
#define IS_SECTOR_CONSUMER(filter) ((filter&FILTER_BY_SECTOR_CONSUMER)!=0)
#define IS_SECTOR_HOUSING(filter) ((filter&FILTER_BY_SECTOR_HOUSING)!=0)
#define IS_SECTOR_TAXES(filter) ((filter&FILTER_BY_SECTOR_TAXES)!=0)
#define IS_SECTOR_HOLIDAYS(filter) ((filter&FILTER_BY_SECTOR_HOLIDAYS)!=0)
//--- frequency
#define IS_FREQUENCY_NONE(filter) ((filter&FILTER_BY_FREQUENCY_NONE)!=0)
#define IS_FREQUENCY_WEEK(filter) ((filter&FILTER_BY_FREQUENCY_WEEK)!=0)
#define IS_FREQUENCY_MONTH(filter) ((filter&FILTER_BY_FREQUENCY_MONTH)!=0)
#define IS_FREQUENCY_QUARTER(filter) ((filter&FILTER_BY_FREQUENCY_QUARTER)!=0)
#define IS_FREQUENCY_YEAR(filter) ((filter&FILTER_BY_FREQUENCY_YEAR)!=0)
#define IS_FREQUENCY_DAY(filter) ((filter&FILTER_BY_FREQUENCY_DAY)!=0)
//--- importance
#define IS_IMPORTANCE_NONE(filter) ((filter&FILTER_BY_IMPORTANCE_NONE)!=0)
#define IS_IMPORTANCE_LOW(filter) ((filter&FILTER_BY_IMPORTANCE_LOW)!=0)
#define IS_IMPORTANCE_MODERATE(filter) ((filter&FILTER_BY_IMPORTANCE_MODERATE)!=0)
#define IS_IMPORTANCE_HIGH(filter) ((filter&FILTER_BY_IMPORTANCE_HIGH)!=0)
//--- unit
#define IS_UNIT_NONE(filter) ((filter&FILTER_BY_UNIT_NONE)!=0)
#define IS_UNIT_PERCENT(filter) ((filter&FILTER_BY_UNIT_PERCENT)!=0)
#define IS_UNIT_CURRENCY(filter) ((filter&FILTER_BY_UNIT_CURRENCY)!=0)
#define IS_UNIT_HOUR(filter) ((filter&FILTER_BY_UNIT_HOUR)!=0)
#define IS_UNIT_JOB(filter) ((filter&FILTER_BY_UNIT_JOB)!=0)
#define IS_UNIT_RIG(filter) ((filter&FILTER_BY_UNIT_RIG)!=0)
#define IS_UNIT_USD(filter) ((filter&FILTER_BY_UNIT_USD)!=0)
#define IS_UNIT_PEOPLE(filter) ((filter&FILTER_BY_UNIT_PEOPLE)!=0)
#define IS_UNIT_MORTGAGE(filter) ((filter&FILTER_BY_UNIT_MORTGAGE)!=0)
#define IS_UNIT_VOTE(filter) ((filter&FILTER_BY_UNIT_VOTE)!=0)
#define IS_UNIT_BARREL(filter) ((filter&FILTER_BY_UNIT_BARREL)!=0)
#define IS_UNIT_CUBICFEET(filter) ((filter&FILTER_BY_UNIT_CUBICFEET)!=0)
#define IS_UNIT_POSITION(filter) ((filter&FILTER_BY_UNIT_POSITION)!=0)
#define IS_UNIT_BUILDING(filter) ((filter&FILTER_BY_UNIT_BUILDING)!=0)
//--- multiplier
#define IS_MULTIPLIER_NONE(filter) ((filter&FILTER_BY_MULTIPLIER_NONE)!=0)
#define IS_MULTIPLIER_THOUSANDS(filter) ((filter&FILTER_BY_MULTIPLIER_THOUSANDS)!=0)
#define IS_MULTIPLIER_MILLIONS(filter) ((filter&FILTER_BY_MULTIPLIER_MILLIONS)!=0)
#define IS_MULTIPLIER_BILLIONS(filter) ((filter&FILTER_BY_MULTIPLIER_BILLIONS)!=0)
#define IS_MULTIPLIER_TRILLIONS(filter) ((filter&FILTER_BY_MULTIPLIER_TRILLIONS)!=0)
//--- time mode
#define IS_TIMEMODE_DATETIME(filter) ((filter&FILTER_BY_TIMEMODE_DATETIME)!=0)
#define IS_TIMEMODE_DATE(filter) ((filter&FILTER_BY_TIMEMODE_DATE)!=0)
#define IS_TIMEMODE_NOTIME(filter) ((filter&FILTER_BY_TIMEMODE_NOTIME)!=0)
#define IS_TIMEMODE_TENTATIVE(filter) ((filter&FILTER_BY_TIMEMODE_TENTATIVE)!=0)

Werfen wir einen Blick auf das Testbeispiel - dem Skript Test_filter_events.mq5. Zunächst wird das Kalenderobjekt für die angegebene EUR-Währung erstellt.

Als Nächstes wählt man im Block 1 alle Ereignisse aus, die sich auf EUR beziehen und "Arbeitslosigkeit" im Namen tragen. Es gibt 33 Ereignisse dieses Typs. Die Ereignisnamen werden an das dynamische Array von Variablen des Typs String gesendet.

In Block 2 machen wir dasselbe, wobei wir das Array vom Typ MqlCalendarEvent ausfüllen.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   CiCalendarInfo event_calendar_info;
   if(event_calendar_info.Init("EUR"))
     {
      //--- 1) get events by name (CArrayString)
      CArrayString events_arr;
      string ev_name = "Unemployment";
      if(event_calendar_info.GetEventsByName(events_arr, ev_name))
        {
         int events_num = events_arr.Total();
         if(events_num > 0)
           {
            ::Print("\n---== CArrayString list ==---");
            ::PrintFormat("   Events list consists of %d events.", events_num);
            ::PrintFormat("   First event: %s", events_arr.At(0));
            ::PrintFormat("   Last event: %s", events_arr.At(events_num - 1));
           }
        }
      //--- 2) get events by name (MqlCalendarEvent)
      MqlCalendarEvent events[];
      if(event_calendar_info.GetEventsByName(events, ev_name))
        {
         int events_num = ::ArraySize(events);
         if(events_num > 0)
           {
            ::Print("\n---== MqlCalendarEvent array ==---");
            ::PrintFormat("   Events array consists of %d events.", events_num);
            ::PrintFormat("   First event: %s", events[0].name);
            ::PrintFormat("   Last event: %s", events[events_num - 1].name);
           }
        }
      //--- 3) filter events
      MqlCalendarEvent filtered_events[];
      int indices[2];
      indices[0] = 0;
      string events_str[2];
      events_str[0] = "First";
      events_str[1] = "Last";
      ulong filter = 0;
      filter |= FILTER_BY_IMPORTANCE_HIGH;
      if(event_calendar_info.FilterEvents(filtered_events, events, filter))
        {
         int f_events_num = ::ArraySize(filtered_events);
         ::Print("\n---== Filtered events array ==---");
         ::Print("   Filtered by: importance high");
         ::PrintFormat("   Events array consists of %d events.", ::ArraySize(filtered_events));
         if(f_events_num > 0)
           {
            indices[1] = f_events_num - 1;
            for(int ind = 0; ind <::ArraySize(indices); ind++)
              {
               MqlCalendarEvent curr_event = filtered_events[indices[ind]];
               ::PrintFormat("   \n%s event:", events_str[ind]);
               event_calendar_info.PrintEventDescription(curr_event);
              }
           }
         ::ArrayFree(filtered_events);
         filter ^= FILTER_BY_IMPORTANCE_HIGH;
        }
      filter |= FILTER_BY_IMPORTANCE_MODERATE;
      if(event_calendar_info.FilterEvents(filtered_events, events, filter))
        {
         int f_events_num = ::ArraySize(filtered_events);
         ::Print("\n---== Filtered events array ==---");
         ::Print("   Filtered by: importance medium");
         ::PrintFormat("   Events array consists of %d events.", ::ArraySize(filtered_events));
         if(f_events_num > 0)
           {
            indices[1] = f_events_num - 1;
            for(int ind = 0; ind <::ArraySize(indices); ind++)
              {
               MqlCalendarEvent curr_event = filtered_events[indices[ind]];
               ::PrintFormat("   \n%s event:", events_str[ind]);
               event_calendar_info.PrintEventDescription(curr_event);
              }
           }
         ::ArrayFree(filtered_events);
         filter ^= FILTER_BY_IMPORTANCE_MODERATE;
        }
      filter |= FILTER_BY_IMPORTANCE_LOW;
      if(event_calendar_info.FilterEvents(filtered_events, events, filter))
        {
         int f_events_num = ::ArraySize(filtered_events);
         ::Print("\n---== Filtered events array ==---");
         ::Print("   Filtered by: importance low");
         ::PrintFormat("   Events array consists of %d events.", ::ArraySize(filtered_events));
         if(f_events_num > 0)
           {
            indices[1] = f_events_num - 1;
            for(int ind = 0; ind <::ArraySize(indices); ind++)
              {
               MqlCalendarEvent curr_event = filtered_events[indices[ind]];
               ::PrintFormat("   \n%s event:", events_str[ind]);
               event_calendar_info.PrintEventDescription(curr_event);
              }
           }
         ::ArrayFree(filtered_events);
         filter ^= FILTER_BY_IMPORTANCE_LOW;
        }
      filter |= FILTER_BY_IMPORTANCE_NONE;
      if(event_calendar_info.FilterEvents(filtered_events, events, filter))
        {
         int f_events_num = ::ArraySize(filtered_events);
         ::Print("\n---== Filtered events array ==---");
         ::Print("   Filtered by: importance none");
         ::PrintFormat("   Events array consists of %d events.", ::ArraySize(filtered_events));
         if(f_events_num > 0)
           {
            indices[1] = f_events_num - 1;
            for(int ind = 0; ind <::ArraySize(indices); ind++)
              {
               MqlCalendarEvent curr_event = filtered_events[indices[ind]];
               ::PrintFormat("   \n%s event:", events_str[ind]);
               event_calendar_info.PrintEventDescription(curr_event);
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+

Wir sortieren im Block 3 die Ereignisse nach ihrer Wichtigkeit. Zuerst wollen wir sehen, wie viele der dreiunddreißig Ereignisse, die zuvor namentlich ausgewählt wurden, wichtig sind. Es stellt sich heraus, dass keine wichtigen gibt. 27 Ereignisse sind von mittlerer Bedeutung, 6 Ereignisse sind von geringer Bedeutung. Außerdem gibt es 0 Ereignisse mit nicht spezifiziertem Wichtigkeitsgrad. 

Das Journal sieht wie folgt aus:

JL      0       13:18:48.419    Test_filter_events (USDCAD,H1)  
FM      0       13:18:48.421    Test_filter_events (USDCAD,H1)  ---== New Calendar Info object ==---
JP      0       13:18:48.421    Test_filter_events (USDCAD,H1)     Currency: EUR
CE      0       13:18:48.630    Test_filter_events (USDCAD,H1)  
EL      0       13:18:48.631    Test_filter_events (USDCAD,H1)  ---== CArrayString list ==---
IF      0       13:18:48.631    Test_filter_events (USDCAD,H1)     Events list consists of 33 events.
MQ      0       13:18:48.631    Test_filter_events (USDCAD,H1)     First event: Unemployment Rate
RK      0       13:18:48.631    Test_filter_events (USDCAD,H1)     Last event: NAV Unemployment Change
HF      0       13:18:48.635    Test_filter_events (USDCAD,H1)  
OR      0       13:18:48.635    Test_filter_events (USDCAD,H1)  ---== MqlCalendarEvent array ==---
JH      0       13:18:48.635    Test_filter_events (USDCAD,H1)     Events array consists of 33 events.
ER      0       13:18:48.635    Test_filter_events (USDCAD,H1)     First event: Unemployment Rate
JM      0       13:18:48.635    Test_filter_events (USDCAD,H1)     Last event: NAV Unemployment Change
DH      0       13:18:48.635    Test_filter_events (USDCAD,H1)  
CR      0       13:18:48.635    Test_filter_events (USDCAD,H1)  ---== Filtered events array ==---
HH      0       13:18:48.635    Test_filter_events (USDCAD,H1)     Filtered by: importance high
DO      0       13:18:48.635    Test_filter_events (USDCAD,H1)     Events array consists of 0 events.
CN      0       13:18:48.636    Test_filter_events (USDCAD,H1)  
PI      0       13:18:48.636    Test_filter_events (USDCAD,H1)  ---== Filtered events array ==---
NO      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Filtered by: importance medium
PE      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Events array consists of 27 events.
KG      0       13:18:48.636    Test_filter_events (USDCAD,H1)     
KI      0       13:18:48.636    Test_filter_events (USDCAD,H1)  First event:
IS      0       13:18:48.636    Test_filter_events (USDCAD,H1)  
EJ      0       13:18:48.636    Test_filter_events (USDCAD,H1)  ---== Event description ==---
JF      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Id: 999030020
DP      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Type: Indicator
KJ      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Sector: Labor market
JM      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Frequency: Monthly
QJ      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Time mode: Exact time
CN      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Country id: 999
KK      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Unit: Percentage
JP      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Importance: Moderate
JH      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Multiplier: None
JF      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Digits: 1
PL      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Source URL: https://ec.europa.eu/eurostat
NH      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Event code: unemployment-rate
MQ      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Name: Unemployment Rate
GI      0       13:18:48.636    Test_filter_events (USDCAD,H1)     
OO      0       13:18:48.636    Test_filter_events (USDCAD,H1)  Last event:
OJ      0       13:18:48.636    Test_filter_events (USDCAD,H1)  
OP      0       13:18:48.636    Test_filter_events (USDCAD,H1)  ---== Event description ==---
QH      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Id: 578040001
NO      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Type: Indicator
ID      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Sector: Labor market
DF      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Frequency: Monthly
KS      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Time mode: Exact time
LI      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Country id: 578
QR      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Unit: Percentage
LJ      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Importance: Moderate
DQ      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Multiplier: None
LH      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Digits: 1
IS      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Source URL: https://www.nav.no/en/Home
EQ      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Event code: nav-unemployment-rate-nsa
PJ      0       13:18:48.636    Test_filter_events (USDCAD,H1)     Name: NAV Unemployment Rate n.s.a.
ED      0       13:18:48.636    Test_filter_events (USDCAD,H1)  
FF      0       13:18:48.636    Test_filter_events (USDCAD,H1)  ---== Filtered events array ==---
PK      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Filtered by: importance low
JS      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Events array consists of 6 events.
FH      0       13:18:48.637    Test_filter_events (USDCAD,H1)     
FS      0       13:18:48.637    Test_filter_events (USDCAD,H1)  First event:
LI      0       13:18:48.637    Test_filter_events (USDCAD,H1)  
LO      0       13:18:48.637    Test_filter_events (USDCAD,H1)  ---== Event description ==---
EK      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Id: 276060003
IM      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Type: Indicator
FE      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Sector: Labor market
OP      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Frequency: Monthly
HQ      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Time mode: Exact time
HH      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Country id: 276
KM      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Unit: People
DJ      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Importance: Low
RM      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Multiplier: Millions
KJ      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Digits: 3
LS      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Source URL: https://www.arbeitsagentur.de/en/welcome
MN      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Event code: unemployment-nsa
ND      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Name: Unemployment n.s.a.
LP      0       13:18:48.637    Test_filter_events (USDCAD,H1)     
LE      0       13:18:48.637    Test_filter_events (USDCAD,H1)  Last event:
DP      0       13:18:48.637    Test_filter_events (USDCAD,H1)  
DG      0       13:18:48.637    Test_filter_events (USDCAD,H1)  ---== Event description ==---
CS      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Id: 578040002
QE      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Type: Indicator
NM      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Sector: Labor market
GH      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Frequency: Monthly
PI      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Time mode: Exact time
GS      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Country id: 578
CE      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Unit: People
LS      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Importance: Low
HJ      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Multiplier: Thousands
QR      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Digits: 3
NI      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Source URL: https://www.nav.no/en/Home
MQ      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Event code: nav-unemployment-change
ES      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Name: NAV Unemployment Change
PI      0       13:18:48.637    Test_filter_events (USDCAD,H1)  
CS      0       13:18:48.637    Test_filter_events (USDCAD,H1)  ---== Filtered events array ==---
DK      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Filtered by: importance none
DH      0       13:18:48.637    Test_filter_events (USDCAD,H1)     Events array consists of 0 events.

Wie ich bereits sagte, gibt es 49 Kriterien für die Auswahl von Ereignissen. Sie können kombiniert oder einzeln verwendet werden.


3. Indikator für nicht-kommerzielle Nettopositionen

Der Wirtschaftskalender enthält viele verschiedene Ereignisse. Ich habe eines der bemerkenswertesten Ereignisse ausgewählt - den wöchentlichen Bericht der Commodity Futures Trading Commission, der die Differenz zwischen dem Gesamtvolumen der Long- und Short-Positionen anzeigt. 

Lassen Sie uns einen Indikator erstellen, der die Daten eines ausgewählten Rohstoffwertes in einem separaten Fenster des Charts anzeigt.

Es gibt 11 solcher Vermögenswerte. Erstellen wir die folgende Enumeration:

//+------------------------------------------------------------------+
//| CFTC Non-Commercial Net Positions                                |
//+------------------------------------------------------------------+
enum ENUM_NON_COM_NET_POSITIONS
  {
   NON_COM_NET_POSITIONS_COPPER = 0,      // Copper
   NON_COM_NET_POSITIONS_SILVER = 1,      // Silver
   NON_COM_NET_POSITIONS_GOLD = 2,        // Gold
   NON_COM_NET_POSITIONS_CRUDE_OIL = 3,   // Crude oil
   NON_COM_NET_POSITIONS_SP_500 = 4,      // S&P 500
   NON_COM_NET_POSITIONS_AlUMINIUM = 5,   // Aluminium
   NON_COM_NET_POSITIONS_CORN = 6,        // Corn
   NON_COM_NET_POSITIONS_NGAS = 7,        // Natural gas
   NON_COM_NET_POSITIONS_SOYBEANS = 8,    // Soybeans
   NON_COM_NET_POSITIONS_WHEAT = 9,       // Wheat
   NON_COM_NET_POSITIONS_NASDAQ_100 = 10, // Nasdaq 100
  };

Der Indikator soll frühere Werte anzeigen und neue Werte erkennen. Für die erste Aufgabe habe ich beschlossen, den folgenden Codeblock in OnCalculate() zu verwenden:

//--- first call
if(prev_calculated == 0)
  {
//--- initialize buffer
   ::ArrayInitialize(gBuffer, EMPTY_VALUE);
//--- 1) collect all events by country
   ulong country_id = 840; // US
   if(gPtrEventsInfo.Init(NULL, country_id))
     {
      MqlCalendarEvent events[];
      if(gPtrEventsInfo.EventsByCountryDescription(events, false))
        {
         string event_code_substr = GetEventCodeSubstring();
         if(event_code_substr != NULL)
            for(int ev_idx = 0; ev_idx <::ArraySize(events); ev_idx++)
              {
               MqlCalendarEvent curr_event = events[ev_idx];
               if(::StringFind(curr_event.event_code, event_code_substr) > -1)
                 {
                  //--- 2) collect all values by event id
                  if(gPtrValuesInfo.Init(NULL, WRONG_VALUE, curr_event.id))
                    {
                     SiTimeSeries net_positions_ts;
                     if(gPtrValuesInfo.ValueHistorySelectByEvent(net_positions_ts, 0))
                       {
                        string net_positions_name;
                        SiTsObservation ts_observations[];
                        if(net_positions_ts.GetSeries(ts_observations, net_positions_name))
                          {
                           //--- consider only past observations
                           int new_size = 0;
                           for(int obs_idx =::ArraySize(ts_observations) - 1; obs_idx >= 0; obs_idx--)
                             {
                              if(ts_observations[obs_idx].val != EMPTY_VALUE)
                                 break;
                              new_size = obs_idx;
                             }
                           if(new_size > 0)
                              ::ArrayResize(ts_observations, new_size);
                           //--- find the starting date
                           datetime start_dtime, ts_start_dtime;
                           start_dtime = time[0];
                           ts_start_dtime = ts_observations[0].time;
                           if(ts_start_dtime > start_dtime)
                              start_dtime = ts_start_dtime;
                           ::IndicatorSetString(INDICATOR_SHORTNAME, net_positions_name);
                           ::IndicatorSetInteger(INDICATOR_DIGITS, 1);
                           //---
                           int start_bar_idx =::iBarShift(_Symbol, _Period, ts_start_dtime);
                           if(start_bar_idx > -1)
                             {
                              start_bar_idx = rates_total - start_bar_idx;
                              uint observations_cnt = 0;
                              SiTsObservation curr_observation = ts_observations[observations_cnt];
                              uint ts_size = ::ArraySize(ts_observations);
                              for(int bar = start_bar_idx; bar < rates_total; bar++)
                                {
                                 if((observations_cnt + 1) < ts_size)
                                   {
                                    SiTsObservation next_observation =
                                       ts_observations[observations_cnt + 1];
                                    if(time[bar] >= next_observation.time)
                                      {
                                       curr_observation = next_observation;
                                       gLastValueDate = curr_observation.time;
                                       gLastValue = curr_observation.val;
                                       observations_cnt++;
                                      }
                                   }
                                 gBuffer[bar] = curr_observation.val;
                                }
                              //--- just to get a change id
                              MqlCalendarValue values[];
                              gPtrValuesInfo.ValueLastSelectByEvent(gChangeId, values);
                             }
                          }
                       }
                    }
                  break;
                 }
              }
        }
     }
  }

Initialisieren wir das erste Kalenderobjekt im Block. Wir geben nur eine Länder-ID ein  USA. Als Nächstes wählen wir alle Länderereignisse aus und ermitteln das notwendige Wertpapier durch einen in der Eingangsvariablen festgelegten Ereigniscode. Danach initialisieren wir das zweite Kalenderobjekt und fordern die Historie an. Als Nächstes wird der Indikatorpuffer ausgefüllt.

Der zweite Block in OnCalculate() besteht darin, einen neuen Wert zu erkennen:

MqlCalendarValue values[];
if(gPtrValuesInfo.ValueLastSelectByEvent(gChangeId, values) > 0)
   if(values[0].time > gLastValueDate)
     {
      gLastValueDate = values[0].time;
      gLastValue = values[0].GetActualValue();
      //--- to log
      if(InpTpLog)
        {
         ::Print("\n---== New event value ==---");
         ::PrintFormat("   Time: %s", ::TimeToString(gLastValueDate));
         datetime server_time =::TimeTradeServer();
         ::PrintFormat("   Release time: %s", ::TimeToString(server_time));
         ::PrintFormat("   Actual value: %0.1f", gLastValue);
        }
     }
//--- if a new bar
if(rates_total > prev_calculated)
   for(int bar = prev_calculated; bar < rates_total; bar++)
      gBuffer[bar] = gLastValue;

Das Ergebnis sollte in etwa so aussehen wie in der folgenden Abbildung (Abb. 3).


CFTC S&P 500 Nicht-gewerbliche Nettopositionen

Abb. 3. CFTC S&P 500 Nicht-gewerbliche Nettopositionen

Im Code des Indikators ist zu erkennen, dass die Kalenderobjekte aufgrund der Reinitialisierung globaler Variablen in Indikatoren dynamisch erstellt werden.


Schlussfolgerung

In diesem Artikel habe ich die Kalenderobjektklasse die Klasse für einen vereinfachten Zugriff auf die Kalendereigenschaften und den Empfang von Ereigniswerten erstellt. Die Kalenderdatenbank ist recht umfangreich und erlaubt es, wichtige wirtschaftliche Ereignisse zu analysieren, ohne auf fremde Ressourcen zurückgreifen zu müssen.

Das Archiv enthält den im Artikel verwendeten Quellcode. Auf meinem PC befinden sich alle Dateien und Ordner in %MQL5\Shared Projects\Testing\Calendar. Wenn Sie die Quellen anders lokalisieren, achten Sie auf die korrekte Einbindung der Header-Datei CalendarInfo.mqh mit Hilfe der #include-Direktive.

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

Beigefügte Dateien |
Code.zip (31.04 KB)
Ein manuelles Chart- und Handelswerkzeug (Teil III). Optimierungen und neue Werkzeuge Ein manuelles Chart- und Handelswerkzeug (Teil III). Optimierungen und neue Werkzeuge
In diesem Artikel werden wir die Idee des Zeichnens von grafischen Objekten auf Charts mit Hilfe von Tastenkombinationen weiterentwickeln. Der Bibliothek wurden neue Werkzeuge hinzugefügt, darunter eine gerade Linie, die durch beliebige Scheitelpunkte gezeichnet wird, und eine Reihe von Rechtecken, die die Auswertung der Umkehrzeit und des Levels ermöglichen. Außerdem zeigt der Artikel die Möglichkeit, den Code zu optimieren, um die Leistung zu verbessern. Das Implementierungsbeispiel wurde umgeschrieben, sodass Shortcuts neben anderen Handelsprogrammen verwendet werden können. Erforderliche Code-Kenntnisse: etwas höher als die eines Anfängers.
Ein Versuch, einen EA-Konstruktor zu entwickeln Ein Versuch, einen EA-Konstruktor zu entwickeln
In diesem Artikel biete ich eine Reihe von Handelsfunktionen in Form eines fertigen EA an. Diese Methode ermöglicht es, durch einfaches Hinzufügen von Indikatoren und Ändern von Eingaben mehrere Handelsstrategien zu erstellen.
Websockets für MetaTrader 5 — Unter Verwendung der Windows API Websockets für MetaTrader 5 — Unter Verwendung der Windows API
In diesem Artikel werden wir die WinHttp.dll verwenden, um einen Websocket-Client für MetaTrader 5-Programme zu erstellen. Der Client wird letztendlich als Klasse implementiert und auch gegen die Binary.com Websocket API getestet.
Grafiken in der Bibliothek DoEasy (Teil 88): Grafische Objektkollektion — zweidimensionales dynamisches Array zur Speicherung der sich dynamisch ändernden Objekteigenschaften Grafiken in der Bibliothek DoEasy (Teil 88): Grafische Objektkollektion — zweidimensionales dynamisches Array zur Speicherung der sich dynamisch ändernden Objekteigenschaften
In diesem Artikel werde ich eine dynamische mehrdimensionale Array-Klasse erstellen, die die Möglichkeit bietet, die Datenmenge in jeder Dimension zu ändern. Auf der Grundlage der erstellten Klasse werde ich ein zweidimensionales dynamisches Array erstellen, um einige dynamisch veränderte Eigenschaften von grafischen Objekten zu speichern.