English Русский 中文 Español 日本語 Português
preview
Nachrichtenhandel leicht gemacht (Teil 3): Ausführen des Handels

Nachrichtenhandel leicht gemacht (Teil 3): Ausführen des Handels

MetaTrader 5Handel | 21 Oktober 2024, 13:24
137 0
Kabelo Frans Mampa
Kabelo Frans Mampa

Einführung

Zuvor haben wir einen Expert Advisor erstellt, um Wirtschaftsdaten in unserer Nachrichtenkalender-Datenbank zu speichern. Wir haben auch viele Kurse entwickelt, um eine Grundlage für unseren Experten zu schaffen, damit er angemessen arbeiten kann. In diesem Artikel werden wir diese Klassen in unserem Projekt weiter ausbauen, um schließlich zu unserem Ziel zu gelangen, mit Wirtschaftsdaten zu handeln. Unser nächstes Ziel wird die Rentabilität sein, die wir in den nächsten Artikeln behandeln werden. In diesem Artikel fügen wir eine neue Ansicht zu unserer Datenbank hinzu, um alle einzigartigen Ereignisse aus dem MQL5-Wirtschaftskalender anzuzeigen und Informationen über die verschiedenen Ereignisse bereitzustellen. Wir werden auch neue Eingaben in den Experten einfügen, um Wirtschaftsdaten beim Handel zu filtern und so für mehr Flexibilität zu sorgen. Sie können sich den vorherigen Artikel in der Serie „Nachrichtenhandel leicht gemacht“, in dem wir einen Risikomanagementkurs zum Risikomanagement für den Handel und weitere nützliche Informationen erstellt haben, falls Sie dies noch nicht getan haben. 



Was können Sie erwarten?

Verbesserte Grafiken, die prägnant, modern und auf das aktuelle Chart abgestimmt sind. Die folgende Abbildung zeigt diese Grafiken im hellen Modus.

    AUDUSD im hellen Modus (Abbildung)

    Abschnitte: 1,2,3,4,5,6,7,8 und 9 werden automatisch immer dann angezeigt, wenn sich der Experte in einem Chart befindet.

    Abschnitte: 10, (11 & 12 & 13 & 14 & 15 sind eine Gruppe) und 16 sind optional und werden bei jeder neuen 1-Minuten-Kerze aktualisiert (dies dient der Verbesserung der Leistung beim Backtesting).

    Abschnitt

    • 10: Zeigt das Datum und die Uhrzeit des Terminals an. Der Zeittext wird in rot angezeigt, wenn ein neues Ereignis eintritt, während das Chart im hellen Modus ist.
    • 11: Zeigt das Datum und die Uhrzeit des aktuellen/nächsten Nachrichtenereignisses an. Der Text wird in rot angezeigt, wenn Datum und Uhrzeit mit der Terminalzeit übereinstimmen.
    • 12: Zeigt den Namen des Nachrichtenereignisses an. Die Textfarbe ändert sich je nach Wichtigkeit des Ereignisses, z. B. wird „Hohe Wichtigkeit“ in Rot angezeigt.
    • 13: Zeigt den Ländernamen des Nachrichtenereignisses an. Die Textfarbe ändert sich in Abhängigkeit von der Bedeutung des Ereignisses und dem Farbmodus des Charts, z. B. im hellen Modus.
    • 14: Zeigt den Währungsnamen des Nachrichtenereignisses an. Die Textfarbe kann variieren.
    • 15: Zeigt die Wichtigkeit des Nachrichtenereignisses an. Die Textfarbe kann variieren.
    • 16: Zeigt den Spread für das aktuelle Symbol und die Bewertung an, die auf der Grundlage der Daten von Spreads von 1-Minuten-Kerzen aus zwei Wochen berechnet und in die Gruppen einteilt: exzellent, gut, normal, schlecht und schrecklich. Jede Kategorie wird in einer anderen Farbe angezeigt, wobei der dunkle und der helle Modus variieren können.

    Die folgende Abbildung zeigt, wie der dunkle Modus implementiert ist.

    Abschnitt

    • 17: Zeigt die Ereigniszeit aller Ereignisse an, die am aktuellen Tag des Terminals eintreten werden oder eingetreten sind. 

    AUDUSD im dunklen Modus (Abbildung)



    DISPLAY Eingänge

    • CHART COLOUR MODE: Mit dieser Option können Sie zwischen dem dunklen und dem hellen Modus wechseln.
    • DISPLAY NEWS INFO: Diese Option dient dazu, die Abschnitte (11 & 12 & 13& 14 & 15) auf dem Chart anzuzeigen oder nicht anzuzeigen.
    • DISPLAY EVENT OBJ: Mit dieser Option können Sie festlegen, ob Abschnitt 17 in der Tabelle angezeigt werden soll oder nicht.
    • DISPLAY SPREAD RATING: Mit dieser Option können Sie festlegen, ob Abschnitt 16 im Chart angezeigt werden soll oder nicht.
    • DISPLAY DATE: Mit dieser Option können Sie festlegen, ob Abschnitt 10 im Chart angezeigt werden soll oder nicht.

    Anzeige der Eingabeoptionen


    DST SCHEDULE Eingänge

    • WÄHLEN SIE DIE OPTION DST: Der Zweck dieser Option besteht darin, dem Nutzer/Händler die Möglichkeit zu geben, seinen eigenen Zeitplan für die Sommerzeit auszuwählen oder dem Experten die Möglichkeit zu geben, automatisch den empfohlenen Zeitplan für die Sommerzeit auszuwählen, um die Ereigniszeiten beim Backtesting im Strategietester korrekt zu konfigurieren.
    • SELECT CUSTOM DST: Mit dieser Option kann der Nutzer/Händler den Sommerzeitumstellung manuell konfigurieren.

    DST SCHEDULE Eingabeoptionen


    RISIKOMANAGEMENT Eingaben

    • SELECT RISK OPTION: Der Zweck dieser Option besteht darin, dem Nutzer/Händler die Möglichkeit zu geben, verschiedene Risikomanagementprofile auszuwählen, z.B. MINIMUM LOTSIZE, MAXIMUM LOTSIZE usw.
    • RISK FLOOR: Diese Option dient dazu, ein Mindestrisiko für alle Risikoprofile festzulegen. Wenn zum Beispiel nicht genug Geld für eine Losgröße von 1 Lot vorhanden ist, aber genug Geld für die minimale Lot-Größe von 0,01 Lot, dann wird 0,01 verwendet, um den Handel zu eröffnen, anstatt keinen Handel zu eröffnen, weil nicht genug Geld vorhanden war. Dies ist nur ein Sicherheitsnetz für den Fall, dass die Risikoprofile nicht angemessen konfiguriert wurden.
    • MAX-RISK: Der Zweck dieser Option besteht darin, einen Handel mit dem Prozentsatz der freien Marge auf dem Konto zu eröffnen, wenn nicht genug Geld für einen normalen Handel vorhanden ist. Diese Option ist nur verfügbar, wenn RISK FLOOR auf MAX-RISK eingestellt ist.
    • RISK CEILING: Der Zweck dieser Option besteht darin, eine Obergrenze für die Losgröße festzulegen, wenn das Konto groß genug ist, um die maximale Losgröße für ein bestimmtes Symbol zu eröffnen. Die Obergrenze unterscheidet sich von MAX LOTSIZE, was bedeutet, dass die maximal mögliche Losgröße diejenige ist, die durch das spezifische Symbol festgelegt ist, während MAX LOTSIZE(x2) zwei Handelsgeschäfte mit der maximalen Losgröße eröffnet, je nachdem, ob das Volumenlimit dies zulässt.
    • PERCENTAGE OF [BALANCE | FREE-MARGIN]: Der Zweck dieser Option besteht darin, einen bestimmten Prozentsatz des verfügbaren Saldos oder der freien Marge zu riskieren.
    • AMOUNT PER [BALANCE | FREE-MARGIN]: Der Zweck dieser Option ist es, einen bestimmten Wert des Saldos (balance) oder der freien Marge zu riskieren, z.B. wenn [BALANCE | FREE-MARGIN] auf 1000 und EACH AMOUNT auf 10 eingestellt ist, bedeutet dies, dass für den Währungswert von je 1000 des Saldos oder der freien Marge 10 Währungseinheiten für jeden Handel riskiert werden. Wenn also Ihr Saldo/freie Marge 1000 USD beträgt, riskieren Sie 10 USD in jedem Handelsgeschäft.
    • LOTSIZE PER [BALANCE | FREE-MARGIN]: Der Zweck dieser Option ist es, eine bestimmte Losgröße für einen Salden- oder freien Marge-Wert zu riskieren, z.B. wenn [BALANCE | FREE-MARGIN] auf 1000 und EACH LOTS(VOLUME) auf 0.1 gesetzt ist, bedeutet dies, dass für je 1000 des Saldo oder der freien Marge 0,1 Lot für jedes Handelsgeschäft riskiert wird. Wenn also Ihr Saldo/freie Marge 1000 USD beträgt, dann riskieren Sie 0,1 für jedes Handelsgeschäft.
    • CUSTOM LOTSIZE: Der Zweck dieser Option besteht darin, für jedes eröffneten Handel eine vorher festgelegte Losgröße zu riskieren.
    • PERCENTAGE OF MAX-RISK: Der Zweck dieser Option ist es, einen Prozentsatz des maximalen Risikovolumens für ein Symbol mit der verfügbaren freien Marge des Kontos zu riskieren. Wenn z.B. das maximale Risikovolumen für AUDUSD mit einer freien Marge des Kontos von 10.000 USD 100 Lots beträgt, dann wird, wenn wir PERCENTAGE OF MAX-RISK auf 25% setzen, die verwendete Lot-Größe 25% von 100 Lots sein, was 25 Lots entspricht.

    RISIKOMANAGEMENT Eingabemöglichkeiten


    NEWS SETTINGS Eingaben


    Die Nachrichteneinstellungen bestehen aus verschiedenen Eingabeoptionen, nämlich:

    1. CALENDAR IMPORTANCE (Bedeutung)
    2. EVENT FREQUENCY (Häufigkeit)
    3. EVENT SECTOR (Sektor)
    4. EVENT TYPE (Typ)
    5. EVENT CURRENCY (Währung)
    Diese Optionen sind in der folgenden Abbildung dargestellt.

    NEWS SETTINGS Eingabeoptionen

    • CALENDAR IMPORTANCE: Diese Option dient dazu, die Nachrichtendaten nach einer bestimmten Nachrichtenbedeutung zu filtern.

    CALENDAR IMPORTANCE Eingangsparameter

    • EVENT FREQUENCY: Mit dieser Option werden die Nachrichtendaten nach der Häufigkeit ihres Auftretens gefiltert.

    EVENT FREQUENCY Eingangsparameter

    • EVENT SECTOR: Diese Option dient dazu, die Nachrichtendaten auf der Grundlage des Sektors zu filtern.

    EVENT SECTOR Eingangsparameter

    • EVENT TYPE: Der Zweck dieser Option besteht darin, die Nachrichtendaten nach ihrem Typ zu filtern, z. B. wird EVENT typischerweise für Reden und Versammlungen verwendet, während INDICATOR für Zinssätze, Beschäftigungsdaten usw. und HOLIDAY für Nachrichtenjahre und verschiedene andere Feiertage steht.

    EVENT TYPE Eingangsparameter

    • EVENT CURRENCY: Diese Option dient dazu, die Nachrichtendaten auf der Grundlage der ausgewählten Währungsoptionen zu filtern. SYMBOL CURRENCIES berücksichtigt alle Währungen aus SYMBOL MARGIN, SYMBOL BASE und SYMBOL PROFIT.

    EVENT CURRENCY Eingangsparameter


    TRADE SETTINGS Eingaben

    • STOPLOSS[0=NONE]: Diese Option dient dazu, einen festen Stop-Loss für alle Handelsgeschäfte zu setzen. Wenn Stop-Loss auf Null gesetzt ist, haben alle Handelsgeschäfte keinen Wert für Stop-Loss.
    • TAKEPROFIT[0=NONE]: Der Zweck dieser Option besteht darin, einen festen Take-Profit für alle Handelsgeschäfte festzulegen. Wenn der Take-Profit auf Null gesetzt ist, haben alle Handelsgeschäfte keinen Take-Profit.
    • PRE-ENTRY SEC: Mit dieser Option kann der Nutzer/Händler die Anzahl der Sekunden konfigurieren, die ein Handelsgeschäft vor der Ereigniszeit geöffnet ist. Wenn also PRE-ENTRY SEC auf 5 eingestellt ist, bedeutet dies, dass 5 Sekunden vor dem Eintreten des Ereignisses die Zeitspanne für die Eröffnung von Handelsgeschäften vor der Ereigniszeit ist. Beispiel: Wenn der Zeitpunkt des Ereignisses 15:00 Uhr ist, dann ist der Handel ab 5 Sekunden vor dem Ereignis um 14:59:45-14:59:59 erlaubt.
    • TRADING DAY OF WEEK: Mit dieser Option können Sie einen beliebigen Wochentag filtern, z. B. Montag, Dienstag usw. 

    TRADE SETTINGS Eingabeoptionen

    Wir werden uns nun mit dem Code beschäftigen, der unseren Experten funktionsfähig macht.


    Klasse der Symbol-Eigenschaften

    Änderungen, die in Teil 2 gemacht wurden:

    • Deklaration der Enumeration für die Spread-Bewertung
    //Enumeration for Spread rating
    enum SpreadRating
      {
       SpreadRating_Terrible,//Terrible
       SpreadRating_Bad,//Bad
       SpreadRating_Normal,//Normal
       SpreadRating_Good,//Good
       SpreadRating_Excellent//Excellent
      };
    • Deklaration einer booleschen Variablen zur Konfiguration des Chart-Farbmodus
    bool isLightMode;//Variable to configure Chart color mode
    • Deklaration einer booleschen Funktion zum Abrufen von Spread Float, dem variablen Spread
    bool              SpreadFloat(string SYMBOL=NULL);//Retrieve Spread Float
    //+------------------------------------------------------------------+
    //|Retrieve Spread Float                                             |
    //+------------------------------------------------------------------+
    bool CSymbolProperties::SpreadFloat(string SYMBOL=NULL)
      {
       if(SetSymbolName(SYMBOL))//Set Symbol
         {
          return CSymbol.SpreadFloat();
         }
       Print("Unable to retrieve Symbol's Spread Float");
       return false;//Retrieve false when failed.
      }
    • Deklaration der Funktion Spread-Rating zum Abrufen des Spread-Ratings
    SpreadRating      SpreadValue(string SYMBOL=NULL);//Retrieve Spread Rating

    Diese Funktion muss einen Wert der Enumeration SpreadRating zurückgeben.

    //+------------------------------------------------------------------+
    //|Retrieve Spread Rating                                            |
    //+------------------------------------------------------------------+
    SpreadRating CSymbolProperties::SpreadValue(string SYMBOL=NULL)
      {
       if(SetSymbolName(SYMBOL))//Set Symbol
         {
          if(SpreadFloat(SYMBOL))//Check if Symbol has a floating Spread
            {
    
             //Declarations
             vector Spreads;
             int SpreadArray[],SpreadAvg=0,SpreadMax=0,SpreadMin=0,
                               SpreadUpper=0,SpreadLower=0,SpreadAvgUpper=0,
                               SpreadAvgLower=0,SpreadMidUpper=0,SpreadMidLower=0;
    
             //Get Spread data from CopySpread built-in function for 2 weeks using M1 timeframe.
             if(CopySpread(GetSymbolName(),PERIOD_M1,iTime(GetSymbolName(),PERIOD_W1,2),
                           iTime(GetSymbolName(),PERIOD_M1,0),SpreadArray)==-1)
               {
                Print("Error trying to retrieve spread values");
                return SpreadRating_Normal;//Retrieve default value when failed.
               }
             else
               {
                Spreads.Assign(SpreadArray);//Assign spread array into Spreads vector variable
    
                SpreadMax = int(Spreads.Max());//Assign max spread
                SpreadMin = int(Spreads.Min());//Assign min spread
                SpreadAvg = int(Spreads.Median());//Assign average spread
    
                //Divide Spread into sectors based of different averages.
                SpreadMidUpper = int((SpreadAvg+SpreadMax)/2);
                SpreadMidLower = int((SpreadAvg+SpreadMin)/2);
                SpreadAvgUpper = int((SpreadAvg+SpreadMidUpper)/2);
                SpreadAvgLower = int((SpreadAvg+SpreadMidLower)/2);
                SpreadUpper = int((SpreadMidUpper+SpreadMax)/2);
                SpreadLower = int((SpreadMidLower+SpreadMin)/2);
    
                int Spread = Spread(SYMBOL);//Assign Symbol's Spread
    
                if(Spread<SpreadLower||Spread==SpreadMin)//Excellent
                  {
                   return SpreadRating_Excellent;
                  }
                else
                   if(Spread>=SpreadLower&&Spread<SpreadAvgLower)//Good
                     {
                      return SpreadRating_Good;
                     }
                   else
                      if(Spread>=SpreadAvgLower&&Spread<=SpreadAvgUpper)//Normal
                        {
                         return SpreadRating_Normal;
                        }
                      else
                         if(Spread>SpreadAvgUpper&&Spread<=SpreadUpper)//Bad
                           {
                            return SpreadRating_Bad;
                           }
                         else//Terrible
                           {
                            return SpreadRating_Terrible;
                           }
               }
            }
          else
            {
             return SpreadRating_Normal;//Retrieve default value when spread is fixed.
            }
         }
       Print("Unable to retrieve Symbol's Spread Rating");
       return SpreadRating_Normal;//Retrieve default value when failed.
      }

    Zunächst wird das Symbol festgelegt, dann wird geprüft, ob das Symbol einen variablen Spread hat, bevor einfache Berechnungen zur Bewertung des Spreads auf der Grundlage seiner Durchschnittswerte durchgeführt werden. Wenn die Einstellung des Symbols fehlgeschlagen ist oder das Symbol keinen gleitenden Spread hat, geben wir SpreadRating_Normal als Standardwert zurück.

       if(SetSymbolName(SYMBOL))//Set Symbol
         {
          if(SpreadFloat(SYMBOL))//Check if Symbol has a floating Spread
            {

    Wenn wir das Symbol erfolgreich gesetzt haben und das Symbol eine variablen Spread hat, deklarieren wir eine Spreads-Vektorvariable und int-Variablen zum Speichern von Spread-Werten. Nachdem wir unsere Variablen deklariert haben, werden wir die Funktion CopySpread verwenden, um die Spread-Werte in unserer Variablen SpreadArray der 1-Minuten-Kerze, die 2 Wochen zurückliegt, bis zur aktuellen 1-Minuten-Kerze zu speichern. Wenn die Funktion CopySpread aus irgendeinem Grund fehlschlägt, wird SpreadRating_Normal als Standardwert zurückgegeben.

     //Declarations
             vector Spreads;
             int SpreadArray[],SpreadAvg=0,SpreadMax=0,SpreadMin=0,
                               SpreadUpper=0,SpreadLower=0,SpreadAvgUpper=0,
                               SpreadAvgLower=0,SpreadMidUpper=0,SpreadMidLower=0;
    
             //Get Spread data from CopySpread built-in function for 2 weeks using M1 timeframe.
             if(CopySpread(GetSymbolName(),PERIOD_M1,iTime(GetSymbolName(),PERIOD_W1,2),
                           iTime(GetSymbolName(),PERIOD_M1,0),SpreadArray)==-1)
               {
                Print("Error trying to retrieve spread values");
                return SpreadRating_Normal;//Retrieve default value when failed.
               }

    Sobald CopySpread erfolgreich ist, weisen wir dem Spreads-Vektor die Ganzzahlwerte aus unserem SpreadArray zu. Dann müssen wir grundlegende Informationen aus diesen Array-Werten abrufen, wie z. B. der maximale Spread während des zweiwöchigen Zeitraums sowie der minimale Spread und der durchschnittliche Spread; diese Werte werden entsprechend in SpreadMax, SpreadMin und SpreadAvg gespeichert. Wir wollen nun verschiedene Durchschnittswerte aus diesen drei vorherigen Werten ermitteln.

    Für die Variable SpreadMidUpper wollen wir den Durchschnitt zwischen SpreadAvg und SpreadMax, für die Variable SpreadMidLower wollen wir den Durchschnitt zwischen SpreadAvg und SpreadMin, für die Variable SpreadAvgUpper wollen wir den Durchschnitt zwischen SpreadAvg und SpreadMidUpper, für die Variable SpreadAvgLower wollen wir den Durchschnitt zwischen SpreadAvg und SpreadMidLower, für die Variable SpreadUpper wollen wir den Durchschnitt zwischen SpreadMidUpper und SpreadMax, für die Variable SpreadLower wollen wir den Durchschnitt zwischen SpreadMidLower und SpreadMin. Wir brauchen auch den aktuelle Spread des Symobls zum Vergleich, um den Spread zu klassifizieren.

    Spreads.Assign(SpreadArray);//Assign spread array into Spreads vector variable
    
                SpreadMax = int(Spreads.Max());//Assign max spread
                SpreadMin = int(Spreads.Min());//Assign min spread
                SpreadAvg = int(Spreads.Median());//Assign average spread
    
                //Divide Spread into sectors based of different averages.
                SpreadMidUpper = int((SpreadAvg+SpreadMax)/2);
                SpreadMidLower = int((SpreadAvg+SpreadMin)/2);
                SpreadAvgUpper = int((SpreadAvg+SpreadMidUpper)/2);
                SpreadAvgLower = int((SpreadAvg+SpreadMidLower)/2);
                SpreadUpper = int((SpreadMidUpper+SpreadMax)/2);
                SpreadLower = int((SpreadMidLower+SpreadMin)/2);
    
                int Spread = Spread(SYMBOL);//Assign Symbol's Spread

    Spread-Werte

    Wir haben 5 Klassifizierungen für den Spread, nämlich:

      • Excellent: Wenn der aktuelle Spread kleiner als die Variable SpreadLower oder gleich SpreadMin ist.
      • Good: Wenn der aktuelle Spread größer oder gleich der Variable SpreadLower ist und der aktuelle Spread kleiner ist als die Variable SpreadAvgLower.
      • Normal: Wenn der aktuelle Spread kleiner oder gleich der Variable SpreadAvgLower ist und der aktuelle Spread kleiner oder gleich der Variable SpreadAvgUpper ist.
      • Bad: Wenn der aktuelle Spread größer ist als SpreadAvgUpper und der aktuelle Spread kleiner oder gleich der Variable SpreadUpper ist.
      • Terrible: Wenn der aktuelle Spread größer ist als die Variable SpreadUpper

                if(Spread<SpreadLower||Spread==SpreadMin)//Excellent
                  {
                   return SpreadRating_Excellent;
                  }
                else
                   if(Spread>=SpreadLower&&Spread<SpreadAvgLower)//Good
                     {
                      return SpreadRating_Good;
                     }
                   else
                      if(Spread>=SpreadAvgLower&&Spread<=SpreadAvgUpper)//Normal
                        {
                         return SpreadRating_Normal;
                        }
                      else
                         if(Spread>SpreadAvgUpper&&Spread<=SpreadUpper)//Bad
                           {
                            return SpreadRating_Bad;
                           }
                         else//Terrible
                           {
                            return SpreadRating_Terrible;
                           }
    • Deklaration der Funktion zum Abrufen der Spread-Farbe auf der Grundlage ihrer Bewertung
    color             SpreadColor(string SYMBOL=NULL);//Retrieve Spread Color

    Um die Farbe des Spread für jeden Enumerationswert des Spread zu erhalten, werden wir eine Switch-Anweisung verwenden, da die Enumerationswerte konstant sind. Die Farben für jede Bewertung sind wie abgebildet:

      • Excellent: wenn im hellen Modus, dann clrBlue

    Excellent, heller Modus

     sonst clrLightCyan

    Excellent, dunkler Modus

      • Good: wenn im hellen Modus, dann clrCornflowerBlue

    Good, heller Modus
    sonst clrLightGreen
    Good dunkler Modus

      • Normal: wenn im hellen Modus, dann clrBlack
    Normal, heller Modus
     sonst clrWheat
    Normal, dunkler Modus
      • Bad: clrOrange
      • Terrible: clrRed
      • Standard: wenn im hellen Modus, dann clrBlack, sonst clrWheat

    //+------------------------------------------------------------------+
    //|Retrieve Spread Color                                             |
    //+------------------------------------------------------------------+
    color CSymbolProperties::SpreadColor(string SYMBOL=NULL)
      {
       switch(SpreadValue(SYMBOL))//Get Spread Rating value
         {
          case SpreadRating_Excellent://Excellent Spread
             return (isLightMode)?clrBlue:clrLightCyan;
             break;
          case SpreadRating_Good://Good Spread
             return (isLightMode)?clrCornflowerBlue:clrLightGreen;
             break;
          case SpreadRating_Normal://Normal Spread
             return (isLightMode)?clrBlack:clrWheat;
             break;
          case SpreadRating_Bad://Bad Spread
             return clrOrange;
             break;
          case SpreadRating_Terrible://Terrible Spread
             return clrRed;
             break;
          default://failed to be identified
             return (isLightMode)?clrBlack:clrWheat;//Retrieve default color when failed.
             break;
         }
      }
    • Deklaration einer String-Funktion zum Abrufen der Beschreibung des Spreads
    string            SpreadDesc(string SYMBOL=NULL);//Retrieve Spread Description
    //+------------------------------------------------------------------+
    //|Retrieve Spread Description                                       |
    //+------------------------------------------------------------------+
    string CSymbolProperties::SpreadDesc(string SYMBOL=NULL)
      {
       switch(SpreadValue(SYMBOL))//Get Spread Rating value
         {
          case SpreadRating_Excellent://Excellent Spread
             return "Excellent";
             break;
          case SpreadRating_Good://Good Spread
             return "Good";
             break;
          case SpreadRating_Normal://Normal Spread
             return "Normal";
             break;
          case SpreadRating_Bad://Bad Spread
             return "Bad";
             break;
          case SpreadRating_Terrible://Terrible Spread
             return "Terrible";
             break;
          default://failed to be identified
             return "Unknown";//Retrieve default value when failed.
             break;
         }
      }
    • Deklaration einer String-Funktion zum Abrufen der Symbolbeschreibung
    string            Description(string SYMBOL=NULL);//Retrieve Symbol's Description
    //+------------------------------------------------------------------+
    //|Retrieve Symbol's Description                                     |
    //+------------------------------------------------------------------+
    string CSymbolProperties::Description(string SYMBOL=NULL)
      {
       if(SetSymbolName(SYMBOL))//Set Symbol
         {
          return CSymbol.Description();
         }
       Print("Unable to retrieve Symbol's Description");
       return "";//Retrieve an empty string when failed.
      }

    Symbol Beschreibung


    Klasse der Chart-Eigenschaften Klasse

    Diese Klasse aus Teil 2 wurde umstrukturiert. Die Charteigenschaftsklasse wird nun abgeleitet von der Chartklasse aus den MQL5-Include-Klassen. In der Struktur ChartProp werden alle Charteigenschaften gespeichert, die wir ändern werden. Unsere öffentliche Funktion ChartRefresh ruft unsere Funktion ChartGet auf, die die Charteigenschaften initialisiert, und dann rufen wir die Funktion ChartSet auf, die das Chart mit unseren Charteigenschaftswerten aus ChartGet konfiguriert.

    #include "SymbolProperties.mqh"
    #include <Charts/Chart.mqh>
    CSymbolProperties CSymbol;//Symbol Properties object
    //+------------------------------------------------------------------+
    //|ChartProperties class                                             |
    //+------------------------------------------------------------------+
    class CChartProperties : public CChart
      {
    private:
    //Structure for chart properties
       struct ChartProp
         {
          ENUM_CHART_MODE mode;//Chart Mode
          color          clrBackground;//Chart Background Color
          color          clrForeground;//Chart Foreground Color
          color          clrLineLast;//Chart Line Color
          color          clrCandleBear;//Chart Bear Candle Color
          color          clrBarDown;//Chart Down Candle Color
          color          clrCandleBull;//Chart Bull Candle Color
          color          clrBarUp;//Chart Up Candle Color
          color          clrLineAsk;//Chart Ask Color
          color          clrLineBid;//Chart Bid Color
          color          clrChartLine;//Chart Line Color
          color          clrStopLevels;//Chart Stop Level Color
          color          clrVolumes;//Chart Volumes Color
          bool           Foreground;//Chart Foreground Visibility
          bool           ShowLineAsk;//Chart Ask Line Visibility
          bool           ShowLineBid;//Chart Bid Line Visibility
          bool           ShowPeriodSep;//Chart Period Separator Visibility
          bool           ShowOHLC;//Chart Open-High-Low-Close Visibility
          bool           ShowGrid;//Chart Grid Visibility
          ENUM_CHART_VOLUME_MODE ShowVolumes;//Chart Volumes Visibility
          bool           AutoScroll;//Chart Auto Scroll Option
          bool           Shift;//Chart Shift Option
          double         ShiftSize;//Chart Shift Size
          bool           ShowObjectDescr;//Chart Object Descriptions
          ulong          CHART_SHOW_TRADE_LEVELS;//Chart Trade Levels Visibility
          ulong          CHART_SHOW_ONE_CLICK;//Chart One Click Trading Visibility
          ulong          CHART_SHOW_TICKER;//Chart Ticker Visibility
          ulong          CHART_DRAG_TRADE_LEVELS;//Chart Drag Trade levels
          ENUM_CHART_POSITION Navigate;//Chart Navigate
         };
       ChartProp         DefaultChart,MyChart;//Used to store chart properties
       void              ChartSet(ChartProp &Prop);//Apply Chart format
       void              ChartGet();//Assign Chart property values
    public:
                         CChartProperties();//Constructor
                        ~CChartProperties(void);//Destructor
                         //Configure the chart
       void              ChartRefresh() {ChartGet();ChartSet(MyChart);}
       string            GetChartPeriodName();//Retrieve Period name
      };

    Im Konstruktor weisen wir der ererbten Variablen m_chart_id die aktuelle Chart-ID zu.

    //+------------------------------------------------------------------+
    //|Constructor                                                       |
    //+------------------------------------------------------------------+
    CChartProperties::CChartProperties()
      {
       m_chart_id=ChartID();//Set chart id
       ChartGet();//Get chart values
       ChartSet(MyChart);//customize chart
      }

    Für die Funktion ChartGet weisen wir unseren Variablen DefaultChart und MyChart Werte zu, wobei DefaultChart die aktuellen Charteigenschaften speichert, bevor wir das Chart ändern, und MyChart unsere nutzerdefinierten Werte speichert.

    //+------------------------------------------------------------------+
    //|Assign Chart property values                                      |
    //+------------------------------------------------------------------+
    void CChartProperties::ChartGet()
      {
       DefaultChart.mode = Mode();//assign chart mode
       MyChart.mode = CHART_CANDLES;//assign custom chart mode
       DefaultChart.clrBackground = ColorBackground();//assign Background color
       MyChart.clrBackground = (isLightMode)?clrWhite:clrBlack;//assign custom Background color
       DefaultChart.clrForeground = ColorForeground();//assign foreground color
       MyChart.clrForeground = (isLightMode)?clrBlack:clrWhite;//assign custom foreground color
       DefaultChart.clrLineLast = ColorLineLast();//assign Chart Line Color
       MyChart.clrLineLast = clrWhite;//assign custom Chart Line Color
       DefaultChart.clrCandleBear = ColorCandleBear();//assign Chart Bear Candle Color
       MyChart.clrCandleBear = clrBlack;//assign custom Chart Bear Candle Color
       DefaultChart.clrBarDown = ColorBarDown();//assign Chart Down Candle Color
       MyChart.clrBarDown = (isLightMode)?clrBlack:CSymbol.Background();//assign custom Chart Down Candle Color
       DefaultChart.clrCandleBull = ColorCandleBull();//assign Chart Bull Candle Color
       MyChart.clrCandleBull = CSymbol.Background();//assign custom Chart Bull Candle Color
       DefaultChart.clrBarUp = ColorBarUp();//assign Chart Up Candle Color
       MyChart.clrBarUp = (isLightMode)?clrBlack:CSymbol.Background();//assign custom Chart Up Candle Color
       DefaultChart.clrLineAsk = ColorLineAsk();//assign Chart Ask Color 
       MyChart.clrLineAsk = (isLightMode)?clrBlack:clrWhite;//assign custom Chart Ask Color
       DefaultChart.clrLineBid = ColorLineBid();//assign Chart Bid Color
       MyChart.clrLineBid = (isLightMode)?clrBlack:CSymbol.Background();//assign custom Chart Bid Color
       DefaultChart.clrChartLine = ColorChartLine();//assign Chart Line Color
       MyChart.clrChartLine = (isLightMode)?clrBlack:clrWhite;//assign custom Chart Line Color
       DefaultChart.clrStopLevels = ColorStopLevels();//assign Chart Stop Level Color
       MyChart.clrStopLevels = clrRed;//assign custom Chart Stop Level Color
       DefaultChart.clrVolumes = ColorVolumes();//assign Chart Volumes Color
       MyChart.clrVolumes = clrGreen;//assign custom Chart Volumes Color
       DefaultChart.Foreground = Foreground();//assign Chart Foreground Visibility
       MyChart.Foreground = false;//assign custom Chart Foreground Visibility
       DefaultChart.ShowLineAsk = ShowLineAsk();//assign Chart Ask Line Visibility
       MyChart.ShowLineAsk = true;//assign custom Chart Ask Line Visibility
       DefaultChart.ShowLineBid = ShowLineBid();//assign Chart Bid Line Visibility
       MyChart.ShowLineBid = true;//assign custom Chart Bid Line Visibility
       DefaultChart.ShowPeriodSep = ShowPeriodSep();//assign Chart Period Separator Visibility
       MyChart.ShowPeriodSep = true;//assign custom Chart Period Separator Visibility
       DefaultChart.ShowOHLC = ShowOHLC();//assign Chart Open-High-Low-Close Visibility
       MyChart.ShowOHLC = false;//assign custom Chart Open-High-Low-Close Visibility
       DefaultChart.ShowGrid = ShowGrid();//assign Chart Grid Visibility
       MyChart.ShowGrid = false;//assign custom Chart Grid Visibility
       DefaultChart.ShowVolumes = ShowVolumes();//assign Chart Volumes Visibility
       MyChart.ShowVolumes = CHART_VOLUME_HIDE;//assign custom Chart Volumes Visibility
       DefaultChart.AutoScroll = AutoScroll();//assign Chart Auto Scroll Option
       MyChart.AutoScroll = true;//assign custom Chart Auto Scroll Option
       DefaultChart.Shift = Shift();//assign Chart Shift Option
       MyChart.Shift = true;//assign custom Chart Shift Option
       DefaultChart.ShiftSize = ShiftSize();//assign Chart Shift Size
       MyChart.ShiftSize = 15;//assign custom Chart Shift Size
       DefaultChart.ShowObjectDescr = ShowObjectDescr();//assign Chart Object Descriptions
       MyChart.ShowObjectDescr = false;//assign custom Chart Object Descriptions
       DefaultChart.Navigate = CHART_END;//assign Chart Navigate
       MyChart.Navigate = CHART_END;//assign custom Chart Navigate
       //---assign Chart Trade Levels Visibility
       DefaultChart.CHART_SHOW_TRADE_LEVELS = ChartGetInteger(ChartId(),CHART_SHOW_TRADE_LEVELS);
       //---assign custom Chart Trade Levels Visibility
       MyChart.CHART_SHOW_TRADE_LEVELS = ulong(true);
       //---assign Chart One Click Trading Visibility
       DefaultChart.CHART_SHOW_ONE_CLICK = ChartGetInteger(ChartId(),CHART_SHOW_ONE_CLICK);
       //---assign custom Chart One Click Trading Visibility
       MyChart.CHART_SHOW_ONE_CLICK = ulong(false);
       //---assign Chart Ticker Visibility
       DefaultChart.CHART_SHOW_TICKER = ChartGetInteger(ChartId(),CHART_SHOW_TICKER);
       //---assign custom Chart Ticker Visibility
       MyChart.CHART_SHOW_TICKER = ulong(false);
       //---assign Chart Drag Trade levels
       DefaultChart.CHART_DRAG_TRADE_LEVELS = ChartGetInteger(ChartId(),CHART_DRAG_TRADE_LEVELS);
       //---assign custom Chart Drag Trade levels
       MyChart.CHART_DRAG_TRADE_LEVELS = ulong(false);
      }

    Unsere ChartSet-Funktion nimmt unsere ChartProp-Struktur als Argument, um das aktuelle Chart zu konfigurieren.

    //+------------------------------------------------------------------+
    //|Apply Chart format                                                |
    //+------------------------------------------------------------------+
    void CChartProperties::ChartSet(ChartProp &Prop)
      {
       Mode(Prop.mode);//Set Chart Candle Mode
       ColorBackground(Prop.clrBackground);//Set Chart Background Color
       ColorForeground(Prop.clrForeground);//Set Chart Foreground Color
       ColorLineLast(Prop.clrLineLast);//Set Chart Line Color
       ColorCandleBear(Prop.clrCandleBear);//Set Chart Bear Candle Color
       ColorBarDown(Prop.clrBarDown);//Set Chart Down Candle Color
       ColorCandleBull(Prop.clrCandleBull);//Set Chart Bull Candle Color
       ColorBarUp(Prop.clrBarUp);//Set Chart Up Candle Color
       ColorLineAsk(Prop.clrLineAsk);//Set Chart Ask Color
       ColorLineBid(Prop.clrLineBid);//Set Chart Bid Color
       ColorChartLine(Prop.clrChartLine);//Set Chart Line Color
       ColorStopLevels(Prop.clrStopLevels);//Set Chart Stop Level Color
       ColorVolumes(Prop.clrVolumes);//Set Chart Volumes Color
       Foreground(Prop.Foreground);//Set if Chart is in Foreground Visibility
       ShowLineAsk(Prop.ShowLineAsk);//Set Chart Ask Line Visibility
       ShowLineBid(Prop.ShowLineBid);//Set Chart Bid Line Visibility
       ShowPeriodSep(Prop.ShowPeriodSep);//Set Chart Period Separator Visibility
       ShowOHLC(Prop.ShowOHLC);//Set Chart Open-High-Low-Close Visibility
       ShowGrid(Prop.ShowGrid);//Set Chart Grid Visibility
       ShowVolumes(Prop.ShowVolumes);//Set Chart Volumes Visibility
       AutoScroll(Prop.AutoScroll);//Set Chart Auto Scroll Option
       Shift(Prop.Shift);//Set Chart Shift Option
       ShiftSize(Prop.ShiftSize);//Set Chart Shift Size Value
       ShowObjectDescr(Prop.ShowObjectDescr);//Set Chart Show Object Descriptions
       ChartSetInteger(ChartId(),CHART_SHOW_TRADE_LEVELS,Prop.CHART_SHOW_TRADE_LEVELS);//Set Chart Trade Levels Visibility
       ChartSetInteger(ChartId(),CHART_SHOW_ONE_CLICK,Prop.CHART_SHOW_ONE_CLICK);//Set Chart One Click Trading Visibility
       ChartSetInteger(ChartId(),CHART_SHOW_TICKER,Prop.CHART_SHOW_TICKER);//Set Chart Ticker Visibility
       ChartSetInteger(ChartId(),CHART_DRAG_TRADE_LEVELS,Prop.CHART_DRAG_TRADE_LEVELS);//Set Chart Drag Trade levels
       Navigate(Prop.Navigate);//Set Chart Navigate
      }

    Bei der Funktion GetChartPeriodName wird der Name der Chartperiode für das aktuelle Chart mithilfe einer Switch-Anweisung abgerufen.

    //+------------------------------------------------------------------+
    //|Retrieve Period name                                              |
    //+------------------------------------------------------------------+
    string CChartProperties::GetChartPeriodName()
      {
       switch(ChartPeriod(ChartId()))//Get chart Period with chart id
         {
          case PERIOD_M1:
             return("M1");
          case PERIOD_M2:
             return("M2");
          case PERIOD_M3:
             return("M3");
          case PERIOD_M4:
             return("M4");
          case PERIOD_M5:
             return("M5");
          case PERIOD_M6:
             return("M6");
          case PERIOD_M10:
             return("M10");
          case PERIOD_M12:
             return("M12");
          case PERIOD_M15:
             return("M15");
          case PERIOD_M20:
             return("M20");
          case PERIOD_M30:
             return("M30");
          case PERIOD_H1:
             return("H1");
          case PERIOD_H2:
             return("H2");
          case PERIOD_H3:
             return("H3");
          case PERIOD_H4:
             return("H4");
          case PERIOD_H6:
             return("H6");
          case PERIOD_H8:
             return("H8");
          case PERIOD_H12:
             return("H12");
          case PERIOD_D1:
             return("Daily");
          case PERIOD_W1:
             return("Weekly");
          case PERIOD_MN1:
             return("Monthly");
         }
       return("unknown period");
      }

    Unser Destruktor stellt die vorherige Konfiguration des Charts wieder her, bevor wir irgendwelche Änderungen am Chart vorgenommen haben.

    //+------------------------------------------------------------------+
    //|Destructor                                                        |
    //+------------------------------------------------------------------+
    CChartProperties::~CChartProperties()
      {
       ChartSet(DefaultChart);//restore chart default configuration
       m_chart_id=-1;//reset chart id
      }



    Klasse der Objekteigenschaften

    In dieser Klasse wurden einige Änderungen an allen für nutzerdefinierte Objekttextfarbe vorgenommen. In Teil 2 konnten Sie nur eine Objekttextfarbe für alle Textobjekte verwenden. Unsere Lösung besteht darin, außerhalb der Klasse eine Farbvariable namens TextObj_color zu deklarieren.

    #include "ChartProperties.mqh"
    color TextObj_color;
    //+------------------------------------------------------------------+
    //|ObjectProperties class                                            |
    //+------------------------------------------------------------------+
    class CObjectProperties:public CChartProperties
      {
    private:
       //Simple  chart objects structure
       struct ObjStruct
         {
          long           ChartId;
          string         Name;
         } Objects[];//ObjStruct variable array
    
       //-- Add chart object to Objects array
       void              AddObj(long chart_id,string name)
         {
          ArrayResize(Objects,Objects.Size()+1,Objects.Size()+2);
          Objects[Objects.Size()-1].ChartId=chart_id;
          Objects[Objects.Size()-1].Name=name;
         }
    
    protected:
       void              DeleteObj()
         {
          for(uint i=0;i<Objects.Size();i++)
            {
             ObjectDelete(Objects[i].ChartId,Objects[i].Name);
            }
         }
    
    public:
                         CObjectProperties(void) {}//Class constructor
    
       //-- Create Rectangle chart object
       void              Square(long chart_ID,string name,int x_coord,int y_coord,int width,int height,ENUM_ANCHOR_POINT Anchor);
    
       //-- Create text chart object
       void              TextObj(long chartID,string name,string text,int x_coord,int y_coord,
                                 ENUM_BASE_CORNER Corner=CORNER_LEFT_UPPER,int fontsize=10);
    
       //-- Create Event object
       void               EventObj(long chartID,string name,string description,datetime eventdate);
    
       //-- Class destructor removes all chart objects created previously
                        ~CObjectProperties(void)
         {
          DeleteObj();
         }
      };

    Wie wir unten sehen können, gibt es viele Parameter für die Textobj-Funktion. Um die Parameter nicht zu verlängern, werden wir nur Textobj_color verwenden, um die Farbe des Textobjekts zu ändern.

    //+------------------------------------------------------------------+
    //|Create text chart object                                          |
    //+------------------------------------------------------------------+
    void CObjectProperties::TextObj(long chartID,string name,string text,int x_coord,int y_coord,
                                    ENUM_BASE_CORNER Corner=CORNER_LEFT_UPPER,int fontsize=10)
      {
       ObjectDelete(chartID,name);//Delete previous object with the same name and chart id
       if(ObjectCreate(chartID,name,OBJ_LABEL,0,0,0))//Create object label
         {
          AddObj(chartID,name);//Add object to array
          ObjectSetInteger(chartID,name,OBJPROP_XDISTANCE,x_coord);//Set x Distance/coordinate
          ObjectSetInteger(chartID,name,OBJPROP_YDISTANCE,y_coord);//Set y Distance/coordinate
          ObjectSetInteger(chartID,name,OBJPROP_CORNER,Corner);//Set object's corner anchor
          ObjectSetString(chartID,name,OBJPROP_TEXT,text);//Set object's text
          ObjectSetInteger(chartID,name,OBJPROP_COLOR,TextObj_color);//Set object's color
          ObjectSetInteger(chartID,name,OBJPROP_FONTSIZE,fontsize);//Set object's font-size
         }
       else
         {
          Print("Failed to create object: ",name);
         }
      }

    Eine kleine Änderung wurde an unserer Funktion Quadrat vorgenommen, um verschiedene Hintergrundfarben je nach Farbmodus des Charts zu ermöglichen.

    //+------------------------------------------------------------------+
    //|Create Rectangle chart object                                     |
    //+------------------------------------------------------------------+
    void CObjectProperties::Square(long chart_ID,string name,int x_coord,int y_coord,int width,int height,ENUM_ANCHOR_POINT Anchor)
      {
       const int              sub_window=0;             // subwindow index
       const int              x=x_coord;                // X coordinate
       const int              y=y_coord;                // Y coordinate
       const color            back_clr=(isLightMode)?clrWhite:clrBlack;// background color
       const ENUM_BORDER_TYPE border=BORDER_SUNKEN;     // border type
       const color            clr=clrRed;               // flat border color (Flat)
       const ENUM_LINE_STYLE  style=STYLE_SOLID;        // flat border style
       const int              line_width=0;             // flat border width
       const bool             back=false;               // in the background
       const bool             selection=false;          // highlight to move
       const bool             hidden=true;              // hidden in the object list
    
       ObjectDelete(chart_ID,name);//Delete previous object with the same name and chart id
       if(ObjectCreate(chart_ID,name,OBJ_RECTANGLE_LABEL,sub_window,0,0))//create rectangle object label
         {
          AddObj(chart_ID,name);//Add object to array
          ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);//Set x Distance/coordinate
          ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);//Set y Distance/coordinate
          ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);//Set object's width/x-size
          ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);//Set object's height/y-size
          ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr);//Set object's background color
          ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_TYPE,border);//Set object's border type
          ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,Anchor);//Set objects anchor point
          ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);//Set object's color
          ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);//Set object's style
          ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,line_width);//Set object's flat border width
          ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);//Set if object is in foreground or not
          ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);//Set if object is selectable/dragable
          ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);//Set if object is Selected
          ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);//Set if object is hidden in object list
          ChartRedraw(chart_ID);
         }
       else
         {
          Print("Failed to create object: ",name);
         }
      }


    Die Header-Datei CommonVariables

    Für Handelszwecke habe ich beschlossen, eine Datenbank im Speicher zu erstellen. Diese Datenbank braucht einen Namen, und der Name berücksichtigt den Namen des Brokers, die aktuelle Chart-ID und ob der Experte im Strategietester ist oder nicht.  

    #define NEWS_DATABASE_MEMORY           StringFormat("Calendar_%s_%d_%s.sqlite",broker,ChartID(),(MQLInfoInteger(MQL_TESTER)?"TESTER":"REAL"))

    Die Enumeration Choice dient der Personalisierung und wird für die Eingabe des Experten verwendet; sie ersetzt den Datentyp Boolean. Die Enumeration DayOfTheWeek wird verwendet, um den Handelstag der Woche ohne Samstag und Sonntag auszuwählen. Die Boolesche Funktion Answer hingegen wandelt die Enumeration Choice in einen booleschen Datentyp um.

    enum Choice
      {
       Yes,//YES
       No//NO
      };
    
    enum DayOfTheWeek
      {
       Monday,//MONDAY
       Tuesday,//TUESDAY
       Wednesday,//WEDNESDAY
       Thursday,//THURSDAY
       Friday,//FRIDAY
       AllDays//ALL DAYS
      };
    
    //+------------------------------------------------------------------+
    //|Convert enumeration Choice into a boolean value                   |
    //+------------------------------------------------------------------+
    bool Answer(Choice choose)
      {
       return (choose==Yes)?true:false;
      }


    Die Klasse der Zeitvariablen

    Der Zweck dieser Klasse ist es, die Zeitdaten der Kerzen zu speichern. Diese Daten werden verwendet, um zu prüfen, ob sich eine neue Kerze gebildet hat.

    //+------------------------------------------------------------------+
    //|TimeVariables class                                               |
    //+------------------------------------------------------------------+
    class CTimeVariables
      {
    private:
       //---Array to store candlestick times
       datetime          CandleTime[2000];
    public:
                         CTimeVariables(void);
       //---Set Array index time
       void              SetTime(uint index,datetime time);
       //---Get Array index time
       datetime          GetTime(uint index);
      };

    Im Konstruktor wird eine Standardzeit für alle Indizes innerhalb des Array CandleTime festgelegt.

    //+------------------------------------------------------------------+
    //|Constructor                                                       |
    //+------------------------------------------------------------------+
    CTimeVariables::CTimeVariables()
      {
       for(uint i=0; i<CandleTime.Size(); i++)
         {
          CandleTime[i]=D'1970.01.01';
         }
      }

    In der Funktion SetTime haben wir zwei Parameter, einen für den Array-Index und den anderen für datetime. Wenn das Argument index größer oder gleich Null und kleiner als die CandleTime-Größe ist, wird der Array-Index dem Argument time zugewiesen. 

    //+------------------------------------------------------------------+
    //|Set Array index time                                              |
    //+------------------------------------------------------------------+
    void CTimeVariables::SetTime(uint index,datetime time)
      {
       if(index>=0&&index<CandleTime.Size())
         {
          CandleTime[index] = time;
         }
      }

    Die Funktion GetTime akzeptiert ein positives ganzzahliges Argument, um die Datumszeit aus dem Array zum Indexwert von CandleTime abzurufen, wenn das Argument index gültig ist.

    //+------------------------------------------------------------------+
    //|Get Array index time                                              |
    //+------------------------------------------------------------------+
    datetime CTimeVariables::GetTime(uint index)
      {
       return (index>=0&&index<CandleTime.Size())?CandleTime[index]:datetime(0);
      }


    Klasse des Zeitmanagements

    Wir werden die Enumeration DSTSchedule deklarieren, damit der Nutzer/Händler zwischen Auto DST oder Custom DST für die Eingabe des Experten wählen kann. Die Variable MySchedule wird zum Speichern der nutzerdefinierten Sommerzeit verwendet.

    //-- Enumeration for DST schedule
    enum DSTSchedule
      {
       AutoDst_Selection,//AUTO DST
       CustomDst_Selection//CUSTOM DST
      } MyDST;
    
    DST_type MySchedule;//Variable for custom DST schedule

    Die folgende Funktion gibt die Stunde für ein bestimmtes Datum in einem Integer-Datentyp zurück. 

    int               ReturnHour(datetime time);//Returns the Hour for a specific date
    //+------------------------------------------------------------------+
    //|Returns the Hour for a specific date                              |
    //+------------------------------------------------------------------+
    int CTimeManagement::ReturnHour(datetime time)
      {
       return Time(time).hour;
      }

    Die folgende Funktion gibt die Minute für ein bestimmtes Datum in einem Integer-Datentyp zurück. 

    int               ReturnMinute(datetime time);//Returns the Minute for a specific date
    //+------------------------------------------------------------------+
    //|Returns the Minute for a specific date                            |
    //+------------------------------------------------------------------+
    int CTimeManagement::ReturnMinute(datetime time)
      {
       return Time(time).min;
      }

    Die folgende Funktion gibt die Sekunde für ein bestimmtes Datum in einem Integer-Datentyp zurück. 

    int               ReturnSecond(datetime time);//Returns the Second for s specific date
    //+------------------------------------------------------------------+
    //|Returns the Second for s specific date                            |
    //+------------------------------------------------------------------+
    int CTimeManagement::ReturnSecond(datetime time)
      {
       return Time(time).sec;
      }

    Die folgende Funktion gibt die MqlDateTime für das Argument datetime zurück.

    //-- Will convert datetime to MqlDateTime
       MqlDateTime       Time(datetime Timetoformat);
    //+------------------------------------------------------------------+
    //|Will convert datetime to MqlDateTime                              |
    //+------------------------------------------------------------------+
    MqlDateTime CTimeManagement::Time(datetime Timetoformat)
      {
       TimeToStruct(Timetoformat,timeFormat);
       return timeFormat;
      }

    Die nachstehende Funktion gibt den Zeitstempel für das datetime-Argument time zurück, wobei Stunde, Minute und Sekunde geändert werden.

    //-- Will return a datetime with changes to the hour,minute and second
       datetime          Time(datetime time,int Hour,int Minute,int Second);
    //+------------------------------------------------------------------+
    //|Will return a datetime with changes to the hour,minute and second |
    //+------------------------------------------------------------------+
    datetime CTimeManagement::Time(datetime time,int Hour,int Minute,int Second)
      {
       timeFormat=Time(time);
       timeFormat.hour=Hour;
       timeFormat.min=Minute;
       timeFormat.sec=Second;
       return StructToTime(timeFormat);
      }

    Die nachstehende Funktion gibt den Zeitstempel für das datetime-Argument time zurück, wobei die Stunde und die Minute geändert werden.

    //-- Will return a datetime with changes to the hour and minute
       datetime          Time(datetime time,int Hour,int Minute);
    //+------------------------------------------------------------------+
    //|Will return a datetime with changes to the hour and minute        |
    //+------------------------------------------------------------------+
    datetime CTimeManagement::Time(datetime time,int Hour,int Minute)
      {
       timeFormat=Time(time);
       timeFormat.hour=Hour;
       timeFormat.min=Minute;
       return StructToTime(timeFormat);
      }

    Die folgende Funktion gibt true zurück, wenn die TimeTradeServer-Zeit innerhalb der Argumente BeginTime und EndTime liegt.

    //-- Check current time is within a time range
       bool              TimeIsInRange(datetime BeginTime,datetime EndTime);
    //+------------------------------------------------------------------+
    //|Check current time is within a time range                         |
    //+------------------------------------------------------------------+
    bool CTimeManagement::TimeIsInRange(datetime BeginTime,datetime EndTime)
      {
       if(BeginTime<=TimeTradeServer()&&EndTime>=TimeTradeServer())
         {
          return true;
         }
       return false;
      }

    Die folgende Funktion gibt true zurück, wenn die PreEvent-Datetime kleiner oder gleich TimeTradeServer und die EventTime größer als TimeTradeServer ist.

    //-- Check if current time is within preEvent time and Event time
       bool              TimePreEvent(datetime PreEvent,datetime Event);
    //+------------------------------------------------------------------+
    //|Check if current time is within preEvent time and Event time      |
    //+------------------------------------------------------------------+
    bool CTimeManagement::TimePreEvent(datetime PreEventTime,datetime EventTime)
      {
       if(PreEventTime<=TimeTradeServer()&&EventTime>TimeTradeServer())
         {
          return true;
         }
       return false;
      }

    Die nachstehende Funktion gibt die MqlDateTime für die aktuelle Zeit mit Änderung der Stunde und Minute zurück.

    //-- Return MqlDateTime for current date time with custom hour and minute
       MqlDateTime       Today(int Hour,int Minute);
    //+------------------------------------------------------------------+
    //|Return MqlDateTime for current date time with custom hour and     |
    //|minute                                                            |
    //+------------------------------------------------------------------+
    MqlDateTime CTimeManagement::Today(int Hour,int Minute)
      {
       TimeTradeServer(today);
       today.hour=Hour;
       today.min=Minute;
       return today;
      }

    Die nachstehende Funktion gibt die MqlDateTime für die aktuelle Zeit zurück, wobei Stunde, Minute und Sekunde geändert werden.

    //-- Return MqlDateTime for current date time with custom hour, minute and second
       MqlDateTime       Today(int Hour,int Minute,int Second);
    //+------------------------------------------------------------------+
    //|Return MqlDateTime for current date time with custom hour, minute |
    //|and second                                                        |
    //+------------------------------------------------------------------+
    MqlDateTime CTimeManagement::Today(int Hour,int Minute,int Second)
      {
       TimeTradeServer(today);
       today.hour=Hour;
       today.min=Minute;
       today.sec=Second;
       return today;
      }

    Die folgende Funktion gibt true zurück, wenn der aktuelle Tag gleich dem entsprechenden Wochentag ist oder die Enumeration DayOfTheWeek gleich AllDays ist.

    //-- Check current day of the week
       bool              isDayOfTheWeek(DayOfTheWeek Day);
    //+------------------------------------------------------------------+
    //|Check current day of the week                                     |
    //+------------------------------------------------------------------+
    bool CTimeManagement::isDayOfTheWeek(DayOfTheWeek Day)
      {
       switch(Day)
         {
          case  Monday://Monday
             if(DayOfWeek(TimeTradeServer())==MONDAY)
               {
                return true;
               }
             break;
          case Tuesday://Tuesday
             if(DayOfWeek(TimeTradeServer())==TUESDAY)
               {
                return true;
               }
             break;
          case Wednesday://Wednesday
             if(DayOfWeek(TimeTradeServer())==WEDNESDAY)
               {
                return true;
               }
             break;
          case Thursday://Thursday
             if(DayOfWeek(TimeTradeServer())==THURSDAY)
               {
                return true;
               }
             break;
          case Friday://Friday
             if(DayOfWeek(TimeTradeServer())==FRIDAY)
               {
                return true;
               }
             break;
          case AllDays://All days
             return true;
             break;
          default://Unknown
             break;
         }
       return false;
      }

    Die folgende Funktion gibt den Wochentag für ein bestimmtes Datum zurück.

    //-- Return enumeration Day of week for a certain date
       ENUM_DAY_OF_WEEK  DayOfWeek(datetime time);
    //+------------------------------------------------------------------+
    //|Return enumeration Day of week for a certain date                 |
    //+------------------------------------------------------------------+
    ENUM_DAY_OF_WEEK CTimeManagement::DayOfWeek(datetime time)
      {
       return (ENUM_DAY_OF_WEEK)Time(time).day_of_week;
      }


    Klasse der Kerzeneigenschaften

    Diese Klasse wurde um eine neue Funktion erweitert.

    //+------------------------------------------------------------------+
    //|CandleProperties class                                            |
    //+------------------------------------------------------------------+
    class CCandleProperties : public CChartProperties
      {
    private:
       CTimeManagement   Time;//TimeManagement object
       CTimeVariables    CTV;//Timevariables object
    public:
       double            Open(int CandleIndex,ENUM_TIMEFRAMES Period=PERIOD_CURRENT,string SYMBOL=NULL);//Retrieve Candle Open-Price
       double            Close(int CandleIndex,ENUM_TIMEFRAMES Period=PERIOD_CURRENT,string SYMBOL=NULL);//Retrieve Candle Close-Price
       double            High(int CandleIndex,ENUM_TIMEFRAMES Period=PERIOD_CURRENT,string SYMBOL=NULL);//Retrieve Candle High-Price
       double            Low(int CandleIndex,ENUM_TIMEFRAMES Period=PERIOD_CURRENT,string SYMBOL=NULL);//Retrieve Candle Low-Price
       bool              IsLargerThanPreviousAndNext(datetime CandleTime,int Offset,string SYMBOL);//Determine if one candle is larger than two others
       bool              NewCandle(int index,ENUM_TIMEFRAMES period=PERIOD_CURRENT,string SYMBOL=NULL);//Check if a new candle is present
      };

    Die Funktion NewCandle gibt true zurück, wenn sich eine neue Kerze gebildet hat, und speichert dann die Öffnungszeit der aktuellen Kerze mit der Funktion SetTime in der Klasse Timevariables. Die zuvor gespeicherte Zeit wird mit der Eröffnungszeit der aktuellen Kerze verglichen, um zu prüfen, ob die Zeiten unterschiedlich sind. Wenn die Zeiten unterschiedlich sind, gehen wir davon aus, dass sich eine neue Kerze gebildet hat.

    //+------------------------------------------------------------------+
    //|Check if a new candle is present                                  |
    //+------------------------------------------------------------------+
    bool CCandleProperties::NewCandle(int index,ENUM_TIMEFRAMES period=PERIOD_CURRENT,string SYMBOL=NULL)
      {
       if(CTV.GetTime(index) == iTime(((SYMBOL==NULL)?Symbol():SYMBOL),period,0))
         {
          return false;//Candle time are equal no new candles have formed
         }
       else
         {
         //--- Candle time has changed set the new time
          CTV.SetTime(index,iTime(((SYMBOL==NULL)?Symbol():SYMBOL),period,0));
          return true;
         }
      }


    Die Klasse der Handelssitzungen

    Der Zweck dieser Klasse ist es, die Handelszeiten der Sitzungen zu behandeln. In diesem Artikel werden wir die Zeiten der Handelssitzungen nicht verwenden, aber wir werden später eine Verwendung für diese Klasse haben. Diese Klasse wird von der Klasse TimeManagement abgeleitet, da diese Klasse die Funktionen von TimeManagement nutzen wird.

    Sitzungszeiten

    #include "Timemanagement.mqh"
    //+------------------------------------------------------------------+
    //|Sessions Class                                                    |
    //+------------------------------------------------------------------+
    class CSessions:CTimeManagement
      {
    public:
                         CSessions(void) {}
                        ~CSessions(void) {}
       //--- Check if trading Session has began
       bool              isSessionStart(int offsethour=0,int offsetmin=0);
       //--- Check if trading Session has ended
       bool              isSessionEnd(int offsethour=0,int offsetmin=45);
       //--- Get Session End datetime
       datetime          SessionEnd(int offsethour=0,int offsetmin=45);
      };

    Die folgende Funktion überprüft alle gültigen Handelssitzungen für das aktuelle Symbol und den Wochentag. Sobald die früheste Handelssitzung gefunden wurde, fügen wir einen Offset zu dieser Zeit hinzu, z.B. wenn die früheste Handelssitzung von 01:00-05:00 Uhr ist, dann ist unsere Offset-Stunde 1 und die Offset-Minute 0, unsere Handelssitzung wird um 02:00-05:00 Uhr beginnen. Der Zweck der Kenntnis der Anfangszeit der Börsensitzung besteht darin, große Spreads zu vermeiden, die normalerweise zu Beginn der Börsensitzung auftreten. Wenn unsere Handelssitzung gerade aktiv ist, gibt die Funktion true zurück. 

    //+------------------------------------------------------------------+
    //|Check if trading Session has started                              |
    //+------------------------------------------------------------------+
    bool CSessions::isSessionStart(int offsethour=0,int offsetmin=0)
      {
    //--- Declarations
       datetime datefrom,dateto,DateFrom[],DateTo[];
    
    //--- Find all session times
       for(int i=0; i<10; i++)
         {
          //--- Get the session dates for the current symbol and Day of week
          if(SymbolInfoSessionTrade(Symbol(),DayOfWeek(TimeTradeServer()),i,datefrom,dateto))
            {
             //--- Check if the end date's hour is at midnight
             if(ReturnHour(dateto)==00||ReturnHour(dateto)==24)
               {
                //--- Adjust the date to one minute before midnight
                dateto = Time(TimeTradeServer(),23,59);
               }
             //--- Re-adjust DateFrom Array size
             ArrayResize(DateFrom,int(ArraySize(DateFrom))+1,int(ArraySize(DateFrom))+2);
             //--- Assign the last array index datefrom value
             DateFrom[int(ArraySize(DateFrom))-1] = datefrom;
             //--- Re-adjust DateTo Array size
             ArrayResize(DateTo,int(ArraySize(DateTo))+1,int(ArraySize(DateTo))+2);
             //--- Assign the last array index dateto value
             DateTo[int(ArraySize(DateTo))-1] = dateto;
            }
         }
    
    //--- Check if there are session times
       if(DateFrom.Size()>0)
         {
          /* Adjust DateFrom index zero date as the first index date will be the earliest date
           from the whole array, we add the offset to this date only*/
          DateFrom[0] = TimePlusOffset(DateFrom[0],MinutesS(startoffsetmin));
          DateFrom[0] = TimePlusOffset(DateFrom[0],HoursS(startoffsethour));
          //--- Iterate through the whole array
          for(uint i=0; i<DateFrom.Size(); i++)
            {
             //--- Check if the current time is within the trading session
             if(TimeIsInRange(DateFrom[i],DateTo[i]))
               {
                return true;
               }
            }
         }
       else
         {
          //--- If there are no trading session times
          return true;
         }
       return false;
      }

    Die folgende Funktion gibt true zurück, wenn die Sitzung beendet ist. Bei einigen Brokern sind die Spreads eine Stunde vor Ende der Handelssitzung riesig, sodass diese Funktion uns helfen kann, den Handel zu diesen Zeiten zu vermeiden.

    //+------------------------------------------------------------------+
    //|Check if trading Session has ended                                |
    //+------------------------------------------------------------------+
    bool CSessions::isSessionEnd(int offsethour=0,int offsetmin=45)
      {
    //--- Declarations
       datetime datefrom,dateto,DateTo[],lastdate=0,sessionend;
    
    //--- Find all session times
       for(int i=0; i<10; i++)
         {
          //--- Get the session dates for the current symbol and Day of week
          if(SymbolInfoSessionTrade(Symbol(),DayOfWeek(TimeTradeServer()),i,datefrom,dateto))
            {
             //--- Check if the end date's hour is at midnight
             if(ReturnHour(dateto)==00||ReturnHour(dateto)==24)
               {
                //--- Adjust the date to one minute before midnight
                dateto = Time(TimeTradeServer(),23,59);
               }
             //--- Re-adjust DateTo Array size
             ArrayResize(DateTo,int(ArraySize(DateTo))+1,int(ArraySize(DateTo))+2);
             //--- Assign the last array index dateto value
             DateTo[int(ArraySize(DateTo))-1] = dateto;
            }
         }
    
    //--- Check if there are session times
       if(DateTo.Size()>0)
         {
          //--- Assign lastdate a default value
          lastdate = DateTo[0];
          //--- Iterate through the whole array
          for(uint i=0; i<DateTo.Size(); i++)
            {
             //--- Check for the latest date in the array
             if(DateTo[i]>lastdate)
               {
                lastdate = DateTo[i];
               }
            }
         }
       else
         {
          //--- If there are no trading session times
          return false;
         }
       /* get the current time and modify the hour and minute time to the lastdate variable
       and assign the new datetime to sessionend variable*/
       sessionend = Today(ReturnHour(lastdate),ReturnMinute(lastdate));
    //--- Re-adjust the sessionend dates with the minute and hour offsets
       sessionend = TimeMinusOffset(sessionend,MinutesS(offsetmin));
       sessionend = TimeMinusOffset(sessionend,HoursS(offsethour));
    
    //--- Check if sessionend date is more than the current time
       if(TimeTradeServer()<sessionend)
         {
          return false;
         }
       return true;
      }

    Die Funktion unten gibt das Datum des Endes der Handelssitzung für den aktuellen Tag zurück. Es gibt einige Einschränkungen für die Zeiten der Handelssitzungen in MQL5, ich habe bemerkt, dass während eines Feiertags einige Symbole viel früher schließen können, als die Zeit der Handelssitzung anzeigen würde, also ist das etwas, das man im Auge behalten sollte.

    //+------------------------------------------------------------------+
    //|Get Session End datetime                                          |
    //+------------------------------------------------------------------+
    datetime CSessions::SessionEnd(int offsethour=0,int offsetmin=45)
      {
    //--- Declarations
       datetime datefrom,dateto,DateTo[],lastdate=0,sessionend;
    
    //--- Find all session times
       for(int i=0; i<10; i++)
         {
          //--- Get the session dates for the current symbol and Day of week
          if(SymbolInfoSessionTrade(Symbol(),DayOfWeek(TimeTradeServer()),i,datefrom,dateto))
            {
             //--- Check if the end date's hour is at midnight
             if(CTV.ReturnHour(dateto)==00||CTV.ReturnHour(dateto)==24)
               {
                //--- Adjust the date to one minute before midnight
                dateto = Time(TimeTradeServer(),23,59);
               }
             //--- Re-adjust DateTo Array size
             ArrayResize(DateTo,int(ArraySize(DateTo))+1,int(ArraySize(DateTo))+2);
             //--- Assign the last array index dateto value
             DateTo[int(ArraySize(DateTo))-1] = dateto;
            }
         }
    
    //--- Check if there are session times
       if(DateTo.Size()>0)
         {
          //--- Assign lastdate a default value
          lastdate = DateTo[0];
          //--- Iterate through the whole array
          for(uint i=0; i<DateTo.Size(); i++)
            {
             //--- Check for the latest date in the array
             if(DateTo[i]>lastdate)
               {
                lastdate = DateTo[i];
               }
            }
         }
       else
         {
          //--- If there are no trading session times
          return 0;
         }
       /* get the current time and modify the hour and minute time to the lastdate variable
       and assign the new datetime to sessionend variable*/
       sessionend = Today(ReturnHour(lastdate),ReturnMinute(lastdate));
    //--- Re-adjust the sessionend dates with the minute and hour offsets
       sessionend = TimeMinusOffset(sessionend,MinutesS(offsetmin));
       sessionend = TimeMinusOffset(sessionend,HoursS(offsethour));
    //--- return sessionend date
       return sessionend;
      }


    Die Klasse der Nachrichten

    Diese Klasse ist die wichtigste im gesamten Projekt und mit über 1000 Codezeilen auch die größte. In Teil 2 haben wir diese Klasse und den Code, der mit der Kalenderdatenbank im gemeinsamen Ordner interagiert, erheblich verbessert. In diesem Artikel werden wir eine weitere Datenbank erstellen, aber dieses Mal wird die Datenbank im Speicher sein.

    Vorteile von DBs im Speicher im Vergleich zur Speicherung

    • Geschwindigkeit: In-Memory-Datenbanken speichern Daten direkt im Arbeitsspeicher, was zu deutlich schnelleren Lese- und Schreibvorgängen führt. Dies ist besonders vorteilhaft für Anwendungen, die Echtzeit-Datenverarbeitung und -Analyse erfordern. Da der Arbeitsspeicher viel schneller ist als ein Festplattenspeicher, ist der Zugriff auf Daten in einer In-Memory-Datenbank schneller. Dies verkürzt die Antwortzeiten und verbessert die Gesamtleistung.
    • Leistung: Die geringere Latenzzeit und der schnellere Datenzugriff führen zu einem höheren Durchsatz, d. h. die Datenbank kann mehr Transaktionen pro Sekunde verarbeiten. In-Memory-Datenbanken können große Datenmengen effizienter verarbeiten und eignen sich daher für Big-Data-Anwendungen, Analysen und andere rechenintensive Aufgaben.

    Wir werden weiterhin unsere DB im Speicher verwenden, wir werden die Daten aus der DB im Speicher sammeln und diese Daten in unsere neue DB im Speicher übertragen, um eine ausgeglichene Leistung beim Backtesting zu erreichen, da nur die DB im Speicher verwendet wird, was je nach den Spezifikationen Ihres Computers drastische Auswirkungen hat.

    Wir beginnen mit den Deklarationen außerhalb der Klasse, die in der Eingabe des Experten verwendet werden. Die Integer-Variable DBMemoryConnection enthält das Integer-Verbindungshandle für unsere Datenbank im Speicher. Die Enumeration Calendar_Importance wird verwendet, um in den Eingabeparametern des Experten die Bedeutung der einzelnen Ereignisse auszuwählen. Die Enumeration Event_Sector wird verwendet, um verschiedene Ereignisbereiche in den Eingabeparametern des Experten auszuwählen. Die Enumeration Event_Frequency wird verwendet, um verschiedene Ereignishäufigkeiten für den Eingabeparameter des Experten auszuwählen. Die Enumeration Event_Type wird verwendet, um verschiedene Ereignistypen für den Eingabeparameter des Experten auszuwählen. Die Enumeration Event_Currency wird verwendet, um im Eingabeparameter des Experten verschiedene Währungsoptionen für das Ereignis auszuwählen. Die Strukturvariable UpcomingNews Calendar speichert die Details des nächsten Wirtschaftsereignisses für den einfachen Zugriff in anderen Klassen/Dateien.

    int       DBMemoryConnection;//In memory database handle
    
    //--- Enumeration for Calendar Importance
    enum Calendar_Importance
      {
       Calendar_Importance_None,//NONE
       Calendar_Importance_Low,//LOW
       Calendar_Importance_Moderate,//MODERATE
       Calendar_Importance_High,//HIGH
       Calendar_Importance_All//ALL
      } myImportance;
    
    //--- Enumeration for Calendar Sector
    enum Event_Sector
      {
       Event_Sector_None,//NONE
       Event_Sector_Market,//MARKET
       Event_Sector_Gdp,//GDP
       Event_Sector_Jobs,//JOBS
       Event_Sector_Prices,//PRICES
       Event_Sector_Money,//MONEY
       Event_Sector_Trade,//TRADE
       Event_Sector_Government,//GOVERNMENT
       Event_Sector_Business,//BUSINESS
       Event_Sector_Consumer,//CONSUMER
       Event_Sector_Housing,//HOUSING
       Event_Sector_Taxes,//TAXES
       Event_Sector_Holidays,//HOLIDAYS
       Event_Sector_ALL//ALL
      } mySector;
    
    //--- Enumeration for Calendar Event Frequency
    enum Event_Frequency
      {
       Event_Frequency_None,//NONE
       Event_Frequency_Week,//WEEK
       Event_Frequency_Month,//MONTH
       Event_Frequency_Quarter,//QUARTER
       Event_Frequency_Year,//YEAR
       Event_Frequency_Day,//DAY
       Event_Frequency_ALL//ALL
      } myFrequency;
    
    //--- Enumeration for Calendar Event type
    enum Event_Type
      {
       Event_Type_Event,//EVENT
       Event_Type_Indicator,//INDICATOR
       Event_Type_Holiday,//HOLIDAY
       Event_Type_All//ALL
      } myType;
    
    //--- Enumeration for Calendar Event Currency
    enum Event_Currency
      {
       Event_Currency_Symbol,//SYMBOL CURRENCIES
       Event_Currency_Margin,//SYMBOL MARGIN
       Event_Currency_Base,//SYMBOL BASE
       Event_Currency_Profit,//SYMBOL PROFIT
       Event_Currency_ALL,//ALL CURRENCIES
       Event_Currency_NZD_NZ,//NZD -> NZ
       Event_Currency_EUR_EU,//EUR -> EU
       Event_Currency_JPY_JP,//JPY -> JP
       Event_Currency_CAD_CA,//CAD -> CA
       Event_Currency_AUD_AU,//AUD -> AU
       Event_Currency_CNY_CN,//CNY -> CN
       Event_Currency_EUR_IT,//EUR -> IT
       Event_Currency_SGD_SG,//SGD -> SG
       Event_Currency_EUR_DE,//EUR -> DE
       Event_Currency_EUR_FR,//EUR -> FR
       Event_Currency_BRL_BR,//BRL -> BR
       Event_Currency_MXN_MX,//MXN -> MX
       Event_Currency_ZAR_ZA,//ZAR -> ZA
       Event_Currency_HKD_HK,//HKD -> HK
       Event_Currency_INR_IN,//INR -> IN
       Event_Currency_NOK_NO,//NOK -> NO
       Event_Currency_USD_US,//USD -> US
       Event_Currency_GBP_GB,//GBP -> GB
       Event_Currency_CHF_CH,//CHF -> CH
       Event_Currency_KRW_KR,//KRW -> KW
       Event_Currency_EUR_ES,//EUR -> ES
       Event_Currency_SEK_SE,//SEK -> SE
       Event_Currency_ALL_WW//ALL -> WW
      } myCurrency;
    
    //--- Structure variable to store Calendar next Event data
    Calendar UpcomingNews;

    Zusätzliche Funktionalität für die Nachrichtenklasse:

    • Erweiterung der Enumeration CalendarComponentsEventInfo_View wurde hinzugefügt, um Ereignisdetails in der Kalender-Speicherdatenbank anzuzeigen, Currencies_View wurde hinzugefügt, um alle im MQL5-Wirtschaftskalender verfügbaren Währungen anzuzeigen.
    • Die Struktur Array CalendarContents wurde von 10 auf 12 vergrößert, um die beiden neuen Ansichten EventInfo_View und Currencies_View unterzubringen.
    • Deklaration einer DBMemory-Variable vom Strukturtyp MQL5CalendarContents zum Speichern von DB-Eigenschaften.
    • Deklaration der CalendarData-Struktur und Variablen, um alle Daten der Kalender-DB im gemeinsamen Ordner zu speichern.
    • Deklaration der Funktion GetCalendar, die alle gefilterten Daten aus der Kalender-DB im gemeinsamen Ordner anfordert und diese Daten im Array der Struktur CalendarData speichert. Die Daten dieses Arrays werden in unsere neue Kalender-DB im Speicher eingefügt, sobald sie erstellt ist.
    • Deklaration der Funktion GetAutoDST zum Abrufen der Enumeration DST_type aus der Tabelle AutoDST in der Kalender-DB im allgemeinen Ordner.
    • Deklaration der Funktion Request_Importance zum Abrufen der String-Anforderung für die Ereignisbedeutung auf der Grundlage der Enumeration Calendar_Importance.
    • Deklaration der Funktion Request_Frequency zum Abrufen der Zeichenkettenanforderung für die Ereignishäufigkeit auf der Grundlage der Enumeration Event_Frequency.
    • Deklaration der Funktion Request_Sector zum Abrufen der String-Anforderung für den Ereignissektor auf der Grundlage der Enumeration Event_Sector.
    • Deklaration der Funktion Request_Type zum Abrufen der String-Anforderung für den Ereignistyp auf der Grundlage der Enumeration Event_Type.
    • Deklaration der Funktion Request_Currency zum Abrufen der String-Anfrage für die Ereigniswährung auf der Grundlage der Enumeration Event_Currency.
    • Die Deklaration der Funktion EconomicDetailsMemory füllt das Array der NewsTime-Kalenderstruktur mit den Ereignissen für ein bestimmtes Datum.
    • Durch die Deklaration der Funktion CreateEconomicDatabaseMemory wird die Kalenderdatenbank im Speicher angelegt.
    • Durch die Deklaration der Funktion EconomicNextEvent wird die Strukturvariable UpcomingNews mit den nächsten Ereignisdaten aktualisiert.
    • Durch die Deklaration der Funktion GetImpact werden die Daten zu den Auswirkungen des bevorstehenden Ereignisses abgerufen.
    • Die Deklaration der Funktion IMPORTANCE konvertiert die Zeichenkette Importance in eine Enumeration der Wichtigkeit von Kalenderereignissen.
    • Die Deklaration der Funktion IMPORTANCE wird die Enumeration Calendar_Importance in die Enumeration Calendar Event Importance umwandeln.
    • Die Deklaration der Funktion GetImportance konvertiert die Enumeration der Wichtigkeit von Kalenderereignissen in die Zeichenkette Importance Rating.
    • Durch die Deklaration der Funktion GetImportance_color wird die Farbe für jede Enumeration der Bedeutung von Kalenderereignissen abgerufen.
    • Die Deklaration der Funktion SECTOR wandelt die Enumeration Event_Sector in die Enumeration Calendar Event Sector um.
    • Die Deklaration der Funktion FREQUENCY wandelt die Enumeration Event_Frequency in die Enumeration Calendar Event Frequency um.
    • Die Deklaration der Funktion TYPE wandelt die Enumeration Event_Type in die Enumeration Calendar Event Type um.

    //+------------------------------------------------------------------+
    //|News class                                                        |
    //+------------------------------------------------------------------+
    class CNews : private CCandleProperties
      {
       //Private Declarations Only accessable by this class/header file
    private:
    
       //-- To keep track of what is in our database
       enum CalendarComponents
         {
          AutoDST_Table,//AutoDST Table
          CalendarAU_View,//View for DST_AU
          CalendarNONE_View,//View for DST_NONE
          CalendarUK_View,//View for DST_UK
          CalendarUS_View,//View for DST_US
          EventInfo_View,//View for Event Information
          Currencies_View,//View for Currencies
          Record_Table,// Record Table
          TimeSchedule_Table,//TimeSchedule Table
          MQL5Calendar_Table,//MQL5Calendar Table
          AutoDST_Trigger,//Table Trigger for AutoDST
          Record_Trigger//Table Trigger for Record
         };
    
       //-- structure to retrieve all the objects in the database
       struct SQLiteMaster
         {
          string         type;//will store object's type
          string         name;//will store object's name
          string         tbl_name;//will store table name
          int            rootpage;//will store rootpage
          string         sql;//Will store the sql create statement
         } DBContents[];//Array of type SQLiteMaster
    
       //--  MQL5CalendarContents inherits from SQLiteMaster structure
       struct MQL5CalendarContents:SQLiteMaster
         {
          CalendarComponents  Content;
          string         insert;//Will store the sql insert statement
         } CalendarContents[12],DBMemory;//Array to Store objects in our database
    
       CTimeManagement   CTime;//TimeManagement Object declaration
       CDaylightSavings_UK  Savings_UK;//DaylightSavings Object for the UK and EU
       CDaylightSavings_US  Savings_US;//DaylightSavings Object for the US
       CDaylightSavings_AU  Savings_AU;//DaylightSavings Object for the AU
    
       bool              AutoDetectDST(DST_type &dstType);//Function will determine Broker DST
       DST_type          DSTType;//variable of DST_type enumeration declared in the CommonVariables class/header file
       bool              InsertIntoTables(int db,Calendar &Evalues[]);//Function for inserting Economic Data in to a database's table
       void              CreateAutoDST(int db);//Function for creating and inserting Recommend DST for the Broker into a table
       bool              CreateCalendarTable(int db,bool &tableExists);//Function for creating a table in a database
       bool              CreateTimeTable(int db,bool &tableExists);//Function for creating a table in a database
       void              CreateCalendarViews(int db);//Function for creating views in a database
       void              CreateRecordTable(int db);//Creates a table to store the record of when last the Calendar database was updated/created
       string            DropRequest;//Variable for dropping tables in the database
    
       //-- Function for retrieving the MQL5CalendarContents structure for the enumartion type CalendarComponents
       MQL5CalendarContents CalendarStruct(CalendarComponents Content)
         {
          MQL5CalendarContents Calendar;
          for(uint i=0;i<CalendarContents.Size();i++)
            {
             if(CalendarContents[i].Content==Content)
               {
                return CalendarContents[i];
               }
            }
          return Calendar;
         }
    
       //--- To Store Calendar DB Data
       struct CalendarData
         {
          int            EventId;//Event Id
          string         Country;//Event Country
          string         EventName;//Event Name
          string         EventType;//Event Type
          string         EventImportance;//Event Importance
          string         EventCurrency;//Event Currency
          string         EventCode;//Event Code
          string         EventSector;//Event Sector
          string         EventForecast;//Event Forecast Value
          string         EventPreval;//Event Previous Value
          string         EventImpact;//Event Impact
          string         EventFrequency;//Event Frequency
          string         DST_UK;//DST UK
          string         DST_US;//DST US
          string         DST_AU;//DST AU
          string         DST_NONE;//DST NONE
         } DB_Data[],DB_Cal;//Structure variables
    
       //--- Will Retrieve all relevant Calendar data for DB in Memory from DB in Storage
       void              GetCalendar(CalendarData &Data[])
         {
          //--- Open calendar DB in Storage
          int db=DatabaseOpen(NEWS_DATABASE_FILE, DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE| DATABASE_OPEN_COMMON);
          if(db==INVALID_HANDLE)//Checks if the database was able to be opened
            {
             //if opening the database failed
             if(!FileIsExist(NEWS_DATABASE_FILE,FILE_COMMON))//Checks if the database Calendar exists in the common folder
               {
                return;//Returns true when the database was failed to be opened and the file doesn't exist in the common folder
               }
            }
          //--- Get filtered calendar DB data
          string SqlRequest = StringFormat("Select MQ.EventId,MQ.Country,MQ.EventName,MQ.EventType,MQ.EventImportance,MQ.EventCurrency,"
                                           "MQ.EventCode,MQ.EventSector,MQ.EventForecast,MQ.EventPreValue,MQ.EventImpact,MQ.EventFrequency,"
                                           "TS.DST_UK,TS.DST_US,TS.DST_AU,TS.DST_NONE from %s MQ "
                                           "Inner Join %s TS on TS.ID=MQ.ID "
                                           "Where %s and %s and %s and %s and %s;",
                                           CalendarStruct(MQL5Calendar_Table).name,CalendarStruct(TimeSchedule_Table).name,
                                           Request_Importance(myImportance),Request_Frequency(myFrequency),
                                           Request_Sector(mySector),Request_Type(myType),Request_Currency(myCurrency));
          //--- Process Sql request
          int Request = DatabasePrepare(db,SqlRequest);
          if(Request==INVALID_HANDLE)
            {
             //--- Print details if request failed.
             Print("DB: ",NEWS_DATABASE_FILE, " request failed with code ", GetLastError());
             Print("SQL");
             Print(SqlRequest);
            }
          else
            {
             //--- Clear data from whole array
             ArrayRemove(Data,0,WHOLE_ARRAY);
             //--- create structure variable to get data from request
             CalendarData data;
             //Assigning values from the sql query into Data structure array
             for(int i=0; DatabaseReadBind(Request,data); i++)
               {
                //--- Resize Data Array
                ArrayResize(Data,i+1,i+2);
                Data[i]  = data;
               }
            }
          DatabaseFinalize(Request);//Finalize request
          //--- Close Calendar database
          DatabaseClose(db);
         }
    
       //--- Retrieve the AutoDST enumeration data from calendar DB in storage
       DST_type          GetAutoDST()
         {
          string Sch_Dst;
          //--- open the database 'Calendar' in the common folder
          int db=DatabaseOpen(NEWS_DATABASE_FILE, DATABASE_OPEN_READONLY|DATABASE_OPEN_COMMON);
    
          if(db==INVALID_HANDLE)//Checks if 'Calendar' failed to be opened
            {
             if(!FileIsExist(NEWS_DATABASE_FILE,FILE_COMMON))//Checks if 'Calendar' database exists
               {
                Print("Could not find Database!");
                return DST_NONE;//return default value when failed.
               }
            }
    
          //--- Sql query to get AutoDST value
          string request_text="SELECT DST FROM 'AutoDST'";
          //--- Process sql request
          int request=DatabasePrepare(db,request_text);
          if(request==INVALID_HANDLE)
            {
             Print("DB: ",NEWS_DATABASE_FILE, " request failed with code ", GetLastError());
             DatabaseClose(db);//Close Database
             return DST_NONE;//return default value when failed.
            }
    
          //--- Read Sql request output data
          if(DatabaseRead(request))
            {
             //-- Store the first column data into string variable Sch_Dst
             if(!DatabaseColumnText(request,0,Sch_Dst))
               {
                Print("DatabaseRead() failed with code ", GetLastError());
                DatabaseFinalize(request);//Finalize request
                DatabaseClose(db);//Closes the database 'Calendar'
                return DST_NONE;//return default value when failed.
               }
            }
          DatabaseFinalize(request);//Finalize request
          DatabaseClose(db);//Closes the database 'Calendar'
          return (Sch_Dst=="DST_UK")?DST_UK:(Sch_Dst=="DST_US")?DST_US:
                 (Sch_Dst=="DST_AU")?DST_AU:DST_NONE;//Returns the enumeration value for each corresponding string
         }
    
       //--- Retrieve Sql request string for calendar event Importance
       string            Request_Importance(Calendar_Importance Importance)
         {
          //--- Constant request prefix string
          const string constant="MQ.EventImportance";
          //--- switch statement for Calendar_Importance enumeration
          switch(Importance)
            {
             case Calendar_Importance_All://String Request for all event Importance
                return constant+"<>'"+EnumToString(myImportance)+"'";
                break;
             default://String Request for any event Importance
                return constant+"='"+EnumToString(IMPORTANCE(myImportance))+"'";
                break;
            }
         }
    
       //--- Retrieve Sql request string for calendar event Frequency
       string            Request_Frequency(Event_Frequency Frequency)
         {
          //--- Constant request prefix string
          const string constant="MQ.EventFrequency";
          //--- switch statement for Event_Frequency enumeration
          switch(Frequency)
            {
             case Event_Frequency_ALL://String Request for all event frequencies
                return constant+"<>'"+EnumToString(myFrequency)+"'";
                break;
             default://String Request for any event frequency
                return constant+"='"+EnumToString(FREQUENCY(myFrequency))+"'";
                break;
            }
         }
    
       //--- Retrieve Sql request string for calendar event Sector
       string            Request_Sector(Event_Sector Sector)
         {
          //--- Constant request prefix string
          const string constant="MQ.EventSector";
          //--- switch statement for Event_Sector enumeration
          switch(Sector)
            {
             case Event_Sector_ALL://String Request for all event sectors
                return constant+"<>'"+EnumToString(mySector)+"'";
                break;
             default://String Request for any event sector
                return constant+"='"+EnumToString(SECTOR(mySector))+"'";
                break;
            }
         }
    
       //--- Retrieve Sql request string for calendar event type
       string            Request_Type(Event_Type Type)
         {
          //--- Constant request prefix string
          const string constant="MQ.EventType";
          //--- switch statement for Event_Type enumeration
          switch(Type)
            {
             case Event_Type_All://String Request for all event types
                return constant+"<>'"+EnumToString(myType)+"'";
                break;
             default://String request for any event type
                return constant+"='"+EnumToString(TYPE(myType))+"'";
                break;
            }
         }
    
       //--- Retrieve Sql request string for calendar event Currency
       string            Request_Currency(Event_Currency Currency)
         {
          //--- Constant request prefix string and request suffix
          const string constant_prefix="(MQ.EventCurrency",constant_suffix="')";
          //--- switch statement for Event_Currency enumeration
          switch(Currency)
            {
             case Event_Currency_ALL://String Request for all currencies
                return constant_prefix+"<>'"+EnumToString(myCurrency)+constant_suffix;
                break;
             case Event_Currency_Symbol://String Request for all symbol currencies
                return constant_prefix+"='"+CSymbol.CurrencyBase()+"' or MQ.EventCurrency='"+
                       CSymbol.CurrencyMargin()+"' or MQ.EventCurrency='"+CSymbol.CurrencyProfit()+constant_suffix;
                break;
             case Event_Currency_Margin://String Request for Margin currency
                return constant_prefix+"='"+CSymbol.CurrencyMargin()+constant_suffix;
                break;
             case Event_Currency_Base://String Request for Base currency
                return constant_prefix+"='"+CSymbol.CurrencyBase()+constant_suffix;
                break;
             case Event_Currency_Profit://String Request for Profit currency
                return constant_prefix+"='"+CSymbol.CurrencyProfit()+constant_suffix;
                break;
             case Event_Currency_NZD_NZ://String Request for NZD currency
                return constant_prefix+"='NZD' and MQ.EventCode='NZ"+constant_suffix;
                break;
             case Event_Currency_EUR_EU://String Request for EUR currency and EU code
                return constant_prefix+"='EUR' and MQ.EventCode='EU"+constant_suffix;
                break;
             case Event_Currency_JPY_JP://String Request for JPY currency
                return constant_prefix+"='JPY' and MQ.EventCode='JP"+constant_suffix;
                break;
             case Event_Currency_CAD_CA://String Request for CAD currency
                return constant_prefix+"='CAD' and MQ.EventCode='CA"+constant_suffix;
                break;
             case Event_Currency_AUD_AU://String Request for AUD currency
                return constant_prefix+"='AUD' and MQ.EventCode='AU"+constant_suffix;
                break;
             case Event_Currency_CNY_CN://String Request for CNY currency
                return constant_prefix+"='CNY' and MQ.EventCode='CN"+constant_suffix;
                break;
             case Event_Currency_EUR_IT://String Request for EUR currency and IT code
                return constant_prefix+"='EUR' and MQ.EventCode='IT"+constant_suffix;
                break;
             case Event_Currency_SGD_SG://String Request for SGD currency
                return constant_prefix+"='SGD' and MQ.EventCode='SG"+constant_suffix;
                break;
             case Event_Currency_EUR_DE://String Request for EUR currency and DE code
                return constant_prefix+"='EUR' and MQ.EventCode='DE"+constant_suffix;
                break;
             case Event_Currency_EUR_FR://String Request for EUR currency and FR code
                return constant_prefix+"='EUR' and MQ.EventCode='FR"+constant_suffix;
                break;
             case Event_Currency_BRL_BR://String Request for BRL currency
                return constant_prefix+"='BRL' and MQ.EventCode='BR"+constant_suffix;
                break;
             case Event_Currency_MXN_MX://String Request for MXN currency
                return constant_prefix+"='MXN' and MQ.EventCode='MX"+constant_suffix;
                break;
             case Event_Currency_ZAR_ZA://String Request for ZAR currency
                return constant_prefix+"='ZAR' and MQ.EventCode='ZA"+constant_suffix;
                break;
             case Event_Currency_HKD_HK://String Request for HKD currency
                return constant_prefix+"='HKD' and MQ.EventCode='HK"+constant_suffix;
                break;
             case Event_Currency_INR_IN://String Request for INR currency
                return constant_prefix+"='INR' and MQ.EventCode='IN"+constant_suffix;
                break;
             case Event_Currency_NOK_NO://String Request for NOK currency
                return constant_prefix+"='NOK' and MQ.EventCode='NO"+constant_suffix;
                break;
             case Event_Currency_USD_US://String Request for USD currency
                return constant_prefix+"='USD' and MQ.EventCode='US"+constant_suffix;
                break;
             case Event_Currency_GBP_GB://String Request for GBP currency
                return constant_prefix+"='GBP' and MQ.EventCode='GB"+constant_suffix;
                break;
             case Event_Currency_CHF_CH://String Request for CHF currency
                return constant_prefix+"='CHF' and MQ.EventCode='CH"+constant_suffix;
                break;
             case Event_Currency_KRW_KR://String Request for KRW currency
                return constant_prefix+"='KRW' and MQ.EventCode='KR"+constant_suffix;
                break;
             case Event_Currency_EUR_ES://String Request for EUR currency and ES code
                return constant_prefix+"='EUR' and MQ.EventCode='ES"+constant_suffix;
                break;
             case Event_Currency_SEK_SE://String Request for SEK currency
                return constant_prefix+"='SEK' and MQ.EventCode='SE"+constant_suffix;
                break;
             case Event_Currency_ALL_WW://String Request for ALL currency
                return constant_prefix+"='ALL' and MQ.EventCode='WW"+constant_suffix;
                break;
             default://String Request for no currencies
                return constant_prefix+"='"+constant_suffix;
                break;
            }
         }
    
       //Public declarations accessable via a class's Object
    public:
                         CNews(void);//Constructor
                        ~CNews(void);//Destructor
       void              CreateEconomicDatabase();//Creates the Calendar database for a specific Broker
       datetime          GetLatestNewsDate();//Gets the latest/newest date in the Calendar database
       void              EconomicDetails(Calendar &NewsTime[],datetime date_from=0,datetime date_to=0);//Gets values from the MQL5 economic Calendar
       void              EconomicDetailsMemory(Calendar &NewsTime[],datetime date);//Gets values from the MQL5 DB Calendar in Memory
       void              CreateEconomicDatabaseMemory();//Create calendar database in memory
       void              EconomicNextEvent(datetime date=0);//Will update UpcomingNews structure variable with the next event data
       bool              UpdateRecords();//Checks if the main Calendar database needs an update or not
       ENUM_CALENDAR_EVENT_IMPACT GetImpact();//Will retrieve Upcoming Event Impact data
    
       //--- Convert Importance string into Calendar Event Importance Enumeration
       ENUM_CALENDAR_EVENT_IMPORTANCE IMPORTANCE(string Importance)
         {
          //--- Calendar Importance is High
          if(Importance==EnumToString(CALENDAR_IMPORTANCE_HIGH))
            {
             return CALENDAR_IMPORTANCE_HIGH;
            }
          else
             //--- Calendar Importance is Moderate
             if(Importance==EnumToString(CALENDAR_IMPORTANCE_MODERATE))
               {
                return CALENDAR_IMPORTANCE_MODERATE;
               }
             else
                //--- Calendar Importance is Low
                if(Importance==EnumToString(CALENDAR_IMPORTANCE_LOW))
                  {
                   return CALENDAR_IMPORTANCE_LOW;
                  }
                else
                   //--- Calendar Importance is None
                  {
                   return CALENDAR_IMPORTANCE_NONE;
                  }
         }
    
       //--- Convert Calendar_Importance Enumeration into Calendar Event Importance Enumeration
       ENUM_CALENDAR_EVENT_IMPORTANCE IMPORTANCE(Calendar_Importance Importance)
         {
          //--- switch statement for Calendar_Importance enumeration
          switch(Importance)
            {
             case Calendar_Importance_None://None
                return CALENDAR_IMPORTANCE_NONE;
                break;
             case Calendar_Importance_Low://Low
                return CALENDAR_IMPORTANCE_LOW;
                break;
             case Calendar_Importance_Moderate://Moderate
                return CALENDAR_IMPORTANCE_MODERATE;
                break;
             case Calendar_Importance_High://High
                return CALENDAR_IMPORTANCE_HIGH;
                break;
             default://None
                return CALENDAR_IMPORTANCE_NONE;
                break;
            }
         }
    
       //--- Convert Calendar Event Importance Enumeration into string Importance Rating
       string            GetImportance(ENUM_CALENDAR_EVENT_IMPORTANCE Importance)
         {
          //--- switch statement for ENUM_CALENDAR_EVENT_IMPORTANCE enumeration
          switch(Importance)
            {
             case  CALENDAR_IMPORTANCE_HIGH://High
                return "HIGH";
                break;
             case CALENDAR_IMPORTANCE_MODERATE://Moderate
                return "MODERATE";
                break;
             case CALENDAR_IMPORTANCE_LOW://Low
                return "LOW";
                break;
             default://None
                return "NONE";
                break;
            }
         }
    
       //--- Retrieve color for each Calendar Event Importance Enumeration
       color             GetImportance_color(ENUM_CALENDAR_EVENT_IMPORTANCE Importance)
         {
          //--- switch statement for ENUM_CALENDAR_EVENT_IMPORTANCE enumeration
          switch(Importance)
            {
             case CALENDAR_IMPORTANCE_HIGH://High
                return clrRed;
                break;
             case CALENDAR_IMPORTANCE_MODERATE://Moderate
                return clrOrange;
                break;
             case CALENDAR_IMPORTANCE_LOW://Low
                return (isLightMode)?clrBlue:clrLightBlue;
                break;
             default://None
                return (isLightMode)?clrBlack:clrWheat;
                break;
            }
         }
    
       //--- Convert Event_Sector Enumeration into Calendar Event Sector Enumeration
       ENUM_CALENDAR_EVENT_SECTOR SECTOR(Event_Sector Sector)
         {
          //--- switch statement for Event_Sector enumeration
          switch(Sector)
            {
             case Event_Sector_None://NONE
                return CALENDAR_SECTOR_NONE;
                break;
             case Event_Sector_Market://MARKET
                return CALENDAR_SECTOR_MARKET;
                break;
             case Event_Sector_Gdp://GDP
                return CALENDAR_SECTOR_GDP;
                break;
             case Event_Sector_Jobs://JOBS
                return CALENDAR_SECTOR_JOBS;
                break;
             case Event_Sector_Prices://PRICES
                return CALENDAR_SECTOR_PRICES;
                break;
             case Event_Sector_Money://MONEY
                return CALENDAR_SECTOR_MONEY;
                break;
             case Event_Sector_Trade://TRADE
                return CALENDAR_SECTOR_TRADE;
                break;
             case Event_Sector_Government://GOVERNMENT
                return CALENDAR_SECTOR_GOVERNMENT;
                break;
             case Event_Sector_Business://BUSINESS
                return CALENDAR_SECTOR_BUSINESS;
                break;
             case Event_Sector_Consumer://CONSUMER
                return CALENDAR_SECTOR_CONSUMER;
                break;
             case Event_Sector_Housing://HOUSING
                return CALENDAR_SECTOR_HOUSING;
                break;
             case Event_Sector_Taxes://TAXES
                return CALENDAR_SECTOR_TAXES;
                break;
             case Event_Sector_Holidays://HOLIDAYS
                return CALENDAR_SECTOR_HOLIDAYS;
                break;
             default://Unknown
                return CALENDAR_SECTOR_NONE;
                break;
            }
         }
    
       //--- Convert Event_Frequency Enumeration into Calendar Event Frequency Enumeration
       ENUM_CALENDAR_EVENT_FREQUENCY FREQUENCY(Event_Frequency Frequency)
         {
          //--- switch statement for Event_Frequency enumeration
          switch(Frequency)
            {
             case  Event_Frequency_None://NONE
                return CALENDAR_FREQUENCY_NONE;
                break;
             case Event_Frequency_Day://DAY
                return CALENDAR_FREQUENCY_DAY;
                break;
             case Event_Frequency_Week://WEEK
                return CALENDAR_FREQUENCY_WEEK;
                break;
             case Event_Frequency_Month://MONTH
                return CALENDAR_FREQUENCY_MONTH;
                break;
             case Event_Frequency_Quarter://QUARTER
                return CALENDAR_FREQUENCY_QUARTER;
                break;
             case Event_Frequency_Year://YEAR
                return CALENDAR_FREQUENCY_YEAR;
                break;
             default://Unknown
                return CALENDAR_FREQUENCY_NONE;
                break;
            }
         }
    
       //--- Convert Event_Type Enumeration into Calendar Event Type Enumeration
       ENUM_CALENDAR_EVENT_TYPE TYPE(Event_Type Type)
         {
          //--- switch statement for Event_Type enumeration
          switch(Type)
            {
             case Event_Type_Event://EVENT
                return CALENDAR_TYPE_EVENT;
                break;
             case Event_Type_Indicator://INDICATOR
                return CALENDAR_TYPE_INDICATOR;
                break;
             case Event_Type_Holiday://HOLIDAY
                return CALENDAR_TYPE_HOLIDAY;
                break;
             default://Unknown
                return CALENDAR_TYPE_EVENT;
                break;
            }
         }
      };

    Wir werden zunächst die SQL-Anweisung in der Funktion GetCalendar durchgehen, die alle Daten aus der Kalender-DB im gemeinsamen Ordner für unsere Kalender-DB im Speicher anfordert. In dieser Anfrage wählen wir alle Spalten in der Tabelle MQL5Calendar und der Tabelle TimeSchedule aus und verbinden die Tabellen über gleiche IDs. Wir filtern dann die Daten auf der Grundlage der Enumerationen, die der Händler/Nutzer in den Eingabeparametern des Experten für die Nachrichteneinstellungen ausgewählt hat.

    //--- Get filtered calendar DB data
          string SqlRequest = StringFormat("Select MQ.EventId,MQ.Country,MQ.EventName,MQ.EventType,MQ.EventImportance,MQ.EventCurrency,"
                                           "MQ.EventCode,MQ.EventSector,MQ.EventForecast,MQ.EventPreValue,MQ.EventImpact,MQ.EventFrequency,"
                                           "TS.DST_UK,TS.DST_US,TS.DST_AU,TS.DST_NONE from %s MQ "
                                           "Inner Join %s TS on TS.ID=MQ.ID "
                                           "Where %s and %s and %s and %s and %s;",
                                           CalendarStruct(MQL5Calendar_Table).name,CalendarStruct(TimeSchedule_Table).name,
                                           Request_Importance(myImportance),Request_Frequency(myFrequency),
                                           Request_Sector(mySector),Request_Type(myType),Request_Currency(myCurrency));

    Schauen wir uns die SQL-Anfrage für die folgende Konfiguration der Nachrichteneinstellungen für das Symbol EURUSD an.

    Nachrichteneinstellungen Konfiguration 1

    Wie unten gezeigt, können wir sehen, wenn wir alle für die Kalenderbedeutung auswählen, konvertieren wir absichtlich nicht unsere Calendar_Importance Enumeration Variable myImportance, weil es keine Ereignisbedeutung mit dem Wert „Calendar_Importance_All“ gibt, sodass wir leicht alle Ereignisse auswählen können, bei denen die EventImportance nicht gleich „Calendar_Importance_All“ ist. Das Gleiche gilt für alle Eingabeparameter der Nachrichteneinstellungen, die auf ALL eingestellt sind.

    case Calendar_Importance_All://String Request for all event Importance
                return constant+"<>'"+EnumToString(myImportance)+"'";
    Select MQ.EventId,MQ.Country,MQ.EventName,MQ.EventType,MQ.EventImportance,MQ.EventCurrency,MQ.EventCode,MQ.EventSector,
    MQ.EventForecast,MQ.EventPreValue,MQ.EventImpact,MQ.EventFrequency,TS.DST_UK,TS.DST_US,TS.DST_AU,TS.DST_NONE from MQL5Calendar MQ
    Inner Join TimeSchedule TS on TS.ID=MQ.ID Where MQ.EventImportance<>'Calendar_Importance_All' and MQ.EventFrequency<>'Event_Frequency_ALL'
    and MQ.EventSector<>'Event_Sector_ALL' and MQ.EventType<>'Event_Type_All' and (MQ.EventCurrency='EUR' or MQ.EventCurrency='EUR' or 
    MQ.EventCurrency='USD');

    Sehen wir uns noch eine weitere SQL-Anfrage der Funktion GetCalendar für die folgende Konfiguration der Nachrichteneinstellungen für das Symbol EURUSD an.

    Nachrichteneinstellungen Konfiguration 2

    Wie unten gezeigt, wenn wir eine andere Option als alle für die Kalenderbedeutung auswählen, wandeln wir unsere Calendar_Importance Enumerationsvariable myImportance in den Enumerationstyp ENUM_CALENDAR_EVENT_IMPORTANCE um, sodass die Zeichenkette mit der in der MQL5Calendar-Tabelle gespeicherten übereinstimmen kann, um die Ereignisbedeutung eines bestimmten Typs korrekt zu ermitteln.

    default://String Request for any event Importance
                return constant+"='"+EnumToString(IMPORTANCE(myImportance))+"'";

    Select MQ.EventId,MQ.Country,MQ.EventName,MQ.EventType,MQ.EventImportance,MQ.EventCurrency,MQ.EventCode,MQ.EventSector,MQ.EventForecast,
    MQ.EventPreValue,MQ.EventImpact,MQ.EventFrequency,TS.DST_UK,TS.DST_US,TS.DST_AU,TS.DST_NONE from MQL5Calendar MQ Inner Join TimeSchedule TS 
    on TS.ID=MQ.ID Where MQ.EventImportance='CALENDAR_IMPORTANCE_HIGH' and MQ.EventFrequency='CALENDAR_FREQUENCY_MONTH' and 
    MQ.EventSector='CALENDAR_SECTOR_JOBS' and MQ.EventType='CALENDAR_TYPE_INDICATOR' and (MQ.EventCurrency<>'Event_Currency_ALL');

     Im Konstruktor der News-Klasse müssen wir die Array-Indizes für die neuen Ansichten für unsere Kalender-DB im gemeinsamen Ordner initialisieren. Für die Info-Ansicht der Ereignisse wird der Array-Index folgendermaßen initialisiert.

    //--- initializing properties for the EventInfo view
       CalendarContents[5].Content = EventInfo_View;
       CalendarContents[5].name = "Event Info";
       CalendarContents[5].sql = "CREATE VIEW IF NOT EXISTS 'Event Info' "
                                 "AS SELECT EVENTID as 'ID',COUNTRY as 'Country',EVENTNAME as 'Name',"
                                 "REPLACE(EVENTTYPE,'CALENDAR_TYPE_','') as 'Type',REPLACE(EVENTSECTOR,'CALENDAR_SECTOR_','') as 'Sector',"
                                 "REPLACE(EVENTIMPORTANCE,'CALENDAR_IMPORTANCE_','') as 'Importance',EVENTCURRENCY as 'Currency' "
                                 "FROM MQL5Calendar GROUP BY \"Name\" ORDER BY \"Country\" Asc,"
                                 "CASE \"Importance\" WHEN 'HIGH' THEN 1 WHEN 'MODERATE' THEN 2 WHEN 'LOW' THEN 3 ELSE 4 END,\"Sector\" Desc;";
       CalendarContents[5].tbl_name = "Event Info";
       CalendarContents[5].type = "view";

    Gehen wir die SQL-Anweisung durch, um die Ansicht „Event Info“ zu erstellen. Zuerst erstellen wir die Ansicht nur, wenn sie noch nicht existiert, dann wählen wir die Spalten ‚EVENTID‘ und benennen sie in ‚ID‘ um, ‚COUNTRY‘ und benennen sie in ‚Land‘, ‚EVENTNAME‘ und benennen sie in ‚Name‘ um, ‚EVENTTYPE‘ wir ersetzen den Text ‚CALENDAR_TYPE_‘ durch einen leeren String und benennen die Spalte in ‚Typ‘, ‚EVENTSECTOR‘ wir ersetzen den Text ‚CALENDAR_SECTOR_‘ durch einen leeren String und benennen die Spalte in ‚Sektor‘ um, ‚EVENTIMPORTANCE‘ wir ersetzen den Text ‚CALENDAR_IMPORTANCE_‘ durch eine leere Zeichenkette und benennen die Spalte ‚Importance‘ um, ‚EVENTCURRENCY‘ und benennen sie in ‚Currency‘ aus der Tabelle MQL5Calendar um. Dann gruppieren wir die Abfrage nach dem ‚EVENTNAME‘, der jetzt ‚Name‘ ist, damit die Ereignisse mit demselben Ereignisnamen nicht mehrfach in der Ansicht angezeigt werden. Dann geben wir der Abfrage eine Reihenfolge, zuerst ordnen wir das Ergebnis nach dem ‚Land‘ aufsteigend, sodass das Land mit dem Anfangsbuchstaben A wie Australien zuerst angezeigt wird, dann ordnen wir das Ergebnis nach der ‚EVENTIMPORTANZ‘, die jetzt ‚Importance‘ genannt wird Ich wollte also die Ereignisse mit der höchsten Wichtigkeit anzeigen. Dazu müssen wir den Textwerten der Bedeutung eine Rangfolge geben, sodass in diesem Fall, wenn die Wichtigkeit „HIGH“ ist, sie die erste Priorität erhält, dann erhält „MODERATE“ die zweite Priorität und „LOW“ die dritte Priorität und schließlich erhält jeder andere Wert die letzte Priorität. Außerdem ordnen wir das Abfrageergebnis nach dem „EVENTSECTOR“, der jetzt „Sector“ heißt, in absteigender Reihenfolge. Ein Beispiel für eine Ansicht wird unten gezeigt.

    CREATE VIEW IF NOT EXISTS 'Event Info' AS SELECT MQ.EVENTID as 'ID',MQ.COUNTRY as 'Country',MQ.EVENTNAME as 'Name',REPLACE(MQ.EVENTTYPE,
    'CALENDAR_TYPE_','') as 'Type',REPLACE(MQ.EVENTSECTOR,'CALENDAR_SECTOR_','') as 'Sector',REPLACE(MQ.EVENTIMPORTANCE,'CALENDAR_IMPORTANCE_','') 
    as 'Importance',MQ.EVENTCURRENCY as 'Currency' FROM MQL5Calendar MQ INNER JOIN TimeSchedule TS on TS.ID=MQ.ID GROUP BY "Name" ORDER BY 
    "Country" Asc,CASE "Importance" WHEN 'HIGH' THEN 1 WHEN 'MODERATE' THEN 2 WHEN 'LOW' THEN 3 ELSE 4 END,"Sector" Desc;

    Ansicht Veranstaltungsinformationen

    ID       Country  Name                                          Type            Sector        Importance   Currency
    36030006 Australia  RBA Governor Lowe Speech                    EVENT           MONEY         HIGH         AUD 
    36030008 Australia  RBA Interest Rate Decision                  INDICATOR       MONEY         HIGH         AUD 
    36010029 Australia  PPI q/q                                     INDICATOR       PRICES        MODERATE     AUD 
    36030014 Australia  RBA Trimmed Mean CPI q/q                    INDICATOR       PRICES        MODERATE     AUD 
    36030009 Australia  RBA Weighted Median CPI q/q                 INDICATOR       PRICES        MODERATE     AUD 
    36010031 Australia  Wage Price Index q/q                        INDICATOR       PRICES        MODERATE     AUD 
    36030026 Australia  RBA Assistant Governor Boulton Speech       EVENT           MONEY         MODERATE     AUD 
    36030024 Australia  RBA Assistant Governor Bullock Speech       EVENT           MONEY         MODERATE     AUD 
    36030025 Australia  RBA Assistant Governor Ellis Speech         EVENT           MONEY         MODERATE     AUD 
    
    62 lines later...
    
    76020002 Brazil  BCB Interest Rate Decision                     INDICATOR       MONEY         HIGH         BRL 
    76020004 Brazil  BCB Inflation Report                           EVENT           PRICES        MODERATE     BRL 
    76050001 Brazil  FIPE CPI m/m                                   INDICATOR       PRICES        MODERATE     BRL 
    76010005 Brazil  Mid-Month CPI m/m                              INDICATOR       PRICES        MODERATE     BRL 
    76020001 Brazil  BCB Focus Market Report                        EVENT           MONEY         MODERATE     BRL 
    76020003 Brazil  BCB MPC (Copom) Minutes                        EVENT           MONEY         MODERATE     BRL 
    76020005 Brazil  BCB National Monetary Council Meeting          EVENT           MONEY         MODERATE     BRL 
    76010009 Brazil  Unemployment Rate 3-months                     INDICATOR       JOBS          MODERATE     BRL 
    76020010 Brazil  Nominal Budget Balance                         INDICATOR       GOVERNMENT    MODERATE     BRL 
    76020011 Brazil  Primary Budget balance                         INDICATOR       GOVERNMENT    MODERATE     BRL 
    76010014 Brazil  Services Volume m/m                            INDICATOR       BUSINESS      MODERATE     BRL 
    
    98 lines later...
    
    124040017 Canada  BoC Governor Macklem Speech                   EVENT           MONEY          HIGH         CAD 
    124040003 Canada  BoC Governor Poloz Speech                     EVENT           MONEY          HIGH         CAD 
    124040006 Canada  BoC Interest Rate Decision                    INDICATOR       MONEY          HIGH         CAD 
    124040009 Canada  BoC Monetary Policy Report Press Conference   EVENT           MONEY          HIGH         CAD 
    124010011 Canada  Employment Change                             INDICATOR       JOBS           HIGH         CAD 
    124010021 Canada  GDP m/m                                       INDICATOR       GDP            HIGH         CAD 
    124010008 Canada  Core Retail Sales m/m                         INDICATOR       CONSUMER       HIGH         CAD 
    124020001 Canada  Ivey PMI                                      INDICATOR       BUSINESS       HIGH         CAD 
    124010024 Canada  IPPI m/m                                      INDICATOR       PRICES         MODERATE     CAD 
    124010026 Canada  RMPI m/m                                      INDICATOR       PRICES         MODERATE     CAD 
    124040001 Canada  BoC Business Outlook Survey                   EVENT           MONEY          MODERATE     CAD 
    

    Für unsere Ansicht Währungen wählen wir die eindeutigen/unterschiedlichen EventCurrency und EventCode aus der Tabelle MQL5Calendar.

    //--- initializing properties for the Currencies view
       CalendarContents[6].Content = Currencies_View;
       CalendarContents[6].name = "Currencies";
       CalendarContents[6].sql = "CREATE VIEW IF NOT EXISTS Currencies AS "
                                 "SELECT Distinct EventCurrency as 'Currency',EventCode as 'Code' FROM 'MQL5Calendar';";
       CalendarContents[6].tbl_name = "Currencies";
       CalendarContents[6].type = "view";
    SELECT * FROM 'Currencies';
    Currency  	Code
    NZD  		NZ
    EUR 		EU
    JPY  		JP
    CAD  		CA
    AUD  		AU
    CNY  		CN
    EUR  		IT
    SGD  		SG
    EUR  		DE
    EUR  		FR
    BRL  		BR
    MXN  		MX
    ZAR  		ZA
    HKD  		HK
    INR  		IN
    NOK  		NO
    USD  		US
    GBP  		GB
    CHF  		CH
    KRW  		KR
    EUR  		ES
    SEK  		SE
    ALL  		WW

    Jetzt werden wir die Eigenschaften für unsere Tabelle MQL5Calendar, die in unserer DB im Speicher sein wird, initialisieren. Diese Tabelle wird eine große Tabelle sein, die im Wesentlichen eine Kombination aus den Tabellen in unserer DB im Speicher ist, diese Tabellen sind MQL5Calendar und TimeSchedule.

    //-- initializing properties for the MQL5Calendar table for DB in System Memory
       DBMemory.Content = MQL5Calendar_Table;
       DBMemory.name = "MQL5Calendar";
       DBMemory.sql = "CREATE TABLE IF NOT EXISTS MQL5Calendar(EVENTID  INT   NOT NULL,COUNTRY  TEXT   NOT NULL,"
                      "EVENTNAME   TEXT   NOT NULL,EVENTTYPE   TEXT   NOT NULL,EVENTIMPORTANCE   TEXT   NOT NULL,"
                      "EVENTCURRENCY  TEXT   NOT NULL,EVENTCODE   TEXT   NOT NULL,EVENTSECTOR TEXT   NOT NULL,"
                      "EVENTFORECAST  TEXT   NOT NULL,EVENTPREVALUE  TEXT   NOT NULL,EVENTIMPACT TEXT   NOT NULL,"
                      "EVENTFREQUENCY TEXT   NOT NULL,DST_UK   TEXT   NOT NULL,DST_US   TEXT   NOT NULL,"
                      "DST_AU   TEXT   NOT NULL,DST_NONE   TEXT   NOT NULL)STRICT;";
       DBMemory.tbl_name="MQL5Calendar";
       DBMemory.type = "table";
       DBMemory.insert = "INSERT INTO 'MQL5Calendar'(EVENTID,COUNTRY,EVENTNAME,EVENTTYPE,EVENTIMPORTANCE,EVENTCURRENCY,EVENTCODE,"
                         "EVENTSECTOR,EVENTFORECAST,EVENTPREVALUE,EVENTIMPACT,EVENTFREQUENCY,DST_UK,DST_US,DST_AU,DST_NONE) "
                         "VALUES (%d,'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s', '%s', '%s');";

    In unserem Destruktor schließen wir die Verbindung zur Datenbank im Speicher, das Schließen der Verbindung zur Datenbank im Speicher wird die gesamte Datenbank löschen. Wir schließen die Verbindung also erst, wenn wir die Datenbank nicht mehr benötigen.

    //+------------------------------------------------------------------+
    //|Destructor                                                        |
    //+------------------------------------------------------------------+
    CNews::~CNews(void)
      {
       if(FileIsExist(NEWS_TEXT_FILE,FILE_COMMON))//Check if the news database open text file exists
         {
          FileDelete(NEWS_TEXT_FILE,FILE_COMMON);
         }
       DatabaseClose(DBMemoryConnection);//Close DB in memory
      }

    Zuvor haben wir in unserer Funktion UpdateRecords eine Sequenz durchlaufen, um zu prüfen, ob wir die Kalenderdatenbank im Speicher aktualisieren sollten. Der Ablauf war folgendermaßen:

    1. Wir prüfen, ob die Kalenderdatenbank im gemeinsamen Ordner vorhanden ist, und führen eine Aktualisierung durch, wenn die Datenbank nicht vorhanden ist.
    2. Wir prüfen, ob alle Datenbankobjekte in der Datenbank vorhanden sind und ob ihre SQL-Anweisungen den Erwartungen entsprechen; wenn nicht, führen wir eine Aktualisierung durch.
    3. Wir prüfen, ob das Datum in der Tabelle Datensätze mit dem aktuellen Datum übereinstimmt, wenn nicht, führen wir eine Aktualisierung durch.

    In diesem Artikel fügen wir einen weiteren Schritt in der Abfolge hinzu. Der Zweck dieses zusätzlichen Schrittes ist es, zu überprüfen, ob die Nachrichtendaten in der Ansicht Calendar_NONE korrekt sind. Ich habe festgestellt, dass sich die Nachrichtendaten aus dem MQL5-Kalender manchmal im Laufe der Zeit ändern können, und wenn wir die Nachrichten gespeichert haben, die sich nicht geändert haben, müssen wir in der Lage sein, auf Unstimmigkeiten zwischen dem, was wir gespeichert haben, und dem, was aus dem MQL5-Kalender aktualisiert wurde, zu prüfen.

    Im nachstehenden Code werden die Nachrichtendaten für den aktuellen Tag mit der Funktion EconomicDetails abgerufen und in dem Array TodayNews gespeichert. Sobald sich die Nachrichtendaten im TodayNews-Array befinden, durchlaufen wir jedes Nachrichtenereignis im Array und prüfen, ob es eine Übereinstimmung in unserer Ansicht Calendar_NONE gibt. Wenn wir keine Übereinstimmung finden können, führen wir eine Aktualisierung durch. Wenn alle Nachrichtendaten in der Ansicht Calendar_NONE übereinstimmen, werden keine Aktualisierungen der Datenbank im Speicher vorgenommen.

          Calendar TodaysNews[];
          datetime Today = CTime.Time(TimeTradeServer(),0,0,0);
          EconomicDetails(TodaysNews,Today,Today+CTime.DaysS());
    
          for(uint i=0;i<TodaysNews.Size();i++)
            {
             request_text=StringFormat("SELECT ID FROM %s where Replace(Date,'.','-')=Replace('%s','.','-') and ID=%d;",
                                       CalendarStruct(CalendarNONE_View).name,TodaysNews[i].EventDate,TodaysNews[i].EventId);
             request=DatabasePrepare(db,request_text);//Creates a handle of a request, which can then be executed using DatabaseRead()
             if(request==INVALID_HANDLE)//Checks if the request failed to be completed
               {
                Print("DB: ",NEWS_DATABASE_FILE, " request failed with code ", GetLastError());
                DatabaseFinalize(request);
                DatabaseClose(db);
                return perform_update;
               }
             //PrintFormat(request_text);
             if(!DatabaseRead(request))//Will be true if there are results from the sql query/request
               {
                DatabaseFinalize(request);
                DatabaseClose(db);
                return perform_update;
               }
             DatabaseFinalize(request);
            }
          DatabaseClose(db);//Closes the database
          perform_update=false;
          return perform_update;

    Der folgende Code ist für die Erstellung der Datenbank im Speicher zuständig. Zunächst öffnen wir die Verbindung zur Datenbank, dann löschen wir die Tabelle MQL5Calendar, falls sie bereits existiert, und erstellen dann die Tabelle MQL5Calendar. Sobald die Tabelle erstellt ist, erhalten wir alle relevanten Daten von der Funktion GetCalendar, wir fügen dann alle von der Funktion abgerufenen Daten in unsere MQL5Calendar-Tabelle in unserer Datenbank im Speicher ein. Außerdem löschen wir das gesamte Array DB_Data und legen unseren Sommerzeitplan in der Variablen MySchedule fest. Für den Handel außerhalb des Strategietesters kann der Nutzer/Händler den Sommerzeitplan nicht manuell ändern, um zu verhindern, dass ein falscher Sommerzeitplan konfiguriert wird, da die Konfiguration des Sommerzeitplans nur für den Strategietester erforderlich ist.

    //+------------------------------------------------------------------+
    //|Create calendar database in memory                                |
    //+------------------------------------------------------------------+
    void CNews::CreateEconomicDatabaseMemory()
      {
    //--- Open/create the database in memory
       DBMemoryConnection=DatabaseOpen(NEWS_DATABASE_MEMORY,DATABASE_OPEN_MEMORY);
       if(DBMemoryConnection==INVALID_HANDLE)//Checks if the database failed to open/create
         {
          Print("DB: ",NEWS_DATABASE_MEMORY, " open failed with code ", GetLastError());
          return;//will terminate execution of the rest of the code below
         }
    //--- Drop the table if it already exists
       DatabaseExecute(DBMemoryConnection,StringFormat("Drop table IF EXISTS %s",DBMemory.name));
    //--- Attempt to create the table
       if(!DatabaseExecute(DBMemoryConnection,DBMemory.sql))
         {
          Print("DB: create the Calendar table failed with code ", GetLastError());
          return;
         }
    //--- Check if the table exists
       if(DatabaseTableExists(DBMemoryConnection,DBMemory.tbl_name))
         {
          //--- Get all news data and time from the database in storage
          GetCalendar(DB_Data);
          //--- Insert all the news data and times into the table
          for(uint i=0;i<DB_Data.Size();i++)
            {
             string request_text=StringFormat(DBMemory.insert,DB_Data[i].EventId,DB_Data[i].Country,
                                              DB_Data[i].EventName,DB_Data[i].EventType,DB_Data[i].EventImportance,
                                              DB_Data[i].EventCurrency,DB_Data[i].EventCode,DB_Data[i].EventSector,
                                              DB_Data[i].EventForecast,DB_Data[i].EventPreval,DB_Data[i].EventImpact,
                                              DB_Data[i].EventFrequency,DB_Data[i].DST_UK,DB_Data[i].DST_US,
                                              DB_Data[i].DST_AU,DB_Data[i].DST_NONE);
    
             if(!DatabaseExecute(DBMemoryConnection, request_text))//Will attempt to run this sql request/query
               {
                //--- failed to run sql request/query
                Print(GetLastError());
                PrintFormat(request_text);
                return;
               }
            }
         }
    //--- Remove all data from the array
       ArrayRemove(DB_Data,0,WHOLE_ARRAY);
    //--- Assign the DST schedule
       MySchedule = (MQLInfoInteger(MQL_TESTER))?(MyDST==AutoDst_Selection)?GetAutoDST():MySchedule:DST_NONE;
      }

    Ok, jetzt ruft die folgende Funktion namens EconomicDetailsMemory alle Nachrichtenereignisse ab, die an einem bestimmten Datum stattfinden, und speichert die Nachrichtendaten dann im Array NewsTime, das per Referenz übergeben wird. 

    //+------------------------------------------------------------------+
    //|Gets values from the MQL5 DB Calendar in Memory                   |
    //+------------------------------------------------------------------+
    void CNews::EconomicDetailsMemory(Calendar &NewsTime[],datetime date)
      {
    //--- SQL query to retrieve news data for a certain date
       string request_text=StringFormat("WITH MySubQuery AS (SELECT EventId as 'Id',Country,EventName as 'Name',EventType as 'Type'"
                                        ",EventImportance as 'Importance',%s as 'CTime',EventCurrency as 'Currency',EventCode as 'Code',"
                                        "EventSector as 'Sector',EventForecast as 'Forecast',EventPrevalue as 'Prevalue',EventImpact as'Impact',"
                                        "EventFrequency as 'Freq',RANK() OVER (PARTITION BY %s Order BY CASE EventPrevalue WHEN 'None' "
                                        "THEN 2 ELSE 1 END,CASE EventForecast WHEN 'None' THEN 2 ELSE 1 END,CASE EventImportance WHEN "
                                        "'CALENDAR_IMPORTANCE_HIGH' THEN 1 WHEN 'CALENDAR_IMPORTANCE_MODERATE' THEN 2 WHEN 'CALENDAR_IMPORTANCE_LOW'"
                                        " THEN 3 ELSE 4 END) Ranking FROM %s) SELECT Id,Country,Name,Type,Importance,CTime,Currency,Code,Sector,"
                                        "Forecast,Prevalue,Impact,Freq FROM MySubQuery where Date(Replace(CTime,'.','-'))=Date(Replace('%s','.','-')) and "
                                        "Ranking<2 Group by CTime;",EnumToString(MySchedule),EnumToString(MySchedule),DBMemory.name,
                                        TimeToString(date));
       int request=DatabasePrepare(DBMemoryConnection,request_text);//Creates a handle of a request, which can then be executed using DatabaseRead()
       if(request==INVALID_HANDLE)//Checks if the request failed to be completed
         {
          Print("DB: ",NEWS_DATABASE_MEMORY, " request failed with code ", GetLastError());
          PrintFormat(request_text);
         }
    //--- Calendar structure variable
       Calendar ReadDB_Data;
    //--- Remove any data in the array
       ArrayRemove(NewsTime,0,WHOLE_ARRAY);
       for(int i=0; DatabaseReadBind(request,ReadDB_Data); i++)//Will read all the results from the sql query/request
         {
          //--- Resize array NewsTime
          ArrayResize(NewsTime,i+1,i+2);
          //--- Assign calendar structure values into NewsTime array index
          NewsTime[i]  = ReadDB_Data;
         }
    //--- Removes a request created in DatabasePrepare()
       DatabaseFinalize(request);
      }

    Lassen Sie uns die SQL-Abfrage aufschlüsseln, denn sie ist komplexer als alle unsere bisherigen Abfragen. In dieser Abfrage verwenden wir also die Klausel WITH und die Funktion RANK().

    Was ist eine WITH-Klausel, und wie funktioniert sie?

    Die WITH-Klausel, auch bekannt als Common Table Expression (CTE), wird verwendet, um temporäre Ergebnismengen zu definieren, auf die Sie innerhalb einer SELECT-, INSERT-, UPDATE- oder DELETE-Anweisung verweisen können. Die WITH-Klausel erleichtert das Verständnis und die Pflege komplexer Abfragen, indem sie diese in einfachere Teile zerlegt. Sie kann auch zur Verbesserung der Leistung beitragen, indem sie die Ergebnisse von teuren Unterabfragen wiederverwendet. CTEs sind temporär und existieren nur für die Dauer der Abfrage. Sie legen keine permanenten Objekte in der Datenbank an.

    Was ist eine RANK()-Funktion, und wie funktioniert sie?

    Die Funktion RANK() wird verwendet, um jeder Zeile innerhalb einer Ergebnismenge auf der Grundlage der Werte in einer oder mehreren Spalten einen eindeutigen Rang zuzuweisen. Die Zeilen werden anhand der angegebenen Kriterien geordnet, und der Rang wird entsprechend zugewiesen. Die Funktion RANK() gehört zu den Fensterfunktionen in SQL, d. h. sie arbeitet mit einem Fenster (oder einer Teilmenge) von Zeilen und kann für jede Zeile der Eingabemenge mehrere Zeilen zurückgeben. Die Funktion RANK() weist jeder Zeile einen Rang zu, der auf der Reihenfolge basiert, die in der ORDER BY-Klausel in der Definition der Fensterfunktion angegeben ist. Wenn mehrere Zeilen die gleichen Werte in den für die Sortierung angegebenen Spalten haben, erhalten sie den gleichen Rang, und der nächste Rang wird um die Anzahl der identischen Ränge übersprungen. PARTITION BY (optional) teilt die Ergebnismenge in Partitionen auf, und die Funktion RANK() wird auf jede Partition unabhängig angewendet.

    In dieser WITH-Klausel, die unten hervorgehoben ist, wählen wir die folgenden Elemente aus: EventId, Country, EventName, EventType, EventImportance, DST_NONE (Sommerzeit, die vom Nutzer/Händler in den Eingaben des Experten festgelegt wurde), EventCurrency, EventCode, EventSector, EventForecast, EventPrevalue, EventImpact, EventFrequency.s inputs), EventCurrency, EventCode, EventSector, EventForecast, EventPrevalue, EventImpact, EventFrequency, dann verwenden wir eine Rangfunktion, deren Zweck es ist, jedem SELECT-Ergebnis eine Rangfolge zu geben. Diese Rangfolge ist immer 1 für eine eindeutige Ereigniszeit (DST_NONE), wenn wir mehrere Ereignisse mit der gleichen Ereigniszeit haben, dann wenden wir die Rangfolge an, also wenn das Ereignis einen EventPrevalue gleich ‚None‘ hat, erhält es den Wert 2, ansonsten den Wert 1 und so weiter für den Rest der Order BY-Klausel.

    WITH MySubQuery AS (SELECT EventId as 'Id',Country,EventName as 'Name',EventType as 'Type',EventImportance as 'Importance',
    DST_NONE as 'CTime',EventCurrency as 'Currency',EventCode as 'Code',EventSector as 'Sector',EventForecast as 'Forecast',
    EventPrevalue as 'Prevalue',EventImpact as'Impact',EventFrequency as 'Freq',RANK() OVER (PARTITION BY DST_NONE 
    Order BY CASE EventPrevalue WHEN 'None' THEN 2 ELSE 1 END,CASE EventForecast WHEN 'None' THEN 2 ELSE 1 END,
    CASE EventImportance WHEN 'CALENDAR_IMPORTANCE_HIGH' THEN 1 WHEN 'CALENDAR_IMPORTANCE_MODERATE' THEN 2 
    WHEN 'CALENDAR_IMPORTANCE_LOW' THEN 3 ELSE 4 END) Ranking FROM MQL5Calendar) SELECT Id,Country,Name,Type,
    Importance,CTime,Currency,Code,Sector,Forecast,Prevalue,Impact,Freq FROM MySubQuery where 
    Date(Replace(CTime,'.','-'))=Date(Replace('2024.07.30 00:00','.','-')) and Ranking<2 Group by CTime;

    Nachfolgend sehen Sie ein Beispiel für die Ereignisse von CTE(MySubQuery). Ich habe die Ereignisse hervorgehoben, die aus den Ergebnissen ausgeschlossen werden, da ihr Rang größer als 1 ist. Wir berücksichtigen nur Ereignisse mit einer Wertigkeit von weniger als 2 und gruppieren das Ergebnis dann nach ihrer Zeit, da wir bei der Darstellung der Ereignisobjekte im Chart nicht mehrere Ereignisobjekte mit der gleichen Zeit erstellen wollen, sondern nur das Ereignis mit der größten Bedeutung anzeigen lassen wollen.

    Id 		Country 	Name 					Type 			Importance 			CTime 		Currency Code Sector 			Forecast  Prevalue   Impact 		Freq 			  Ranking
    392030007 	Japan 		Unemployment Rate 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 01:30 JPY 	 JP   CALENDAR_SECTOR_JOBS 	2500000   2600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    392050002 	Japan 		Jobs to Applicants Ratio 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 01:30 JPY 	 JP   CALENDAR_SECTOR_JOBS 	1240000   1240000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    36010001 	Australia 	Building Approvals m/m 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 03:30 AUD 	 AU   CALENDAR_SECTOR_BUSINESS 	-900000   5500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    36010002 	Australia 	Private House Approvals m/m 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 03:30 AUD 	 AU   CALENDAR_SECTOR_BUSINESS 	None 	  2100000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    250010005 	France 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 07:30 EUR 	 FR   CALENDAR_SECTOR_GDP 	200000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    250010006 	France 		GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 07:30 EUR 	 FR   CALENDAR_SECTOR_GDP 	1000000	  1100000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    250010008 	France 		Consumer Spending m/m 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 07:30 EUR 	 FR   CALENDAR_SECTOR_CONSUMER 	800000 	  1500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    756050001 	Switzerland 	KOF Economic Barometer 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 CHF 	 CH   CALENDAR_SECTOR_BUSINESS 	101500000 102700000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    724010001 	Spain 		CPI m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_PRICES 	200000 	  400000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    724010003 	Spain 		HICP m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_PRICES 	300000 	  400000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    724010005 	Spain 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_GDP 	300000 	  800000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    724010002 	Spain 		CPI y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 EUR  	 ES   CALENDAR_SECTOR_PRICES 	3000000   3400000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    724010004 	Spain 		HICP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_PRICES 	3500000   3600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    724010006 	Spain 		GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_GDP 	1900000   2500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 5
    752020001 	Sweden 		Business Confidence 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_BUSINESS 	95500000  97300000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    752020002 	Sweden 		Manufacturing Confidence 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_BUSINESS 	99000000  99200000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    752020003 	Sweden 		Consumer Confidence 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_CONSUMER 	95300000  93300000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    752020004 	Sweden 		Inflation Expectations 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_CONSUMER 	6300000   6200000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    752020005 	Sweden 		Economic Tendency Indicator 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_BUSINESS 	94800000  96300000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    276010008 	Germany 	GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 10:00 EUR 	 DE   CALENDAR_SECTOR_GDP 	100000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    380010020 	Italy 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 10:00 EUR 	 IT   CALENDAR_SECTOR_GDP 	200000 	  300000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    276010009 	Germany 	GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 10:00 EUR 	 DE   CALENDAR_SECTOR_GDP 	-400000   -900000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    380010021 	Italy 		GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 10:00 EUR 	 IT   CALENDAR_SECTOR_GDP 	400000 	  700000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 4
    999030016 	European Union 	GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_GDP 	200000 	  300000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    999030017 	European Union 	GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_GDP 	400000 	  400000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    999040003 	European Union 	Industrial Confidence Indicator 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_BUSINESS 	-9700000  -10100000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040004 	European Union 	Services Sentiment Indicator 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_BUSINESS 	8300000   6500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040005 	European Union 	Economic Sentiment Indicator 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_BUSINESS 	95300000  95900000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040006 	European Union 	Consumer Confidence Index 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_CONSUMER 	-13000000 -13000000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040007 	European Union 	Consumer Price Expectations 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR  	 EU   CALENDAR_SECTOR_CONSUMER 	14400000  13100000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040008 	European Union 	Industry Selling Price Expectations 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_BUSINESS 	6300000   6100000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    380020007 	Italy 		10-Year BTP Auction 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 11:30 EUR 	 IT   CALENDAR_SECTOR_MARKET 	None 	  4010000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_NONE    1
    380020005 	Italy 		5-Year BTP Auction 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:30 EUR 	 IT   CALENDAR_SECTOR_MARKET 	None 	  3550000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_NONE    2
    826130002 	United Kingdom 	10-Year Treasury Gilt Auction 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:30 GBP 	 GB   CALENDAR_SECTOR_MARKET 	None 	  4371000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_NONE    2
    724080001 	Spain 		Business Confidence 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 12:00 EUR 	 ES   CALENDAR_SECTOR_BUSINESS 	-4100000  -5700000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    76030002 	Brazil 		FGV IGP-M Inflation Index m/m 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 13:00 BRL 	 BR   CALENDAR_SECTOR_PRICES 	1000000   810000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    484020016 	Mexico 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 14:00 MXN 	 MX   CALENDAR_SECTOR_GDP 	0 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    276010020 	Germany 	CPI m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 14:00 EUR 	 DE   CALENDAR_SECTOR_PRICES 	0 	  100000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    276010022 	Germany 	HICP m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 14:00 EUR 	 DE   CALENDAR_SECTOR_PRICES 	-100000   200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    76010012 	Brazil 		PPI m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 14:00 BRL 	 BR   CALENDAR_SECTOR_PRICES 	700000 	  450000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    484020017 	Mexico 		GDP n.s.a. y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 14:00 MXN 	 MX   CALENDAR_SECTOR_GDP 	2000000   1600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    276010021 	Germany 	CPI y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 14:00 EUR 	 DE   CALENDAR_SECTOR_PRICES 	2200000   2200000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   6
    276010023 	Germany 	HICP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 14:00 EUR 	 DE   CALENDAR_SECTOR_PRICES 	2500000   2500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   6
    76010013 	Brazil 		PPI y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 14:00 BRL 	 BR   CALENDAR_SECTOR_PRICES 	2200000   170000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   6
    840170001 	United States 	S&P/CS HPI Composite-20 y/y 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	6800000   7200000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840110001 	United States 	HPI m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	300000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840110002 	United States 	HPI y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	5700000   6300000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840110003 	United States 	HPI 					CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	427700000 424300000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840170002 	United States 	S&P/CS HPI Composite-20 n.s.a. m/m 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	700000 	  1400000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840170003 	United States 	S&P/CS HPI Composite-20 s.a. m/m 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	200000 	  400000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840030021 	United States 	JOLTS Job Openings 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 16:00 USD 	 US   CALENDAR_SECTOR_JOBS 	7979000   8140000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840180002 	United States 	CB Consumer Confidence Index 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 16:00 USD 	 US   CALENDAR_SECTOR_CONSUMER 	108000000 100400000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840060003 	United States 	Dallas Fed Services Revenues 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 16:30 USD 	 US   CALENDAR_SECTOR_BUSINESS 	3900000   1900000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840060004 	United States 	Dallas Fed Services Business Activity 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 16:30 USD 	 US   CALENDAR_SECTOR_BUSINESS 	-6700000  -4100000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    484010001 	Mexico Fiscal 	Balance 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 22:30 MXN 	 MX   CALENDAR_SECTOR_TRADE 	-900000   -174071000 CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    

    Die Endergebnisse sind unten aufgeführt.

    Id 		Country 	Name 					Type 			Importance 			CTime 		Currency Code Sector 			Forecast  Prevalue   Impact 		Freq 			  Ranking
    392030007 	Japan 		Unemployment Rate 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 01:30 JPY 	 JP   CALENDAR_SECTOR_JOBS 	2500000   2600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    36010001 	Australia 	Building Approvals m/m 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 03:30 AUD 	 AU   CALENDAR_SECTOR_BUSINESS 	-900000   5500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    250010005 	France 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 07:30 EUR 	 FR   CALENDAR_SECTOR_GDP 	200000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    756050001 	Switzerland 	KOF Economic Barometer 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 CHF 	 CH   CALENDAR_SECTOR_BUSINESS 	101500000 102700000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    276010008 	Germany 	GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 10:00 EUR 	 DE   CALENDAR_SECTOR_GDP 	100000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    999030016 	European Union 	GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_GDP 	200000 	  300000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    380020007 	Italy 		10-Year BTP Auction 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 11:30 EUR 	 IT   CALENDAR_SECTOR_MARKET 	None 	  4010000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_NONE    1
    724080001 	Spain 		Business Confidence 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 12:00 EUR 	 ES   CALENDAR_SECTOR_BUSINESS 	-4100000  -5700000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    76030002 	Brazil 		FGV IGP-M Inflation Index m/m 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 13:00 BRL 	 BR   CALENDAR_SECTOR_PRICES 	1000000   810000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    484020016 	Mexico 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 14:00 MXN 	 MX   CALENDAR_SECTOR_GDP 	0 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    840170001 	United States 	S&P/CS HPI Composite-20 y/y 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	6800000   7200000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840030021 	United States 	JOLTS Job Openings 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 16:00 USD 	 US   CALENDAR_SECTOR_JOBS 	7979000   8140000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840060003 	United States 	Dallas Fed Services Revenues 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 16:30 USD 	 US   CALENDAR_SECTOR_BUSINESS 	3900000   1900000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    484010001 	Mexico Fiscal 	Balance 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 22:30 MXN 	 MX   CALENDAR_SECTOR_TRADE 	-900000   -174071000 CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1

    Diese Ergebnisse werden in der folgenden Variablen gespeichert:

    Calendar &NewsTime[]

    Die nachfolgende Funktion EconomicNextEvent ähnelt der zuvor genannten Funktion EconomicDetailsMemory. Der Hauptunterschied besteht darin, dass die nachfolgende Funktion dazu dient, das nächste Ereignis abzurufen, anstatt alle Ereignisse für ein bestimmtes Datum abzurufen.

    //+------------------------------------------------------------------+
    //|Will update UpcomingNews structure variable with the next event   |
    //|data                                                              |
    //+------------------------------------------------------------------+
    void CNews::EconomicNextEvent(datetime date=0)
      {
    //--- Declare unassigned Calendar structure variable Empty
       Calendar Empty;
    //--- assign empty values to Calendar structure variable UpcomingNews
       UpcomingNews = Empty;
    //--- If date variable is zero then assign current date
       date = (date==0)?TimeTradeServer():date;
    //--- Query to retrieve next upcoming event.
       string request_text=StringFormat("WITH MySubQuery AS (SELECT EventId as 'Id',Country,EventName as 'Name',"
                                        "EventType as 'Type',EventImportance as 'Importance',%s as 'CTime',EventCurrency as 'Currency',"
                                        "EventCode as 'Code',EventSector as 'Sector',EventForecast as 'Forecast',"
                                        "EventPrevalue as 'Prevalue',EventImpact as 'Impact',EventFrequency as 'Freq',"
                                        "RANK() OVER (PARTITION BY %s ORDER BY CASE EventPrevalue WHEN 'None' THEN 2 ELSE 1 END"
                                        ", CASE EventForecast WHEN 'None' THEN 2 ELSE 1 END,CASE EventImportance "
                                        "WHEN 'CALENDAR_IMPORTANCE_HIGH' THEN 1 WHEN 'CALENDAR_IMPORTANCE_MODERATE' THEN 2 WHEN"
                                        " 'CALENDAR_IMPORTANCE_LOW' THEN 3 ELSE 4 END) Ranking FROM %s) SELECT Id,Country,Name,"
                                        "Type,Importance,CTime,Currency,Code,Sector,Forecast,Prevalue,Impact,Freq FROM MySubQuery "
                                        "where Replace(CTime,'.','-')>=Replace('%s','.','-') AND Ranking<2 Group by CTime LIMIT 1;",
                                        EnumToString(MySchedule),EnumToString(MySchedule),DBMemory.name,TimeToString(date));
    
       int request=DatabasePrepare(DBMemoryConnection,request_text);//Creates a handle of a request, which can then be executed using DatabaseRead()
       if(request==INVALID_HANDLE)//Checks if the request failed to be completed
         {
          Print("DB: ",NEWS_DATABASE_MEMORY, " request failed with code ", GetLastError());
          PrintFormat(request_text);
         }
    //--- Assign query results to Calendar structure variable UpcomingNews
       DatabaseReadBind(request,UpcomingNews);
    //--- Removes a request created in DatabasePrepare()
       DatabaseFinalize(request);
      }

    Die nachstehende Abfrage für die Funktion EconomicNextEvent ähnelt der Abfrage in der Funktion EconomicDetailsMemory, die wir zuvor erläutert haben. Der einzige Unterschied besteht darin, dass die nachstehende Abfrage die Ergebnisse um 1 begrenzt.

    WITH MySubQuery AS (SELECT EventId as 'Id',Country,EventName as 'Name',EventType as 'Type',EventImportance as 'Importance',
    DST_NONE as 'CTime',EventCurrency as 'Currency',EventCode as 'Code',EventSector as 'Sector',EventForecast as 'Forecast',
    EventPrevalue as 'Prevalue',EventImpact as'Impact',EventFrequency as 'Freq',RANK() OVER (PARTITION BY DST_NONE 
    Order BY CASE EventPrevalue WHEN 'None' THEN 2 ELSE 1 END,CASE EventForecast WHEN 'None' THEN 2 ELSE 1 END,
    CASE EventImportance WHEN 'CALENDAR_IMPORTANCE_HIGH' THEN 1 WHEN 'CALENDAR_IMPORTANCE_MODERATE' THEN 2 
    WHEN 'CALENDAR_IMPORTANCE_LOW' THEN 3 ELSE 4 END) Ranking FROM MQL5Calendar) SELECT Id,Country,Name,Type,
    Importance,CTime,Currency,Code,Sector,Forecast,Prevalue,Impact,Freq FROM MySubQuery where 
    Date(Replace(CTime,'.','-'))=Date(Replace('2024.07.30 00:00','.','-')) and Ranking<2 Group by CTime LIMIT 1;

    Nachfolgend werden Beispielergebnisse für die obige Abfrage gezeigt.

    Id 		Country 	Name 					Type 			Importance 			CTime 		Currency Code Sector 			Forecast  Prevalue   Impact 		Freq 			  Ranking
    392030007 	Japan 		Unemployment Rate 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 01:30 JPY 	 JP   CALENDAR_SECTOR_JOBS 	2500000   2600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    

    Das obige Beispielergebnis wird in der Variablen UpcomingNews gespeichert, die wir außerhalb der Nachrichtenklasse deklariert haben.

    //--- Assign query results to Calendar structure variable UpcomingNews
       DatabaseReadBind(request,UpcomingNews);

    Die letzte neu hinzugefügte Funktion in der Nachrichtenklasse aus Teil 2 heißt GetImpact und ist unten dargestellt. Der Zweck dieser Funktion ist die Rückgabe des Enumerationswertes für die Enumeration ENUM_CALENDAR_EVENT_IMPACT für das bevorstehende Ereignis auf der Grundlage früherer Ereignisse mit ähnlichen Eigenschaften oder Werten wie das bevorstehende Ereignis. Lassen Sie mich das näher erklären.

    //+------------------------------------------------------------------+
    //|Will retrieve Upcoming Event Impact data                          |
    //+------------------------------------------------------------------+
    ENUM_CALENDAR_EVENT_IMPACT CNews::GetImpact()
      {
    //--- Declaration of string variable
       string impact=NULL;
    //--- Query to get impact data from previous event with the same event id and matching EventPrevalue and EventForecast scenarios.
       string request_text=StringFormat("SELECT EventImpact FROM %s where Replace(%s,'.','-')<Replace('%s','.','-') AND EventId=%d"
                                        " %s ORDER BY %s DESC LIMIT 1;",DBMemory.name,EnumToString(MySchedule),UpcomingNews.EventDate,
                                        UpcomingNews.EventId,((UpcomingNews.EventPreval=="None"||UpcomingNews.EventForecast=="None")?
                                              "AND EventImpact='CALENDAR_IMPACT_NA'":(int(UpcomingNews.EventPreval)<int(UpcomingNews.EventForecast))?
                                              "AND EventPrevalue<EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'":
                                              (int(UpcomingNews.EventPreval)>int(UpcomingNews.EventForecast))?
                                              "AND EventPrevalue>EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'":
                                              "AND EventPrevalue=EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'"),
                                        EnumToString(MySchedule));
    
       int request=DatabasePrepare(DBMemoryConnection,request_text);//Creates a handle of a request, which can then be executed using DatabaseRead()
    
       if(request==INVALID_HANDLE)//Checks if the request failed to be completed
         {
          Print("DB: ",NEWS_DATABASE_MEMORY, " request failed with code ", GetLastError());
          PrintFormat(request_text);
         }
       if(DatabaseRead(request))//Will read the one record in the 'Record' table
         {
          //--- assign first column result into impact variable
          DatabaseColumnText(request,0,impact);
         }
    //--- Removes a request created in DatabasePrepare()
       DatabaseFinalize(request);
    //--- Return equivalent Event impact in the enumeration ENUM_CALENDAR_EVENT_IMPACT
       if(impact=="CALENDAR_IMPACT_POSITIVE")
         {
          return CALENDAR_IMPACT_POSITIVE;
         }
       else
          if(impact=="CALENDAR_IMPACT_NEGATIVE")
            {
             return CALENDAR_IMPACT_NEGATIVE;
            }
          else
            {
             return CALENDAR_IMPACT_NA;
            }
      }

    Die Ereignisauswirkung funktioniert nach meinen Beobachtungen grundsätzlich so, dass bevorstehende Ereignisse oder Ereignisse, die am aktuellen Tag auftraten, alle den Enumerationswert der Auswirkung CALENDAR_IMPACT_NA haben, was bedeutet, dass die Auswirkung für das Ereignis nicht verfügbar ist. Die Auswirkungen des Ereignisses werden erst aktualisiert, nachdem der Tag des Ereignisses vergangen ist, und auch nur dann, wenn für das Ereignis sowohl der vorherige Wert als auch der prognostizierte Wert vor dem Eintreten des Ereignisses verfügbar waren. Es gibt einige Fälle, in denen die Auswirkungen des Ereignisses immer noch als nicht verfügbar registriert werden, selbst wenn alle diese Anforderungen erfüllt sind. 


    Wozu brauchen wir den Wert für die Auswirkungen früherer Ereignisse, und wie können wir ihn nutzen?

    Erstens benötigen wir die Auswirkungen des vorangegangenen Ereignisses, um vorherzusagen, wie die Auswirkungen des nächsten Ereignisses aussehen könnten. Wenn also der vorherige Wert des bevorstehenden Ereignisses nicht „None“ ist und auch der Prognosewert, dann prüfen wir, ob diese Werte gleich sind oder welcher Wert größer ist als der andere. Sobald wir herausgefunden haben, welcher Wert größer ist als der andere oder ob die Werte gleich sind, suchen wir nach früheren Ereignissen, die dieselbe Konfiguration aufwiesen, und rufen die Ereignisauswirkungen für dieses frühere Ereignis ab, um vorherzusagen, wie die Auswirkungen des kommenden Ereignisses sein könnten. Wenn z. B. der vorherige Wert des bevorstehenden Ereignisses 3000 und die Prognose 10.000 beträgt, suchen wir nach dem letzten Ereignis mit der gleichen Ereignis-ID, das einen vorherigen Wert hatte, der unter dem Prognosewert lag, und verwenden die Auswirkungen dieses Ereignisses für das bevorstehende Ereignis.

    <>Was ist die Auswirkung des Ereignisses, und worauf basiert die Auswirkung?

    Die Auswirkung eines Ereignisses ist die Messung der wahrgenommenen Auswirkung, die ein bestimmtes Ereignis auf eine Währung hatte, die Auswirkung basiert auf der Währung des Ereignisses. Wenn also die Arbeitslosenquote das bevorstehende Ereignis ist und das vorherige Ereignis mit der ähnlichen Konfiguration von vorherigem Wert und prognostiziertem Wert eine Ereignisauswirkung von CALENDAR_IMPACT_NEGATIVE hat und die Ereigniswährung USD ist, bedeutet dies im Wesentlichen, dass der US-Dollar bei der vorherigen Arbeitslosenquote negativ beeinflusst wurde. Wenn Sie also direkt nach dem Auftreten der vorherigen Arbeitslosenquote auf dem Symbol EURUSD waren, würden wir idealerweise sehen, dass der EURUSD steigt, was bedeutet, dass der EUR gegenüber dem US-Dollar an Wert gewonnen hat. 

    In der nachstehenden Abfrage werden die Auswirkungen des Ereignisses aus der Tabelle MQL5Calendar in der Datenbank im Speicher AUSGEWÄHLT. In der WHERE-Klausel suchen wir nach Ereignisdaten vor dem bevorstehenden Ereignisdatum und filtern nach der gleichen Ereignis-ID. Wir filtern dann nach demselben Beziehungsszenario zwischen dem vorherigen Ereigniswert (EventPreval) und dem Ereignisprognosewert (EventForecast). Wenn UpcomingNews.EventPreval gleich „None“ oder UpcomingNews.EventForecast gleich „None“ ist, wissen wir bereits, dass die Ereignisauswirkung „None“ sein wird. Wenn UpcomingNews.EventPreval kleiner als UpcomingNews.EventForecast ist, suchen wir nach vorherigen Ereignissen, bei denen EventPrevalue<EventForecast und die Ereignisauswirkung nicht NA ist, wenn UpcomingNews.EventPreval größer als UpcomingNews.EventForecast ist, suchen wir nach vorherigen Ereignissen, bei denen EventPreval>EventForecast und die Ereignisauswirkung nicht NA ist, andernfalls suchen wir nach Ereignissen, bei denen EventPrevalue=EventForecast und die Ereignisauswirkung nicht NA ist. Alle Ergebnisse werden nach dem aktuellsten Datum gefiltert, da die ORDER BY-Klausel in absteigender Reihenfolge für das Ereignisdatum ist und die LIMIT-Klausel nur die Rückgabe/Ausgabe eines Datensatzes zulässt.

    //--- Query to get impact data from previous event with the same event id and matching EventPrevalue and EventForecast scenarios.
       string request_text=StringFormat("SELECT EventImpact FROM %s where Replace(%s,'.','-')<Replace('%s','.','-') AND EventId=%d"
                                        " %s ORDER BY %s DESC LIMIT 1;",DBMemory.name,EnumToString(MySchedule),UpcomingNews.EventDate,
                                        UpcomingNews.EventId,((UpcomingNews.EventPreval=="None"||UpcomingNews.EventForecast=="None")?
                                              "AND EventImpact='CALENDAR_IMPACT_NA'":(int(UpcomingNews.EventPreval)<int(UpcomingNews.EventForecast))?
                                              "AND EventPrevalue<EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'":
                                              (int(UpcomingNews.EventPreval)>int(UpcomingNews.EventForecast))?
                                              "AND EventPrevalue>EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'":
                                              "AND EventPrevalue=EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'"),
                                        EnumToString(MySchedule));

    Ein Beispiel dafür, wie die obige Abfrage aussieht, wenn alle Variablen mit Daten gefüllt sind. Wie Sie also unten sehen können, wählen wir den EventImpact FROM MQL5Calendar WHERE DST_NONE ist kleiner als ‚2024.08.01 16:30‘ und die EventId ist gleich 124500001 und EventPrevalue ist kleiner als EventForecast und EventImpact ist nicht gleich ‚CALENDAR_IMPACT_NA‘, dann setzen wir die Ergebnisse in absteigender Reihenfolge in Bezug auf DST_NONE und begrenzen die Ergebnisse schließlich auf ein Ergebnis.

    SELECT EventImpact FROM MQL5Calendar where Replace(DST_NONE,'.','-')<Replace('2024.08.01 16:30','.','-') AND EventId=124500001 
    AND EventPrevalue<EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA' ORDER BY DST_NONE DESC LIMIT 1;


    Die Klasse der allgemeinen Grafik

    Diese Klasse ist für die Darstellung der visuellen Elemente des Experten auf dem Chart verantwortlich. Sie haben also bereits bemerkt, dass die visuellen Elemente für Teil 3 einen größeren Schritt nach vorne machen als in Teil 2, und so wird auch der Code sein, der diese visuellen Elemente erzeugt. Werfen wir einen Blick auf den Code. Diese Klasse benötigt also Zugang zu den Informationen über Nachrichten, Risikomanagement und Konten, sodass diese Klassen einbezogen werden.

    #include "ObjectProperties.mqh"
    #include "RiskManagement.mqh"
    #include "CommonVariables.mqh"
    #include "News.mqh"
    //+------------------------------------------------------------------+
    //|CommonGraphics class                                              |
    //+------------------------------------------------------------------+
    class CCommonGraphics:CObjectProperties
      {
    private:
       //--- GraphicText structure this structure is responsible for managing the graphical text
       struct GraphicText
         {
          //--- private declaration for struct GraphicText
       private:
          //--- this structure will store properties for the subtext
          struct subtextformat
            {
             string      Label;//Store text label
             string      Text;//Store text value
            };
          //--- this structure inherits from subtextformat and is responsible for finding text
          struct found:subtextformat
            {
             bool        isFound;//Check if text is found
             int         index;//Get index for the text
            };
          //--- structure array for subtexts
          subtextformat  sub_text[];
          //--- function to find text properties from text's label
          found          FoundText(string label)
            {
             found find;
             find.Label="";
             find.Text="";
             find.isFound=false;
             find.index=-1;
             for(uint i=0;i<sub_text.Size();i++)
               {
                //--- If text label is found in array
                if(label==sub_text[i].Label)
                  {
                   //--- Assign text properties
                   find.Label=sub_text[i].Label;
                   find.Text=sub_text[i].Text;
                   find.isFound=true;
                   find.index=int(i);
                   return find;//return found text properties
                  }
               }
             return find;//return text properties
            }
          //--- public declaration for struct GraphicText
       public:
          //--- string variable
          string         text;
          //--- function to set/add text properties
          void           subtext(string label,string value)
            {
             //--- Get text properties from label
             found result = FoundText(label);
             //--- Check if text label was found/exists in array sub_text
             if(!result.isFound)
               {
                //--- Resize array sub_text
                ArrayResize(sub_text,sub_text.Size()+1,sub_text.Size()+2);
                //--- Add text properties for new array index
                sub_text[sub_text.Size()-1].Label = label;
                sub_text[sub_text.Size()-1].Text = value;
               }
             else
               {
                /* Set new text/override text from text label that exists
                in the array sub_text array */
                sub_text[result.index].Text = value;
               }
            }
          //--- function to retrieve text from text label
          string         subtext(string label)
            {
             return FoundText(label).Text;
            }
         };// End of struct GraphicText
    
       //--- AccountInfo object declaration
       CAccountInfo      CAccount;
       //--- News object declaration
       CNews             NewsObj;
       //--- TimeManagement object declaration
       CTimeManagement   CTime;
       //--- Calendar structure array declaration
       Calendar          CalendarArray[];
       //--- color variable declaration
       color             EventColor;
       //--- unit variable declarations
       uint              Fontsize,X_start,Y_start;
       //--- void function declarations for Graphical blocks
       void              Block_1();
       void              Block_2(uint SecondsPreEvent=5);
       CRiskManagement   CRisk;//Risk management class object
       //--- GraphicText structure array declarations
       GraphicText       Texts_Block1[9],Texts_Block2[7];
       //--- structure to store text height and width
       struct Text_Prop_Size
         {
          uint           Height;//store text height
          uint           Width;//store text width
         };
    
       //--- void function to retrieve sum of the texts height and the maximum width of texts from GraphicText array Texts
       void              GetTextMaxWidthAndHeight(GraphicText &Texts[],uint &Max_Height,uint &Max_Width,uint FontSize)
         {
          //--- set fontsize properties to get accurate text height and width sizes
          TextSetFont("Arial",(-1*FontSize)-100);
          //--- set variables to default value of zero
          Max_Height=0;
          Max_Width=0;
          //--- loop through all texts in the GraphicText array Texts
          for(uint i=0;i<Texts.Size();i++)
            {
             //--- temporary declarations for height and width
             uint Height=0,Width=0;
             //--- retrieve text height and width from index in Texts array
             TextGetSize(Texts[i].text,Width,Height);
             //--- sum texts height to variable Max_Height
             Max_Height+=Height;
             //--- assign width if text width is more than variable Max_Width value
             Max_Width=(Width>Max_Width)?Width:Max_Width;
            }
         }
       //--- function to retrieve text height and width properties in the structure Text_Prop_Size format
       Text_Prop_Size    GetText(string Text,uint FontSize)
         {
          //--- structure Text_Prop_Size variable
          Text_Prop_Size Size;
          //--- set fontsize properties to get accurate text height and width sizes
          TextSetFont("Arial",(-1*FontSize)-100);
          //--- retrieve text height and width from Text string variable
          TextGetSize(Text,Size.Width,Size.Height);
          //--- return structure Text_Prop_Size variable
          return Size;
         }
       //--- Function to get texts height sum and max width in the structure Text_Prop_Size format
       Text_Prop_Size    GetTextMax(GraphicText &Texts[],uint FontSize)
         {
          //--- structure Text_Prop_Size variable
          Text_Prop_Size Size;
          //--- uint variable declarations for text properties
          uint Max_Height;
          uint Max_Width;
          //--- Retrieve sum of texts height and maximum texts width into Max_Height,Max_Width
          GetTextMaxWidthAndHeight(Texts,Max_Height,Max_Width,FontSize);
          //--- assign values into structure Text_Prop_Size variable
          Size.Height = Max_Height;
          Size.Width = Max_Width;
          //--- return structure Text_Prop_Size variable
          return Size;
         }
       //--- Boolean declarations
       bool              is_date,is_spread,is_news,is_events;
    
    public:
       //--- class constructor
                         CCommonGraphics(bool display_date,bool display_spread,bool display_news,bool display_events);
                        ~CCommonGraphics(void) {}//class destructor
       void              GraphicsRefresh(uint SecondsPreEvent=5);//will create/refresh the chart objects
       //--- will update certain graphics at an interval
       void              Block_2_Realtime(uint SecondsPreEvent=5);
       //--- will create chart event objects
       void              NewsEvent();
      };

    Die untenstehende Struktur namens GraphicText ist keine gewöhnliche Struktur in MQL5. Diese Struktur enthält private und/oder öffentliche Deklarationen von Strukturen, Struktur-Arrays, Funktionen und eine String-Variable. In diesem Fall verhält sich die Struktur GraphicText wie eine ganz eigene Klasse. Diese Struktur dient dazu, grafische Texte zu verwalten und zu speichern. Das Array der Struktur sub_text speichert alle Texteigenschaften, und die Funktion FoundText sucht nach einer Übereinstimmung der Textbeschriftung im Array sub_text; wenn es eine Übereinstimmung gibt, werden die Details dieser Übereinstimmung in der Struktur found zurückgegeben, die von der Struktur subtextformat erbt. In den öffentlichen Deklarationen speichert die String-Variable namens text die volle Länge des Textes im Array der Struktur sub_text. Die void-Funktion subtext fügt das Textlabel und den Text/Untertext in das Array sub_text ein oder überschreibt den im Array gespeicherten Text/Untertext, wenn die String-Variable label im Array gefunden wird. Die String-Funktion namens subtext ruft den Text für das Label ab, das mit den Labels im Array der Struktur sub_text verknüpft ist.

       //--- GraphicText structure this structure is responsible for managing the graphical text
       struct GraphicText
         {
          //--- private declaration for struct GraphicText
       private:
          //--- this structure will store properties for the subtext
          struct subtextformat
            {
             string      Label;//Store text label
             string      Text;//Store text value
            };
          //--- this structure inherits from subtextformat and is responsible for finding text
          struct found:subtextformat
            {
             bool        isFound;//Check if text is found
             int         index;//Get index for the text
            };
          //--- structure array for subtexts
          subtextformat  sub_text[];
          //--- function to find text properties from text's label
          found          FoundText(string label)
            {
             found find;
             find.Label="";
             find.Text="";
             find.isFound=false;
             find.index=-1;
             for(uint i=0;i<sub_text.Size();i++)
               {
                //--- If text label is found in array
                if(label==sub_text[i].Label)
                  {
                   //--- Assign text properties
                   find.Label=sub_text[i].Label;
                   find.Text=sub_text[i].Text;
                   find.isFound=true;
                   find.index=int(i);
                   return find;//return found text properties
                  }
               }
             return find;//return text properties
            }
          //--- public declaration for struct GraphicText
       public:
          //--- string variable
          string         text;
          //--- function to set/add text properties
          void           subtext(string label,string value)
            {
             //--- Get text properties from label
             found result = FoundText(label);
             //--- Check if text label was found/exists in array sub_text
             if(!result.isFound)
               {
                //--- Resize array sub_text
                ArrayResize(sub_text,sub_text.Size()+1,sub_text.Size()+2);
                //--- Add text properties for new array index
                sub_text[sub_text.Size()-1].Label = label;
                sub_text[sub_text.Size()-1].Text = value;
               }
             else
               {
                /* Set new text/override text from text label that exists
                in the array sub_text array */
                sub_text[result.index].Text = value;
               }
            }
          //--- function to retrieve text from text label
          string         subtext(string label)
            {
             return FoundText(label).Text;
            }
         };// End of struct GraphicText

    Die nachstehende Funktion wird erstellt, um die Summe der Texthöhen im Strukturarray Texts sowie die maximale Breite der Texte im Array zu ermitteln.

     //--- void function to retrieve sum of the texts height and the maximum width of texts from GraphicText array Texts
       void              GetTextMaxWidthAndHeight(GraphicText &Texts[],uint &Max_Height,uint &Max_Width,uint FontSize)
         {
          //--- set fontsize properties to get accurate text height and width sizes
          TextSetFont("Arial",(-1*FontSize)-100);
          //--- set variables to default value of zero
          Max_Height=0;
          Max_Width=0;
          //--- loop through all texts in the GraphicText array Texts
          for(uint i=0;i<Texts.Size();i++)
            {
             //--- temporary declarations for height and width
             uint Height=0,Width=0;
             //--- retrieve text height and width from index in Texts array
             TextGetSize(Texts[i].text,Width,Height);
             //--- sum texts height to variable Max_Height
             Max_Height+=Height;
             //--- assign width if text width is more than variable Max_Width value
             Max_Width=(Width>Max_Width)?Width:Max_Width;
            }
         }

    Die folgende Funktion wird erstellt, um die Eigenschaften Höhe und Breite im Format der Struktur Text_Prop_Size aus der String-Variablen Text abzurufen.

    //--- function to retrieve text height and width properties in the structure Text_Prop_Size format
       Text_Prop_Size    GetText(string Text,uint FontSize)
         {
          //--- structure Text_Prop_Size variable
          Text_Prop_Size Size;
          //--- set fontsize properties to get accurate text height and width sizes
          TextSetFont("Arial",(-1*FontSize)-100);
          //--- retrieve text height and width from Text string variable
          TextGetSize(Text,Size.Width,Size.Height);
          //--- return structure Text_Prop_Size variable
          return Size;
         }

    Die folgende Funktion wird erstellt, um die Summe der Höhen und die maximale Breite der Eigenschaften in der Struktur Text_Prop_Size Format aus der Struktur Array Texts abzurufen.

    //--- Function to get texts height sum and max width in the structure Text_Prop_Size format
       Text_Prop_Size    GetTextMax(GraphicText &Texts[],uint FontSize)
         {
          //--- structure Text_Prop_Size variable
          Text_Prop_Size Size;
          //--- uint variable declarations for text properties
          uint Max_Height;
          uint Max_Width;
          //--- Retrieve sum of texts height and maximum texts width into Max_Height,Max_Width
          GetTextMaxWidthAndHeight(Texts,Max_Height,Max_Width,FontSize);
          //--- assign values into structure Text_Prop_Size variable
          Size.Height = Max_Height;
          Size.Width = Max_Width;
          //--- return structure Text_Prop_Size variable
          return Size;
         }

    Im Konstruktor der Klasse initialisieren wir unsere zuvor deklarierten Variablen is_date (mit deren Hilfe wir entscheiden, ob die Datumsinformationen im Chart angezeigt werden sollen), is_spread (mit deren Hilfe wir entscheiden, ob die Spread-Informationen im Chart angezeigt werden sollen), is_news (mit deren Hilfe wir entscheiden, ob die Nachrichteninformationen im Chart angezeigt werden sollen) und is_events (mit deren Hilfe wir entscheiden, ob die Ereignisobjektinformationen im Chart angezeigt werden sollen). NewsObject. Die Funktion EconomicNextEvent aktualisiert die Variable UpcomingNews mit den Details der nächsten Nachricht.

    //+------------------------------------------------------------------+
    //|Constructor                                                       |
    //+------------------------------------------------------------------+
    CCommonGraphics::CCommonGraphics(bool display_date,bool display_spread,bool display_news,bool display_events):
    //--- Assign variables
       is_date(display_date),is_spread(display_spread),is_news(display_news),is_events(display_events)
      {
    //--- get next news event
       NewsObject.EconomicNextEvent();
      }

    GraphicsRefresh ist dafür verantwortlich, zunächst das Chart von zuvor erstellten Objekten zu säubern, falls vorhanden, und dann andere Funktionen aufzurufen, die Chartobjekte erstellen, um verschiedene Informationen im aktuellen Chart anzuzeigen.

    //+------------------------------------------------------------------+
    //|will create/refresh the chart objects                             |
    //+------------------------------------------------------------------+
    void CCommonGraphics::GraphicsRefresh(uint SecondsPreEvent=5)
      {
    //--- create graphics if outside the strategy tester or in the strategy tester and visual mode is enabled
       if((!MQLInfoInteger(MQL_TESTER))||(MQLInfoInteger(MQL_TESTER)&&MQLInfoInteger(MQL_VISUAL_MODE)))
         {
          //--- Delete chart objects
          DeleteObj();//function from Object properties class
          Block_1();//Create graphics for block 1
          //--- Check whether to create graphics for block 2
          if(is_date||is_news||is_spread)
            {
             Block_2(SecondsPreEvent);//Create graphics for block 2
            }
          //--- creates event objects
          NewsEvent();
         }
      }

    Die nachstehende Funktion mit der Bezeichnung Block_1 ist für die Erstellung der grafischen Elemente für den grafischen Block 1 zuständig, der unten angegeben ist und aus folgenden Elementen besteht

    • Symbol Name
    • Symbol Zeitraum
    • Symbol Beschreibung
    • Symbol Kontraktgröße
    • Symbol Minimales Volumen (lot)
    • Symbol Maximales Volumen (lot)
    • Symbol Schrittweite Volumen
    • Symbol Volumen-Limit
    • Risk Option
    • Risk Floor
    • Risk Ceiling

    Grafischer Block 1

    //+------------------------------------------------------------------+
    //|Graphical Block 1                                                 |
    //+------------------------------------------------------------------+
    void CCommonGraphics::Block_1()
      {
    //--- Set text object color depending if the chart color mode is LightMode or not
       TextObj_color = (isLightMode)?clrBlack:clrWheat;
    //--- Set text properties for Symbol name,Symbol period and Symbol description # section 1
       Texts_Block1[0].text = Symbol()+", "+GetChartPeriodName()+": "+CSymbol.Description();//set main text
       Texts_Block1[0].subtext("Symbol Name",Symbol()+",");//set subtext - label,value
       Texts_Block1[0].subtext("Symbol Period",GetChartPeriodName());//set subtext - label,value
       Texts_Block1[0].subtext("Symbol Desc",": "+CSymbol.Description());//set subtext - label,value
    //--- Set text properties for Contract size # section 2
       Texts_Block1[1].text = "Contract Size: "+string(CSymbol.ContractSize());//set main text
       Texts_Block1[1].subtext("Contract Size Text","Contract Size:");//set subtext - label,value
       Texts_Block1[1].subtext("Contract Size",string(CSymbol.ContractSize()));//set subtext - label,value
    //--- Set text properties for Minimum lot # section 3
       Texts_Block1[2].text = "Minimum Lot: "+string(CSymbol.LotsMin());//set main text
       Texts_Block1[2].subtext("Minimum Lot Text","Minimum Lot:");//set subtext - label,value
       Texts_Block1[2].subtext("Minimum Lot",string(CSymbol.LotsMin()));//set subtext - label,value
    //--- Set text properties for Max lot # section 4
       Texts_Block1[3].text = "Max Lot: "+string(CSymbol.LotsMax());//set main text
       Texts_Block1[3].subtext("Max Lot Text","Max Lot:");//set subtext - label,value
       Texts_Block1[3].subtext("Max Lot",string(CSymbol.LotsMax()));//set subtext - label,value
    //--- Set text properties for Volume step # section 5
       Texts_Block1[4].text = "Volume Step: "+string(CSymbol.LotsStep());//set main text
       Texts_Block1[4].subtext("Volume Step Text","Volume Step:");//set subtext - label,value
       Texts_Block1[4].subtext("Volume Step",string(CSymbol.LotsStep()));//set subtext - label,value
    //--- Set text properties for Volume limit # section 6
       Texts_Block1[5].text = "Volume Limit: "+string(CSymbol.LotsLimit());//set main text
       Texts_Block1[5].subtext("Volume Limit Text","Volume Limit:");//set subtext - label,value
       Texts_Block1[5].subtext("Volume Limit",string(CSymbol.LotsLimit()));//set subtext - label,value
    //--- Set text properties for Risk option # section 7
       Texts_Block1[6].text = "Risk Option: "+CRisk.GetRiskOption();//set main text
       Texts_Block1[6].subtext("Risk Option Text","Risk Option:");//set subtext - label,value
       Texts_Block1[6].subtext("Risk Option",CRisk.GetRiskOption());//set subtext - label,value
    //--- Set text properties for Risk floor # section 8
       Texts_Block1[7].text = "Risk Floor: "+CRisk.GetRiskFloor();//set main text
       Texts_Block1[7].subtext("Risk Floor Text","Risk Floor:");//set subtext - label,value
       Texts_Block1[7].subtext("Risk Floor",CRisk.GetRiskFloor());//set subtext - label,value
    //--- Set text properties for Risk ceiling # section 9
       Texts_Block1[8].text = "Risk Ceiling: "+CRisk.GetRiskCeil();//set main text
       Texts_Block1[8].subtext("Risk Ceiling Text","Risk Ceiling:");//set subtext - label,value
       Texts_Block1[8].subtext("Risk Ceiling",CRisk.GetRiskCeil());//set subtext - label,value
    
    //--- Set basic properties
       Fontsize=10;//Set Fontsize
       X_start=2;//Set X distance
       Y_start=2;//Set Y distance
    
    /* Create objects # section 1*/
    //-- Create the background object for width and height+3 of section 1 text
       Square(0,"Symbol Name background",X_start,Y_start,GetText(Texts_Block1[0].text,Fontsize).Width,
              GetText(Texts_Block1[0].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 1
       TextObj(0,"Symbol Name",Texts_Block1[0].subtext("Symbol Name"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[0].subtext("Symbol Name"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Period",Texts_Block1[0].subtext("Symbol Period"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[0].subtext("Symbol Period"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Desc",Texts_Block1[0].subtext("Symbol Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 2*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[0].text,Fontsize).Height;//Re-adjust Y distance, add height from section 1
       //-- Create the background object for width and height+3 of section 2 text
       Square(0,"Symbol Contract Size background",X_start,Y_start,GetText(Texts_Block1[1].text,Fontsize).Width,
              GetText(Texts_Block1[1].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 2
       TextObj(0,"Symbol Contract Size Text",Texts_Block1[1].subtext("Contract Size Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[1].subtext("Contract Size Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Contract Size",Texts_Block1[1].subtext("Contract Size"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 3*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[1].text,Fontsize).Height;//Re-adjust Y distance, add height from section 2
       //-- Create the background object for width and height+3 of section 3 text
       Square(0,"Symbol MinLot background",X_start,Y_start,GetText(Texts_Block1[2].text,Fontsize).Width,
              GetText(Texts_Block1[2].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 3
       TextObj(0,"Symbol MinLot Text",Texts_Block1[2].subtext("Minimum Lot Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[2].subtext("Minimum Lot Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol MinLot",Texts_Block1[2].subtext("Minimum Lot"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 4*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[2].text,Fontsize).Height;//Re-adjust Y distance, add height from section 3
       //-- Create the background object for width and height+3 of section 4 text
       Square(0,"Symbol MaxLot background",X_start,Y_start,GetText(Texts_Block1[3].text,Fontsize).Width,
              GetText(Texts_Block1[3].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 4
       TextObj(0,"Symbol MaxLot Text",Texts_Block1[3].subtext("Max Lot Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[3].subtext("Max Lot Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol MaxLot",Texts_Block1[3].subtext("Max Lot"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 5*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[3].text,Fontsize).Height;//Re-adjust Y distance, add height from section 4
       //-- Create the background object for width and height+3 of section 5 text
       Square(0,"Symbol Volume Step background",X_start,Y_start,GetText(Texts_Block1[4].text,Fontsize).Width,
              GetText(Texts_Block1[4].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 5
       TextObj(0,"Symbol Volume Step Text",Texts_Block1[4].subtext("Volume Step Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[4].subtext("Volume Step Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Volume Step",Texts_Block1[4].subtext("Volume Step"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 6*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[4].text,Fontsize).Height;//Re-adjust Y distance, add height from section 5
       //-- Create the background object for width and height+3 of section 6 text
       Square(0,"Symbol Volume Limit background",X_start,Y_start,GetText(Texts_Block1[5].text,Fontsize).Width,
              GetText(Texts_Block1[5].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 6
       TextObj(0,"Symbol Volume Limit Text",Texts_Block1[5].subtext("Volume Limit Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[5].subtext("Volume Limit Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Volume Limit",Texts_Block1[5].subtext("Volume Limit"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 7*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[5].text,Fontsize).Height;//Re-adjust Y distance, add height from section 6
       //-- Create the background object for width and height+3 of section 7 text
       Square(0,"Risk Option background",X_start,Y_start,GetText(Texts_Block1[6].text,Fontsize).Width,
              GetText(Texts_Block1[6].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 7
       TextObj(0,"Risk Option Text",Texts_Block1[6].subtext("Risk Option Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[6].subtext("Risk Option Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Risk Option",Texts_Block1[6].subtext("Risk Option"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 8*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[6].text,Fontsize).Height;//Re-adjust Y distance, add height from section 7
       //-- Create the background object for width and height+3 of section 8 text
       Square(0,"Risk Floor background",X_start,Y_start,GetText(Texts_Block1[7].text,Fontsize).Width,
              GetText(Texts_Block1[7].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 8
       TextObj(0,"Risk Floor Text",Texts_Block1[7].subtext("Risk Floor Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[7].subtext("Risk Floor Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Risk Floor",Texts_Block1[7].subtext("Risk Floor"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 9*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[7].text,Fontsize).Height;//Re-adjust Y distance, add height from section 8
       //-- Create the background object for width and height+3 of section 9 text
       Square(0,"Risk Ceil background",X_start,Y_start,GetText(Texts_Block1[8].text,Fontsize).Width,
              GetText(Texts_Block1[8].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 9
       TextObj(0,"Risk Ceil Text",Texts_Block1[8].subtext("Risk Ceiling Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[8].subtext("Risk Ceiling Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Risk Ceil",Texts_Block1[8].subtext("Risk Ceiling"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
      }

    Die nachstehende Funktion mit der Bezeichnung Block_2 ist für die Erstellung der grafischen Elemente für den grafischen Block 2 zuständig, der unten angegeben ist und aus folgenden Elementen besteht:

    • Aktuelles Datum und Uhrzeit
    • Ereignis-Datum (event)
    • Ereignis-Name
    • Ereignis-Land
    • Ereignis-Währung
    • Ereignis-Bedeutung
    • Spread Einstufung

    Grafischer Block 2

    //+------------------------------------------------------------------+
    //|Graphical Block 2                                                 |
    //+------------------------------------------------------------------+
    void CCommonGraphics::Block_2(uint SecondsPreEvent=5)
      {
    //--- Set text object color depending if the chart color mode is LightMode or not
       TextObj_color=(isLightMode)?clrBlack:clrWheat;
       if(is_date)//Check whether to display date information
         {
          //--- Set text properties for Date and Time # section 10
          Texts_Block2[0].text = "Date:"+TimeToString(TimeTradeServer(),TIME_DATE)+"|| Time:"+TimeToString(TimeTradeServer(),TIME_MINUTES)
                                 +"   ";//set main text
          Texts_Block2[0].subtext("Date Text","Date:");//set subtext - label,value
          Texts_Block2[0].subtext("Date",TimeToString(TimeTradeServer(),TIME_DATE));//set subtext - label,value
          Texts_Block2[0].subtext("Time Text","|| Time:");//set subtext - label,value
          Texts_Block2[0].subtext("Time",TimeToString(TimeTradeServer(),TIME_MINUTES));//set subtext - label,value
         }
       if(is_news)//Check whether to display news information
         {
          //--- Set text object color depending on upcoming news event's Importance
          EventColor = NewsObj.GetImportance_color(NewsObj.IMPORTANCE(UpcomingNews.EventImportance));
          //--- Set text properties for Event Date # section 11
          Texts_Block2[1].text = "Event: @"+UpcomingNews.EventDate+" ";//set main text
          Texts_Block2[1].subtext("Event Date Text","Event: @");//set subtext - label,value
          Texts_Block2[1].subtext("Event Date",UpcomingNews.EventDate);//set subtext - label,value
          //--- Set text properties for Event Name # section 12
          Texts_Block2[2].text = "Name: "+UpcomingNews.EventName+" ";//set main text
          Texts_Block2[2].subtext("Event Name Text","Name: ");//set subtext - label,value
          Texts_Block2[2].subtext("Event Name",UpcomingNews.EventName);//set subtext - label,value
          //--- Set text properties for Event Country # section 13
          Texts_Block2[3].text = "Country: "+UpcomingNews.CountryName+" ";//set main text
          Texts_Block2[3].subtext("Event Country Text","Country: ");//set subtext - label,value
          Texts_Block2[3].subtext("Event Country",UpcomingNews.CountryName);//set subtext - label,value
          //--- Set text properties for Event Currency # section 14
          Texts_Block2[4].text = "Currency: "+UpcomingNews.EventCurrency+" ";//set main text
          Texts_Block2[4].subtext("Event Currency Text","Currency: ");//set subtext - label,value
          Texts_Block2[4].subtext("Event Currency",UpcomingNews.EventCurrency);//set subtext - label,value
          //--- Set text properties for Event Importance # section 15
          Texts_Block2[5].text = "Importance: "+NewsObj.GetImportance(NewsObj.IMPORTANCE(UpcomingNews.EventImportance))+" ";//set main text
          Texts_Block2[5].subtext("Importance Text","Importance: ");//set subtext - label,value
          Texts_Block2[5].subtext("Importance",NewsObj.GetImportance(NewsObj.IMPORTANCE(UpcomingNews.EventImportance)));//set subtext - label,value
         }
       if(is_spread)//Check whether to display spread information
         {
          //--- Set text properties for Spread # section 16
          Texts_Block2[6].text = "Spread: "+string(CSymbol.Spread())+" Rating: "+CSymbol.SpreadDesc()+" ";//set main text
          Texts_Block2[6].subtext("Spread Text","Spread:");//set subtext - label,value
          Texts_Block2[6].subtext("Spread",string(CSymbol.Spread()));//set subtext - label,value
          Texts_Block2[6].subtext("Rating Text"," Rating:");//set subtext - label,value
          Texts_Block2[6].subtext("Rating Desc",CSymbol.SpreadDesc());//set subtext - label,value
         }
    
    //--- Set basic properties
       Fontsize=10;
       X_start=2;//Reset X distance
       Y_start=GetTextMax(Texts_Block1,Fontsize).Height+29;//Re-adjust Y distance from graphical block 1 Height
    
       /* Create objects # section 10*/
       if(is_date)//Check whether to display date information
         {
          //-- Create the background object for width and height+3 of section 10 text
          Square(0,"Datetime background",X_start,Y_start,GetText(Texts_Block2[0].text,Fontsize).Width,
                 GetText(Texts_Block2[0].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //-- Will create the text objects for section 10
          TextObj(0,"Date Text",Texts_Block2[0].subtext("Date Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Date Text"),Fontsize).Width;//Re-adjust X distance
          TextObj(0,"Date",Texts_Block2[0].subtext("Date"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Date"),Fontsize).Width;//Re-adjust X distance
          TextObj(0,"Time Text",Texts_Block2[0].subtext("Time Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Time Text"),Fontsize).Width;//Re-adjust X distance
          //--- Adjust text color depending if chart color mode is LightMode and if a news event is occurring
          TextObj_color = CTime.TimeIsInRange(CTime.TimeMinusOffset(datetime(UpcomingNews.EventDate),SecondsPreEvent),
                                              CTime.TimePlusOffset(datetime(UpcomingNews.EventDate),59))?clrRed:(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Time",Texts_Block2[0].subtext("Time"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
         }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       if(UpcomingNews.CountryName!=NULL&&is_news)//Check whether to display news information and if upcoming news is available
         {
          /* Create objects # section 11*/
          Y_start+=(is_date)?GetText(Texts_Block2[0].text,Fontsize).Height:0;//Re-adjust Y distance depending if section 10 is shown
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 11 text
          Square(0,"Event Date background",X_start,Y_start,GetText(Texts_Block2[1].text,Fontsize).Width,
                 GetText(Texts_Block2[1].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 11
          TextObj(0,"Event Date Text",Texts_Block2[1].subtext("Event Date Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[1].subtext("Event Date Text"),Fontsize).Width;//Re-adjust X distance
          //--- Adjust text color depending if chart color mode is LightMode and if a news event is occurring
          TextObj_color = CTime.TimeIsInRange(CTime.TimeMinusOffset(datetime(UpcomingNews.EventDate),SecondsPreEvent),
                                              CTime.TimePlusOffset(datetime(UpcomingNews.EventDate),59))?clrRed:(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Event Date",Texts_Block2[1].subtext("Event Date"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 12*/
          Y_start+=GetText(Texts_Block2[1].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 12 text
          Square(0,"Event Name background",X_start,Y_start,GetText(Texts_Block2[2].text,Fontsize).Width,
                 GetText(Texts_Block2[2].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 12
          TextObj(0,"Event Name Text",Texts_Block2[2].subtext("Event Name Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[2].subtext("Event Name Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Name",Texts_Block2[2].subtext("Event Name"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 13*/
          Y_start+=GetText(Texts_Block2[2].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 13 text
          Square(0,"Event Country background",X_start,Y_start,GetText(Texts_Block2[3].text,Fontsize).Width,
                 GetText(Texts_Block2[3].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 13
          TextObj(0,"Event Country Text",Texts_Block2[3].subtext("Event Country Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[3].subtext("Event Country Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Country",Texts_Block2[3].subtext("Event Country"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 14*/
          Y_start+=GetText(Texts_Block2[3].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 14 text
          Square(0,"Event Currency background",X_start,Y_start,GetText(Texts_Block2[4].text,Fontsize).Width,
                 GetText(Texts_Block2[4].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 14
          TextObj(0,"Event Currency Text",Texts_Block2[4].subtext("Event Currency Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[4].subtext("Event Currency Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Currency",Texts_Block2[4].subtext("Event Currency"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 15*/
          Y_start+=GetText(Texts_Block2[4].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 15 text
          Square(0,"Event Importance background",X_start,Y_start,GetText(Texts_Block2[5].text,Fontsize).Width,
                 GetText(Texts_Block2[5].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 15
          TextObj(0,"Importance Text",Texts_Block2[5].subtext("Importance Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[5].subtext("Importance Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Importance",Texts_Block2[5].subtext("Importance"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 16*/
          if(is_spread)//Check whether to display spread information
            {
             Y_start+=GetText(Texts_Block2[5].text,Fontsize).Height;//Re-adjust Y distance
             X_start=2;//Reset X distance
             //-- Create the background object for width and height+3 of section 16 text
             Square(0,"Spread background",X_start,Y_start,GetText(Texts_Block2[6].text,Fontsize).Width,
                    GetText(Texts_Block2[6].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
             Y_start+=3;//Re-adjust Y distance
             X_start+=2;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             color Spread_clr=CSymbol.SpreadColor();
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             //-- Will create the text objects for section 16
             TextObj(0,"Symbol Spread Text",Texts_Block2[6].subtext("Spread Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Spread",Texts_Block2[6].subtext("Spread"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             TextObj(0,"Symbol Rating Text",Texts_Block2[6].subtext("Rating Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Rating Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Rating",Texts_Block2[6].subtext("Rating Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
            }
         }
       else
          /* Create objects # section 16*/
          if(is_spread)//Check whether to display spread information
            {
             Y_start+=(is_date)?GetText(Texts_Block2[0].text,Fontsize).Height:0;//Re-adjust Y distance depending if section 10 is shown
             X_start=2;//Reset X distance
             //-- Create the background object for width and height+3 of section 16 text
             Square(0,"Spread background",X_start,Y_start,GetText(Texts_Block2[6].text,Fontsize).Width,
                    GetText(Texts_Block2[6].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
             Y_start+=3;//Re-adjust Y distance
             X_start+=2;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             color Spread_clr=CSymbol.SpreadColor();
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             //-- Will create the text objects for section 16
             TextObj(0,"Symbol Spread Text",Texts_Block2[6].subtext("Spread Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Spread",Texts_Block2[6].subtext("Spread"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             TextObj(0,"Symbol Rating Text",Texts_Block2[6].subtext("Rating Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Rating Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Rating",Texts_Block2[6].subtext("Rating Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
            }
      }

    Die folgende Funktion aktualisiert alle Änderungen an den grafischen Abschnitten von Block 2 und wird nicht alle Elemente aus der Funktion Block_2 neu erstellen.

    //+------------------------------------------------------------------+
    //|will update certain graphics at an interval                       |
    //+------------------------------------------------------------------+
    void CCommonGraphics::Block_2_Realtime(uint SecondsPreEvent=5)
      {
       if(MQLInfoInteger(MQL_TESTER)&&!MQLInfoInteger(MQL_VISUAL_MODE))
         {
          return;//exit if in strategy tester and not in visual mode
         }
    
       if(is_date)//Check whether to display date information
         {
          //--- Set text properties for Date and Time # section 10
          Texts_Block2[0].text = "Date:"+TimeToString(TimeTradeServer(),TIME_DATE)+"|| Time:"+TimeToString(TimeTradeServer(),TIME_SECONDS)
                                 +"   ";//set main text
          Texts_Block2[0].subtext("Date Text","Date:");//set subtext - label,value
          Texts_Block2[0].subtext("Date",TimeToString(TimeTradeServer(),TIME_DATE));//set subtext - label,value
          Texts_Block2[0].subtext("Time Text","|| Time:");//set subtext - label,value
          Texts_Block2[0].subtext("Time",TimeToString(TimeTradeServer(),TIME_SECONDS));//set subtext - label,value
         }
       if(is_news)//Check whether to display news information
         {
          //--- Set text object color depending on upcoming news event's Importance
          EventColor = NewsObj.GetImportance_color(NewsObj.IMPORTANCE(UpcomingNews.EventImportance));
          //--- Set text properties for Event Date # section 11
          Texts_Block2[1].text = "Event: @"+UpcomingNews.EventDate+" ";//set main text
          Texts_Block2[1].subtext("Event Date Text","Event: @");//set subtext - label,value
          Texts_Block2[1].subtext("Event Date",UpcomingNews.EventDate);//set subtext - label,value
          //--- Set text properties for Event Name # section 12
          Texts_Block2[2].text = "Name: "+UpcomingNews.EventName+" ";//set main text
          Texts_Block2[2].subtext("Event Name Text","Name: ");//set subtext - label,value
          Texts_Block2[2].subtext("Event Name",UpcomingNews.EventName);//set subtext - label,value
          //--- Set text properties for Event Country # section 13
          Texts_Block2[3].text = "Country: "+UpcomingNews.CountryName+" ";//set main text
          Texts_Block2[3].subtext("Event Country Text","Country: ");//set subtext - label,value
          Texts_Block2[3].subtext("Event Country",UpcomingNews.CountryName);//set subtext - label,value
          //--- Set text properties for Event Currency # section 14
          Texts_Block2[4].text = "Currency: "+UpcomingNews.EventCurrency+" ";//set main text
          Texts_Block2[4].subtext("Event Currency Text","Currency: ");//set subtext - label,value
          Texts_Block2[4].subtext("Event Currency",UpcomingNews.EventCurrency);//set subtext - label,value
          //--- Set text properties for Event Importance # section 15
          Texts_Block2[5].text = "Importance: "+NewsObj.GetImportance(NewsObj.IMPORTANCE(UpcomingNews.EventImportance))+" ";//set main text
          Texts_Block2[5].subtext("Importance Text","Importance: ");//set subtext - label,value
          Texts_Block2[5].subtext("Importance",NewsObj.GetImportance(NewsObj.IMPORTANCE(UpcomingNews.EventImportance)));//set subtext - label,value
         }
       if(is_spread)//Check whether to display spread information
         {
          //--- Set text properties for Spread # section 16
          Texts_Block2[6].text = "Spread: "+string(CSymbol.Spread())+" Rating: "+CSymbol.SpreadDesc()+" ";//set main text
          Texts_Block2[6].subtext("Spread Text","Spread:");//set subtext - label,value
          Texts_Block2[6].subtext("Spread",string(CSymbol.Spread()));//set subtext - label,value
          Texts_Block2[6].subtext("Rating Text"," Rating:");//set subtext - label,value
          Texts_Block2[6].subtext("Rating Desc",CSymbol.SpreadDesc());//set subtext - label,value
         }
    
    //--- Set basic properties
       Fontsize=10;
       X_start=2;//Reset X distance
       Y_start=GetTextMax(Texts_Block1,Fontsize).Height+29;//Re-adjust Y distance from section block 1
    
       /* Create objects # section 10*/
       if(is_date)//Check whether to display date information
         {
          //-- Check if the background object x-size for section 10 is the same size as section 10 text width
          if(ObjectGetInteger(0,"Datetime background",OBJPROP_XSIZE)!=GetText(Texts_Block2[0].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 10 text width
             ObjectSetInteger(0,"Datetime background",OBJPROP_XSIZE,long(GetText(Texts_Block2[0].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 10
          TextObj(0,"Date Text",Texts_Block2[0].subtext("Date Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Date Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Date",Texts_Block2[0].subtext("Date"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Date"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Time Text",Texts_Block2[0].subtext("Time Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Time Text"),Fontsize).Width;//Re-adjust X distance
          //--- Adjust text color depending if chart color mode is LightMode and if a news event is occurring
          TextObj_color = CTime.TimeIsInRange(CTime.TimeMinusOffset(datetime(UpcomingNews.EventDate),SecondsPreEvent),
                                              CTime.TimePlusOffset(datetime(UpcomingNews.EventDate),59))?clrRed:(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Time",Texts_Block2[0].subtext("Time"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
         }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       if(UpcomingNews.CountryName!=NULL&&is_news)//Check whether to display news information
         {
          /* Create objects # section 11*/
          Y_start+=(is_date)?GetText(Texts_Block2[0].text,Fontsize).Height:0;
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 11 is the same size as section 11 text width
          if(ObjectGetInteger(0,"Event Date background",OBJPROP_XSIZE)!=GetText(Texts_Block2[1].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 11 text width
             ObjectSetInteger(0,"Event Date background",OBJPROP_XSIZE,long(GetText(Texts_Block2[1].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 11
          TextObj(0,"Event Date Text",Texts_Block2[1].subtext("Event Date Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[1].subtext("Event Date Text"),Fontsize).Width;//Re-adjust X distance
          //--- Adjust text color depending if chart color mode is LightMode and if a news event is occurring
          TextObj_color = CTime.TimeIsInRange(CTime.TimeMinusOffset(datetime(UpcomingNews.EventDate),SecondsPreEvent),
                                              CTime.TimePlusOffset(datetime(UpcomingNews.EventDate),59))?clrRed:(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Event Date",Texts_Block2[1].subtext("Event Date"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 12*/
          Y_start+=GetText(Texts_Block2[1].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 12 is the same size as section 12 text width
          if(ObjectGetInteger(0,"Event Name background",OBJPROP_XSIZE)!=GetText(Texts_Block2[2].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 12 text width
             ObjectSetInteger(0,"Event Name background",OBJPROP_XSIZE,long(GetText(Texts_Block2[2].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 12
          TextObj(0,"Event Name Text",Texts_Block2[2].subtext("Event Name Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[2].subtext("Event Name Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Name",Texts_Block2[2].subtext("Event Name"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 13*/
          Y_start+=GetText(Texts_Block2[2].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 13 is the same size as section 13 text width
          if(ObjectGetInteger(0,"Event Country background",OBJPROP_XSIZE)!=GetText(Texts_Block2[3].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 13 text width
             ObjectSetInteger(0,"Event Country background",OBJPROP_XSIZE,long(GetText(Texts_Block2[3].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 13
          TextObj(0,"Event Country Text",Texts_Block2[3].subtext("Event Country Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[3].subtext("Event Country Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Country",Texts_Block2[3].subtext("Event Country"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 14*/
          Y_start+=GetText(Texts_Block2[3].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 14 is the same size as section 14 text width
          if(ObjectGetInteger(0,"Event Currency background",OBJPROP_XSIZE)!=GetText(Texts_Block2[4].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 14 text width
             ObjectSetInteger(0,"Event Currency background",OBJPROP_XSIZE,long(GetText(Texts_Block2[4].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 14
          TextObj(0,"Event Currency Text",Texts_Block2[4].subtext("Event Currency Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[4].subtext("Event Currency Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Currency",Texts_Block2[4].subtext("Event Currency"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 15*/
          Y_start+=GetText(Texts_Block2[4].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 15 is the same size as section 15 text width
          if(ObjectGetInteger(0,"Event Importance background",OBJPROP_XSIZE)!=GetText(Texts_Block2[5].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 15 text width
             ObjectSetInteger(0,"Event Importance background",OBJPROP_XSIZE,long(GetText(Texts_Block2[5].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 15
          TextObj(0,"Importance Text",Texts_Block2[5].subtext("Importance Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[5].subtext("Importance Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Importance",Texts_Block2[5].subtext("Importance"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 16*/
          if(is_spread)//Check whether to display spread information
            {
             Y_start+=GetText(Texts_Block2[5].text,Fontsize).Height;//Re-adjust Y distance
             X_start=2;//Reset X distance
             //-- Check if the background object x-size for section 16 is the same size as section 16 text width
             if(ObjectGetInteger(0,"Spread background",OBJPROP_XSIZE)!=GetText(Texts_Block2[6].text,Fontsize).Width)
               {
                //-- Will re-adjust background object to any changes of section 16 text width
                ObjectSetInteger(0,"Spread background",OBJPROP_XSIZE,long(GetText(Texts_Block2[6].text,Fontsize).Width));
               }
             Y_start+=3;//Re-adjust Y distance
             X_start+=2;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             color Spread_clr=CSymbol.SpreadColor();
             //-- Will create the text object for the Symbol's name
             X_start+=GetText(Texts_Block2[6].subtext("Spread Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             //-- Will update the text objects for section 16
             TextObj(0,"Symbol Spread",Texts_Block2[6].subtext("Spread"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             TextObj(0,"Symbol Rating Text",Texts_Block2[6].subtext("Rating Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Rating Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Rating",Texts_Block2[6].subtext("Rating Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
            }
         }
       else
          /* Create objects # section 16*/
          if(is_spread)//Check whether to display spread information
            {
             Y_start+=(is_date)?GetText(Texts_Block2[0].text,Fontsize).Height:0;//Re-adjust Y distance
             X_start=2;//Reset X distance
             //-- Check if the background object x-size for section 16 is the same size as section 16 text width
             if(ObjectGetInteger(0,"Spread background",OBJPROP_XSIZE)!=GetText(Texts_Block2[6].text,Fontsize).Width)
               {
                //-- Will re-adjust background object to any changes of section 16 text width
                ObjectSetInteger(0,"Spread background",OBJPROP_XSIZE,long(GetText(Texts_Block2[6].text,Fontsize).Width));
               }
             Y_start+=3;//Re-adjust Y distance
             X_start+=2;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             color Spread_clr=CSymbol.SpreadColor();
             //-- Will create the text object for the Symbol's name
             X_start+=GetText(Texts_Block2[6].subtext("Spread Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             //-- Will update the text objects for section 16
             TextObj(0,"Symbol Spread",Texts_Block2[6].subtext("Spread"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             TextObj(0,"Symbol Rating Text",Texts_Block2[6].subtext("Rating Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Rating Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Rating",Texts_Block2[6].subtext("Rating Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
            }
      }

    Die folgende Funktion erstellt das Ereignisobjekt im Chart mit allen verfügbaren Nachrichtenereignissen für den aktuellen Tag.

    Abschnitt 17

    //+------------------------------------------------------------------+
    //|will create chart event objects                                   |
    //+------------------------------------------------------------------+
    void CCommonGraphics::NewsEvent()
      {
       if(!is_events||(MQLInfoInteger(MQL_TESTER)&&!MQLInfoInteger(MQL_VISUAL_MODE)))
         {return;}//exit if in strategy tester and not in visual mode or is_events variable is false
    //--- Retrieve news events for the current Daily period into array CalendarArray
       NewsObj.EconomicDetailsMemory(CalendarArray,iTime(Symbol(),PERIOD_D1,0));
    //--- Iterate through all events in CalendarArray
       for(uint i=0;i<CalendarArray.Size();i++)
         {
          //--- Create event object with the news properties
          EventObj(0,CalendarArray[i].EventName+" "+CalendarArray[i].CountryName+" "+CalendarArray[i].EventDate,
                   CalendarArray[i].EventName+"["+CalendarArray[i].CountryName+"]",StringToTime(CalendarArray[i].EventDate));
         }
    //--- Refresh the chart/ update the chart
       ChartRefresh();
      }


    Handelsmanagement-Klasse

    Diese Klasse wird für die Eröffnung von Handelsgeschäften für unseren Experten verantwortlich sein. Die Funktionalität dieser Klasse wird wahrscheinlich in späteren Artikeln erweitert. Die Handelsmanagementklasse wird von der Risikomanagementklasse abgeleitet, um die Losgrößen für jeden Handel zu konfigurieren.

    #include <Trade\Trade.mqh>
    #include <Trade\OrderInfo.mqh>
    #include <Trade\SymbolInfo.mqh>
    #include "RiskManagement.mqh"
    #include "TimeManagement.mqh"
    //+------------------------------------------------------------------+
    //|TradeManagement class                                             |
    //+------------------------------------------------------------------+
    class CTradeManagement:CRiskManagement
      {
    private:
       CTrade            Trade;//Trade class object
       CSymbolProperties CSymbol;//SymbolProperties class object
       CTimeManagement   CTime;//TimeManagement class object
       bool              TradeResult;//boolean to store trade result
       double            mySL;//double variable to store Stoploss
       double            myTP;//double variable to store Takeprofit
    public:
       //--- Class constructor
                         CTradeManagement(string SYMBOL=NULL)
         {
          //--- Set symbol name
          CSymbol.SetSymbolName(SYMBOL);
         }
       //--- Class destructor
                        ~CTradeManagement(void) {}
       //--- Will retrieve if there are any open trades
       bool              OpenTrade(ENUM_POSITION_TYPE Type,ulong Magic,string COMMENT=NULL);
       //--- Will retrieve if there are any deals
       bool              OpenedDeal(ENUM_DEAL_TYPE Type,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open buy trade
       bool              Buy(double SL,double TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open buy trade with integer SL
       bool              Buy(int SL,double TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open buy trade with integer TP
       bool              Buy(double SL,int TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open buy trade with integer SL & TP
       bool              Buy(int SL,int TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open sell trade
       bool              Sell(double SL,double TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open sell trade with integer SL
       bool              Sell(int SL,double TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open sell trade with integer TP
       bool              Sell(double SL,int TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open sell trade with integer SL & TP
       bool              Sell(int SL,int TP,ulong Magic,string COMMENT=NULL);
      };

    Die folgende Funktion sucht nach offenen Positionen mit einem bestimmten Positionstyp (Kauf/Verkauf), Magic (eindeutiger Fußabdruck), Comment (Positionsdetails). Wir verwenden diese Funktion, um zu prüfen, ob wir bereits einen Handel eröffnet haben, wenn das Nachrichtenereignis eintritt, sodass wir die Eröffnung zusätzlicher/unnötiger Handelsgeschäfte vermeiden.

    //+------------------------------------------------------------------+
    //|Will retrieve if there are any open trades                        |
    //+------------------------------------------------------------------+
    bool CTradeManagement::OpenTrade(ENUM_POSITION_TYPE Type,ulong Magic,string COMMENT=NULL)
      {
    //--- Iterate through all open positions
       for(int i=0; i<PositionsTotal(); i++)
         {
          //--- Check if Position ticket is above zero
          if(PositionGetTicket(i)>0)
            {
             //--- Check if the Position's Symbol,Magic,Type,Comment is correct
             if(PositionGetString(POSITION_SYMBOL)==CSymbol.GetSymbolName()&&PositionGetInteger(POSITION_MAGIC)==Magic
                &&PositionGetInteger(POSITION_TYPE)==Type&&PositionGetString(POSITION_COMMENT)==COMMENT)
               {
                //--- Return true when there is an open position
                return true;
               }
            }
         }
    //--- No open positions found.
       return false;
      }

    Die Funktion OpenedDeal prüft, ob ein Handelsgeschäft geöffnet ist, d.h. ob offene Kauf-/Verkauf-Deals oder Handelsgeschäfte existieren. Wir benötigen diese Funktion, um zu verhindern, dass wir bzw. der Experte neue Handelsgeschäfte eröffnen, wenn ein Handelsgeschäft während eines Nachrichtenereignisses geschlossen wurde. Ohne diese Funktion wird der Experte einen Kauf eröffnen, wenn z.B. der NFP kurz bevorsteht. Wenn eine offene Kaufposition aufgrund der Volatilität geschlossen wird, möchten wir nicht, dass der Experte einen weiteres Handelsgeschäfte eröffnet, da wir das Ereignis bereits gehandelt haben und keinen Bedarf an weiteren haben, die zu unnötigen Verlusten führen könnten. 

    //+------------------------------------------------------------------+
    //|Will retrieve if there are any deals                              |
    //+------------------------------------------------------------------+
    bool CTradeManagement::OpenedDeal(ENUM_DEAL_TYPE Type,ulong Magic,string COMMENT=NULL)
      {
    //--- Check History starting from 2 minutes ago
       if(HistorySelect(CTime.TimeMinusOffset(TimeTradeServer(),CTime.MinutesS(2)),TimeTradeServer()))
         {
          //--- Iterate through all history deals
          for(int i=0; i<HistoryDealsTotal(); i++)
            {
             //--- Assign history deal ticket
             ulong ticket = HistoryDealGetTicket(i);
             //--- Check if ticket is more than zero
             if(ticket>0)
               {
                //--- Check if the Deal's Symbol,Magic,Type,Comment is correct
                if(HistoryDealGetString(ticket,DEAL_SYMBOL)==CSymbol.GetSymbolName()&&
                   HistoryDealGetInteger(ticket,DEAL_MAGIC)==Magic&&HistoryDealGetInteger(ticket,DEAL_TYPE)==Type
                   &&HistoryDealGetString(ticket,DEAL_COMMENT)==COMMENT)
                  {
                   //--- Return true when there are any deals
                   return true;
                  }
               }
            }
         }
    //--- No deals found.
       return false;
      }

    Mit der folgenden Funktion werden alle Marktaufträge für Kauf-Handelsgeschäfte geöffnet.

    //+------------------------------------------------------------------+
    //|Will attempt open buy trade                                       |
    //+------------------------------------------------------------------+
    bool CTradeManagement::Buy(double SL,double TP,ulong Magic,string COMMENT=NULL)
      {
    //--- Normalize the SL Price
       CSymbol.NormalizePrice(SL);
    //--- Normalize the TP Price
       CSymbol.NormalizePrice(TP);
    //--- Set the order type for Risk management calculation
       SetOrderType(ORDER_TYPE_BUY);
    //--- Set open price for Risk management calculation
       OpenPrice = CSymbol.Ask();
    //--- Set close price for Risk management calculation
       ClosePrice = SL;
    //--- Set Trade magic number
       Trade.SetExpertMagicNumber(Magic);
    //--- Check if there are any open trades or opened deals already
       if(!OpenTrade(POSITION_TYPE_BUY,Magic,COMMENT)&&!OpenedDeal(DEAL_TYPE_BUY,Magic,COMMENT))
         {
          //--- Iterate through the Lot-sizes if they're more than max-lot
          for(double i=Volume();i>=CSymbol.LotsMin();i-=CSymbol.LotsMax())
            {
             //--- normalize Lot-size
             NormalizeLotsize(i);
             //--- Open trade with a Lot-size not more than max-lot
             TradeResult = Trade.Buy((i>CSymbol.LotsMax())?CSymbol.LotsMax():i,CSymbol.GetSymbolName(),CSymbol.Ask(),SL,TP,COMMENT);
             //--- Check if trade failed.
             if(!TradeResult)
               {
                return TradeResult;
               }
            }
         }
       else
         {
          //--- Trade failed because there is an open trade or opened deal
          return false;
         }
    //--- Return trade result.
       return TradeResult;
      }

    Die nachstehende Funktion öffnet alle Marktaufträge für Verkaufs-Handelsgeschäfte.

    //+------------------------------------------------------------------+
    //|Will attempt open sell trade                                      |
    //+------------------------------------------------------------------+
    bool CTradeManagement::Sell(double SL,double TP,ulong Magic,string COMMENT=NULL)
      {
    //--- Normalize the SL Price
       CSymbol.NormalizePrice(SL);
    //--- Normalize the TP Price
       CSymbol.NormalizePrice(TP);
    //--- Set the order type for Risk management calculation
       SetOrderType(ORDER_TYPE_SELL);
    //--- Set open price for Risk management calculation
       OpenPrice = CSymbol.Bid();
    //--- Set close price for Risk management calculation
       ClosePrice = SL;
    //--- Set Trade magic number
       Trade.SetExpertMagicNumber(Magic);
    //--- Check if there are any open trades or opened deals already
       if(!OpenTrade(POSITION_TYPE_SELL,Magic,COMMENT)&&!OpenedDeal(DEAL_TYPE_SELL,Magic,COMMENT))
         {
          //--- Iterate through the Lot-sizes if they're more than max-lot
          for(double i=Volume();i>=CSymbol.LotsMin();i-=CSymbol.LotsMax())
            {
             //--- normalize Lot-size
             NormalizeLotsize(i);
             //--- Open trade with a Lot-size not more than max-lot
             TradeResult = Trade.Sell((i>CSymbol.LotsMax())?CSymbol.LotsMax():i,CSymbol.GetSymbolName(),CSymbol.Bid(),SL,TP,COMMENT);
             //--- Check if trade failed.
             if(!TradeResult)
               {
                return TradeResult;
               }
            }
         }
       else
         {
          //--- Trade failed because there is an open trade or opened deal
          return false;
         }
    //--- Return trade result.
       return TradeResult;
      }


    Experte für den Handle von Nachrichten

    Wir haben neue Eingaben für den Experten, wir haben die Erklärungen bereits in der Einleitung gesehen.

    //--- width and height of the canvas (used for drawing)
    #define IMG_WIDTH  200
    #define IMG_HEIGHT 100
    //--- enable to set color format
    ENUM_COLOR_FORMAT clr_format=COLOR_FORMAT_XRGB_NOALPHA;
    //--- drawing array (buffer)
    uint ExtImg[IMG_WIDTH*IMG_HEIGHT];
    
    #include "News.mqh"
    CNews NewsObject;//Class object for News
    #include "TimeManagement.mqh"
    CTimeManagement CTM;//Class object for Time Management
    #include "WorkingWithFolders.mqh"
    CFolders Folder;//Class object for Folders
    #include "ChartProperties.mqh"
    CChartProperties Chart;//Class object for Chart Properties
    #include "RiskManagement.mqh"
    CRiskManagement CRisk;//Class object for Risk Management
    #include "CommonGraphics.mqh"
    CCommonGraphics *CGraphics;//Class pointer object for Common Graphics
    CCandleProperties *CP;//Class pointer object for Candle Properties
    #include "TradeManagement.mqh"
    CTradeManagement Trade;//Class object for Trade Management
    
    //--- used to separate Input Menu
    enum iSeparator
      {
       Delimiter//__________________________
      };
    
    //--- for chart color Mode selection
    enum DisplayMode
      {
       Display_LightMode,//LIGHT MODE
       Display_DarkMode//DARK MODE
      };
    
    sinput group "+--------|   DISPLAY   |--------+";
    sinput DisplayMode iDisplayMode=Display_LightMode;//CHART COLOUR MODE
    sinput Choice iDisplay_NewsInfo=Yes;//DISPLAY NEWS INFO
    sinput Choice iDisplay_EventObj=Yes;//DISPLAY EVENT OBJ
    sinput Choice iDisplay_Spread=Yes;//DISPLAY SPREAD RATING
    sinput Choice iDisplay_Date=Yes;//DISPLAY DATE
    sinput group "";
    sinput group "+--------|   DST SCHEDULE   |--------+";
    input DSTSchedule ScheduleDST=AutoDst_Selection;//SELECT DST OPTION
    sinput iSeparator iCustomSchedule=Delimiter;//__________________________
    sinput iSeparator iCustomScheduleL=Delimiter;//CUSTOM DST
    input DST_type CustomSchedule=DST_NONE;//SELECT CUSTOM DST
    sinput group "";
    sinput group "+--------| RISK MANAGEMENT |--------+";
    input RiskOptions RISK_Type=MINIMUM_LOT;//SELECT RISK OPTION
    input RiskFloor RISK_Mini=RiskFloorMin;//RISK FLOOR
    input double RISK_Mini_Percent=75;//MAX-RISK [100<-->0.01]%
    input RiskCeil  RISK_Maxi=RiskCeilMax;//RISK CEILING
    sinput iSeparator iRisk_1=Delimiter;//__________________________
    sinput iSeparator iRisk_1L=Delimiter;//PERCENTAGE OF [BALANCE | FREE-MARGIN]
    input double Risk_1_PERCENTAGE=3;//[100<-->0.01]%
    sinput iSeparator iRisk_2=Delimiter;//__________________________
    sinput iSeparator iRisk_2L=Delimiter;//AMOUNT PER [BALANCE | FREE-MARGIN]
    input double Risk_2_VALUE=1000;//[BALANCE | FREE-MARGIN]
    input double Risk_2_AMOUNT=10;//EACH AMOUNT
    sinput iSeparator iRisk_3=Delimiter;//__________________________
    sinput iSeparator iRisk_3L=Delimiter;//LOTSIZE PER [BALANCE | FREE-MARGIN]
    input double Risk_3_VALUE=1000;//[BALANCE | FREE-MARGIN]
    input double Risk_3_LOTSIZE=0.1;//EACH LOTS(VOLUME)
    sinput iSeparator iRisk_4=Delimiter;//__________________________
    sinput iSeparator iRisk_4L=Delimiter;//CUSTOM LOTSIZE
    input double Risk_4_LOTSIZE=0.01;//LOTS(VOLUME)
    sinput iSeparator iRisk_5=Delimiter;//__________________________
    sinput iSeparator iRisk_5L=Delimiter;//PERCENTAGE OF MAX-RISK
    input double Risk_5_PERCENTAGE=1;//[100<-->0.01]%
    sinput group "";
    sinput group "+--------| NEWS SETTINGS |--------+";
    input Calendar_Importance iImportance=Calendar_Importance_High;//CALENDAR IMPORTANCE
    input Event_Frequency iFrequency=Event_Frequency_ALL;//EVENT FREQUENCY
    input Event_Sector iSector=Event_Sector_ALL;//EVENT SECTOR
    input Event_Type iType=Event_Type_Indicator;//EVENT TYPE
    input Event_Currency iCurrency=Event_Currency_Symbol;//EVENT CURRENCY
    sinput group "";
    sinput group "+--------| TRADE SETTINGS |--------+";
    input uint iStoploss=500;//STOPLOSS [0=NONE]
    input uint iTakeprofit=500;//TAKEPROFIT [0=NONE]
    input uint iSecondsPreEvent=5;//PRE-ENTRY SEC
    input DayOfTheWeek TradingDay=AllDays;//TRADING DAY OF WEEK
    sinput group "";
    //--- to keep track of start-up time
    datetime Startup_date;

    In der OnInit Integer-Funktion unten durchlaufen wir verschiedene Prozeduren, wenn wir den Experten für den Handel einrichten, ob im Strategietester oder nicht.

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- Assign if in LightMode or not
       isLightMode=(iDisplayMode==Display_LightMode)?true:false;
    //--- call function for common initialization procedure
       InitCommon();
    //--- store Init result
       int InitResult;
       if(!MQLInfoInteger(MQL_TESTER))//Checks whether the program is in the strategy tester
         {
          //--- initialization procedure outside strategy tester
          InitResult=InitNonTester();
         }
       else
         {
          //--- initialization procedure inside strategy tester
          InitResult=InitTester();
         }
    //--- Create DB in memory
       NewsObject.CreateEconomicDatabaseMemory();
    //--- Initialize Common graphics class pointer object
       CGraphics = new CCommonGraphics(Answer(iDisplay_Date),Answer(iDisplay_Spread),Answer(iDisplay_NewsInfo),Answer(iDisplay_EventObj));
       CGraphics.GraphicsRefresh(iSecondsPreEvent);//-- Create chart objects
    //--- Initialize Candle properties pointer object
       CP = new CCandleProperties();
    //--- Store start-up time.
       Startup_date = TimeTradeServer();
    //--- return Init result
       return InitResult;
      }

    In der folgenden Funktion initialisieren wir die Eigenschaften sowohl für den Strategietester als auch für die normale Handelsumgebung.

    //+------------------------------------------------------------------+
    //|function for common initialization procedure                      |
    //+------------------------------------------------------------------+
    void InitCommon()
      {
    //Initializing CRiskManagement variable for Risk options
       RiskProfileOption = RISK_Type;
    //Initializing CRiskManagement variable for Risk floor
       RiskFloorOption = RISK_Mini;
    //Initializing CRiskManagement variable for RiskFloorMax
       RiskFloorPercentage = (RISK_Mini_Percent>100)?100:
                             (RISK_Mini_Percent<0.01)?0.01:RISK_Mini_Percent;//Percentage cannot be more than 100% or less than 0.01%
    //Initializing CRiskManagement variable for Risk ceiling
       RiskCeilOption = RISK_Maxi;
    //Initializing CRiskManagement variable for Risk options (PERCENTAGE OF BALANCE and PERCENTAGE OF FREE-MARGIN)
       Risk_Profile_1 = (Risk_1_PERCENTAGE>100)?100:
                        (Risk_1_PERCENTAGE<0.01)?0.01:Risk_1_PERCENTAGE;//Percentage cannot be more than 100% or less than 0.01%
    //Initializing CRiskManagement variables for Risk options (AMOUNT PER BALANCE and AMOUNT PER FREE-MARGIN)
       Risk_Profile_2.RiskAmountBoF = Risk_2_VALUE;
       Risk_Profile_2.RiskAmount = Risk_2_AMOUNT;
    //Initializing CRiskManagement variables for Risk options (LOTSIZE PER BALANCE and LOTSIZE PER FREE-MARGIN)
       Risk_Profile_3.RiskLotBoF = Risk_3_VALUE;
       Risk_Profile_3.RiskLot = Risk_3_LOTSIZE;
    //Initializing CRiskManagement variable for Risk option (CUSTOM LOTSIZE)
       Risk_Profile_4 = Risk_4_LOTSIZE;
    //Initializing CRiskManagement variable for Risk option (PERCENTAGE OF MAX-RISK)
       Risk_Profile_5 = (Risk_5_PERCENTAGE>100)?100:
                        (Risk_5_PERCENTAGE<0.01)?0.01:Risk_5_PERCENTAGE;//Percentage cannot be more than 100% or less than 0.01%
    //--- Initializing DST Schedule variables
       MyDST = ScheduleDST;
       MySchedule = CustomSchedule;
    //--- Initializing News filter variables
       myFrequency=iFrequency;
       myImportance=iImportance;
       mySector=iSector;
       myType=iType;
       myCurrency=iCurrency;
       Chart.ChartRefresh();//Load chart configurations
      }

    Die folgende Funktion wird nur für die normale Handelsumgebung initialisiert.

    //+------------------------------------------------------------------+
    //|function for initialization procedure outside strategy tester     |
    //+------------------------------------------------------------------+
    int InitNonTester()
      {
    //--- Check if in Strategy tester!
       if(MQLInfoInteger(MQL_TESTER))
         {
          //--- Initialization failed.
          return(INIT_SUCCEEDED);
         }
    //--- create OBJ_BITMAP_LABEL object for drawing
       ObjectCreate(0,"STATUS",OBJ_BITMAP_LABEL,0,0,0);
       ObjectSetInteger(0,"STATUS",OBJPROP_XDISTANCE,5);
       ObjectSetInteger(0,"STATUS",OBJPROP_YDISTANCE,22);
    //--- specify the name of the graphical resource
       ObjectSetString(0,"STATUS",OBJPROP_BMPFILE,"::PROGRESS");
       uint   w,h;          // variables for receiving text string sizes
       uint    x,y;          // variables for calculation of the current coordinates of text string anchor points
       /*
       In the Do while loop below, the code will check if the terminal is connected to the internet.
       If the the program is stopped the loop will break, if the program is not stopped and the terminal
       is connected to the internet the function CreateEconomicDatabase will be called from the News.mqh header file's
       object called NewsObject and the loop will break once called.
       */
       bool done=false;
       do
         {
          //--- clear the drawing buffer array
          ArrayFill(ExtImg,0,IMG_WIDTH*IMG_HEIGHT,0);
    
          if(!TerminalInfoInteger(TERMINAL_CONNECTED))
            {
             //-- integer dots used as a loading animation
             static int dots=0;
             //--- set the font
             TextSetFont("Arial",-150,FW_EXTRABOLD,0);
             TextGetSize("Waiting",w,h);//get text width and height values
             //--- calculate the coordinates of the 'Waiting' text
             x=10;//horizontal alignment
             y=IMG_HEIGHT/2-(h/2);//alignment for the text to be centered vertically
             //--- output the 'Waiting' text to ExtImg[] buffer
             TextOut("Waiting",x,y,TA_LEFT|TA_TOP,ExtImg,IMG_WIDTH,IMG_HEIGHT,ColorToARGB(CSymbol.Background()),clr_format);
             //--- calculate the coordinates for the dots after the 'Waiting' text
             x=w+13;//horizontal alignment
             y=IMG_HEIGHT/2-(h/2);//alignment for the text to be centered vertically
             TextSetFont("Arial",-160,FW_EXTRABOLD,0);
             //--- output of dots to ExtImg[] buffer
             TextOut(StringSubstr("...",0,dots),x,y,TA_LEFT|TA_TOP,ExtImg,IMG_WIDTH,IMG_HEIGHT,ColorToARGB(CSymbol.Background()),clr_format);
             //--- update the graphical resource
             ResourceCreate("::PROGRESS",ExtImg,IMG_WIDTH,IMG_HEIGHT,0,0,IMG_WIDTH,clr_format);
             //--- force chart update
             Chart.Redraw();
             dots=(dots==3)?0:dots+1;
             //-- Notify user that program is waiting for connection
             Print("Waiting for connection...");
             Sleep(500);
             continue;
            }
          else
            {
             //--- set the font
             TextSetFont("Arial",-120,FW_EXTRABOLD,0);
             TextGetSize("Getting Ready",w,h);//get text width and height values
             x=20;//horizontal alignment
             y=IMG_HEIGHT/2-(h/2);//alignment for the text to be centered vertically
             //--- output the text 'Getting Ready...' to ExtImg[] buffer
             TextOut("Getting Ready...",x,y,TA_LEFT|TA_TOP,ExtImg,IMG_WIDTH,IMG_HEIGHT,ColorToARGB(CSymbol.Background()),clr_format);
             //--- update the graphical resource
             ResourceCreate("::PROGRESS",ExtImg,IMG_WIDTH,IMG_HEIGHT,0,0,IMG_WIDTH,clr_format);
             //--- force chart update
             Chart.Redraw();
             //-- Notify user that connection is successful
             Print("Connection Successful!");
             NewsObject.CreateEconomicDatabase();//calling the database create function
             done=true;
            }
         }
       while(!done&&!IsStopped());
    //-- Delete chart object
       ObjectDelete(0,"STATUS");
    //-- force chart to update
       Chart.Redraw();
    //--- Initialization succeeded.
       return(INIT_SUCCEEDED);
      }

    Die folgende Funktion wird nur für die Umgebung des Strategietesters initialisiert.

    //+------------------------------------------------------------------+
    //|function for initialization procedure inside strategy tester      |
    //+------------------------------------------------------------------+
    int InitTester()
      {
    //--- Check if not in Strategy tester!
       if(!MQLInfoInteger(MQL_TESTER))
         {
          //--- Initialization failed.
          return(INIT_SUCCEEDED);
         }
    //Checks whether the database file exists
       if(!FileIsExist(NEWS_DATABASE_FILE,FILE_COMMON))
         {
          //--- Warning messages
          Print("Necessary Files Do not Exist!");
          Print("Run Program outside of the Strategy Tester");
          Print("Necessary Files Should be Created First");
          //--- Initialization failed.
          return(INIT_FAILED);
         }
       else
         {
          //Checks whether the latest database date includes the time and date being tested
          datetime latestdate = CTM.TimeMinusOffset(NewsObject.GetLatestNewsDate(),CTM.DaysS());//Day before the latest recorded time in the database
          if(latestdate<TimeTradeServer())
            {
             Print("Necessary Files outdated!");
             Print("To Update Files: Run Program outside of the Strategy Tester");
            }
          Print("Database Dates End at: ",latestdate);
          PrintFormat("Dates after %s will not be available for backtest",TimeToString(latestdate));
         }
    //--- Initialization succeeded.
       return(INIT_SUCCEEDED);
      }

    Die folgende Funktion wird bei jedem neuen Tick ausgeführt.

    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick()
      {
    //--- Run procedures
       Execution();
      }

    In dieser Funktion rufen wir alle Funktionen auf, die den Experten funktionsfähig machen. Nicht jede Funktion muss bei jedem Tick ausgeführt werden, daher rufen wir bestimmte Funktionen nur bei jeder neuen bestimmten Kerze auf, zum Beispiel bei jeder Tageskerze. Dies verbessert die Leistung und reduziert unnötige Funktionsaufrufe und den Verbrauch von Ressourcen.

    //+------------------------------------------------------------------+
    //|Execute program procedures                                        |
    //+------------------------------------------------------------------+
    void Execution()
      {
    //--- Update realtime Graphic every 1 min
       if(CP.NewCandle(1,PERIOD_M1))
         {
          CGraphics.Block_2_Realtime(iSecondsPreEvent);
         }
    //--- function to open trades
       EnterTrade();
    //--- Check if not start-up date
       if(!CTM.DateisToday(Startup_date))
         {
          //--- Run every New Daily Candle
          if(CP.NewCandle(2,PERIOD_D1))
            {
             //--- Check if not in strategy tester
             if(!MQLInfoInteger(MQL_TESTER))
               {
                //--- Update/Create DB in Memory
                NewsObject.CreateEconomicDatabaseMemory();
               }
             CGraphics.GraphicsRefresh(iSecondsPreEvent);//-- Create/Re-create chart objects
             //--- Update Realtime Graphics
             CGraphics.Block_2_Realtime(iSecondsPreEvent);
            }
          //--- Check if not in strategy tester
          if(!MQLInfoInteger(MQL_TESTER))
            {
             //--- Run every New Hourly Candle
             if(CP.NewCandle(3,PERIOD_H1))
               {
                //--- Check if DB in Storage needs an update
                if(NewsObject.UpdateRecords())
                  {
                   //--- initialization procedure outside strategy tester
                   InitNonTester();
                  }
               }
            }
         }
       else
         {
          //--- Run every New Daily Candle
          if(CP.NewCandle(4,PERIOD_D1))
            {
             //--- Update Event objects on chart
             CGraphics.NewsEvent();
            }
         }
      }

    Die nachstehende Funktion ist für die Eröffnung von Handelsgeschäften für Marktaufträge auf der Grundlage der Ereignisauswirkungen und der Ereigniswährung verantwortlich. Wenn die Ereigniswährung gleich der Gewinnwährung ist und der Auswirkungstyp CALENDAR_IMPACT_NEGATIVE ist, eröffnen wir einen Kauf-Position, da wir davon ausgehen, dass die Gewinnwährung während des Nachrichtenereignisses schwächer wird. Wenn die Ereigniswährung gleich der Gewinnwährung ist und der Auswirkungstyp CALENDAR_IMPACT_POSITIVE ist, eröffnen wir einen Verkaufs-Position, da wir davon ausgehen, dass die Gewinnwährung während des Nachrichtenereignisses stärker wird. 

    //+------------------------------------------------------------------+
    //|function to open trades                                           |
    //+------------------------------------------------------------------+
    void EnterTrade()
      {
    //--- static variable for storing upcoming event Impact value
       static ENUM_CALENDAR_EVENT_IMPACT Impact=CALENDAR_IMPACT_NA;
    //--- Check if Upcoming news date has passed and if upcoming news is not null and if new minute candle has formed.
       if(datetime(UpcomingNews.EventDate)<TimeTradeServer()&&UpcomingNews.CountryName!=NULL&&CP.NewCandle(5,PERIOD_M1))
         {
          //--- Update for next upcoming news
          NewsObject.EconomicNextEvent();
          //--- Get impact value for upcoming news
          Impact=NewsObject.GetImpact();
         }
    //--- Check if upcoming news date is about to occur and if it is the trading day of week
       if(CTM.TimePreEvent(CTM.TimeMinusOffset(datetime(UpcomingNews.EventDate),(iSecondsPreEvent==0)?1:iSecondsPreEvent)
                           ,datetime(UpcomingNews.EventDate))
          &&CTM.isDayOfTheWeek(TradingDay))
         {
          //--- Check each Impact value type
          switch(Impact)
            {
             //--- When Impact news is negative
             case CALENDAR_IMPACT_NEGATIVE:
                //--- Check if profit currency is news event currency
                if(UpcomingNews.EventCurrency==CSymbol.CurrencyProfit())
                  {
                   //--- Open buy trade with Event id as Magic number
                   Trade.Buy(iStoploss,iTakeprofit,ulong(UpcomingNews.EventId),"NewsTrading");
                  }
                else
                  {
                   //--- Open sell trade with Event id as Magic number
                   Trade.Sell(iStoploss,iTakeprofit,ulong(UpcomingNews.EventId),"NewsTrading");
                  }
                break;
             //--- When Impact news is positive
             case CALENDAR_IMPACT_POSITIVE:
                //--- Check if profit currency is news event currency
                if(UpcomingNews.EventCurrency==CSymbol.CurrencyProfit())
                  {
                   //--- Open sell trade with Event id as Magic number
                   Trade.Sell(iStoploss,iTakeprofit,ulong(UpcomingNews.EventId),"NewsTrading");
                  }
                else
                  {
                   //--- Open buy trade with Event id as Magic number
                   Trade.Buy(iStoploss,iTakeprofit,ulong(UpcomingNews.EventId),"NewsTrading");
                  }
                break;
             //--- Unknown
             default:
                break;
            }
         }
      }


    Schlussfolgerung

    In diesem Artikel haben wir uns mit dem Hinzufügen einer Datenbank im Speicher und dem Erstellen zusätzlicher Ansichten beschäftigt, um mehr Informationen über die Ereignisse im MQL5-Wirtschaftskalender zu erhalten. Wir haben zusätzliche grafische Objekte auf dem Chart erstellt, um Informationen über das bevorstehende Ereignis anzuzeigen, und eine Dunkelmodusfunktion implementiert. Darüber hinaus haben wir relevante Eingabeoptionen für den Nutzer/Händler hinzugefügt, um die Nachrichtendaten nach seinen Präferenzen zu filtern, sowie Expert Advisor-Eingaben für den Handel. Außerdem wird in dem Artikel erläutert, wie wir Marktaufträge auf der Grundlage der Auswirkungen von Ereignissen eröffnen und wie die Auswirkungen von Ereignissen für unsere Handelsstrategie relevant sind.

    Ich bin offen für Ihre Meinung und freue mich über jeden Meinungsaustausch. Im nächsten Artikel werden wir weitere Funktionen zu den Nachrichteneingaben hinzufügen, um einzelne Wirtschaftsereignisse und den Handel mit schwebenden Aufträgen für mehr Flexibilität zu berücksichtigen, sowie den Handel, der keine Auswirkungen von Ereignissen erfordert. Danke fürs Lesen.



    Video




    Übersetzt aus dem Englischen von MetaQuotes Ltd.
    Originalartikel: https://www.mql5.com/en/articles/15359

    Beigefügte Dateien |
    NewsTrading_Part3.zip (567.27 KB)
    Klassische Strategien neu interpretieren (Teil IV): SP500 und US-Staatsanleihen Klassische Strategien neu interpretieren (Teil IV): SP500 und US-Staatsanleihen
    In dieser Artikelserie analysieren wir klassische Handelsstrategien mit modernen Algorithmen, um festzustellen, ob wir die Strategie mithilfe von KI verbessern können. Im heutigen Artikel greifen wir einen klassischen Ansatz für den Handel mit dem SP500 auf, indem wir seine Beziehung zu den US-Staatsanleihen nutzen.
    Integration von MQL5 in Datenverarbeitungspakete (Teil 2): Maschinelles Lernen und prädiktive Analytik Integration von MQL5 in Datenverarbeitungspakete (Teil 2): Maschinelles Lernen und prädiktive Analytik
    In unserer Serie über die Integration von MQL5 mit Datenverarbeitungspaketen befassen wir uns mit der leistungsstarken Kombination aus maschinellem Lernen und prädiktiver Analyse. Wir werden untersuchen, wie MQL5 nahtlos mit gängigen Bibliotheken für maschinelles Lernen verbunden werden kann, um anspruchsvolle Vorhersagemodelle für Finanzmärkte zu ermöglichen.
    Erstellen eines Handelsadministrator-Panels in MQL5 (Teil I): Aufbau einer Nachrichtenschnittstelle Erstellen eines Handelsadministrator-Panels in MQL5 (Teil I): Aufbau einer Nachrichtenschnittstelle
    Dieser Artikel beschreibt die Erstellung einer Nachrichtenschnittstelle (Messaging Interface) für MetaTrader 5, die sich an Systemadministratoren richtet, um die Kommunikation mit anderen Händlern direkt auf der Plattform zu erleichtern. Jüngste Integrationen von sozialen Plattformen mit MQL5 ermöglichen eine schnelle Signalübertragung über verschiedene Kanäle. Stellen Sie sich vor, Sie könnten gesendete Signale mit nur einem Klick validieren - entweder „JA“ oder „NEIN“ bzw. „YES“ or „NO“. Lesen Sie weiter, um mehr zu erfahren.
    MQL5-Integration: Python MQL5-Integration: Python
    Python ist eine bekannte und beliebte Programmiersprache mit vielen Funktionen, insbesondere in den Bereichen Finanzen, Datenwissenschaft, künstliche Intelligenz und maschinelles Lernen. Python ist ein leistungsfähiges Werkzeug, das auch beim Handel nützlich sein kann. MQL5 ermöglicht es uns, diese leistungsstarke Sprache als Integration zu nutzen, um unsere Ziele effektiv zu erreichen. In diesem Artikel erfahren Sie, wie Sie Python in MQL5 integrieren und verwenden können, nachdem Sie einige grundlegende Informationen über Python gelernt haben.