English Русский Español 日本語
preview
Wie man einen einfachen Multi-Currency Expert Advisor mit MQL5 erstellt (Teil 4): Triangulärer gleitender Durchschnitt — Indikatorensignale

Wie man einen einfachen Multi-Currency Expert Advisor mit MQL5 erstellt (Teil 4): Triangulärer gleitender Durchschnitt — Indikatorensignale

MetaTrader 5Handel | 27 Februar 2024, 10:57
222 5
Roberto Jacobs
Roberto Jacobs

Einführung

Die Definition eines Expert Advisor für mehrere Währungen ( Multi-Currency) in diesem Artikel ist ein Expert Advisor oder Handelsroboter, der mehr als nur ein Symbolpaar von dessen Symbolchart handeln kann (Aufträge öffnen, schließen und verwalten oder zum Beispiel Trailing Stop Loss und Trailing Profit). wobei in diesem Artikel der Expert Advisor 30 Paare handeln wird.

Dieses Mal werden wir nur einen Indikator verwenden, nämlich den Triangulären gleitenden Durchschnitt im Multi-Zeitrahmen- oder Einzelzeitrahmen-Modus.
    In diesem Artikel kann bestimmt werden, ob die Signalberechnungen des Expert Advisor von Multi-Timeframes (von mehreren Zeitrahmen) oder von Single-Timeframes (nur eines Zeitrahmens) durchgeführt werden sollen.

    Der Trianguläre gleitende Durchschnitt ist ein nutzerdefinierter Indikator für MT5 vom Autor Mladen Rakic, und ich habe die Erlaubnis vom Autor erhalten, seinen Indikator als Signal für den Multi-Currency Expert Advisor „TriangularMA_MTF_MCEA“ zu verwenden.
    Gruss und Dank an den Autor Mladen Rakic.

    Wir alle wissen, dass der Handel mit mehreren Währungen, sowohl auf dem Handelsterminal als auch auf dem Strategietester, mit der Leistung, den Fähigkeiten und den Möglichkeiten von MQL5 möglich ist.

    Ziel ist es daher, die wesentlichen Bedürfnisse von Händlern zu erfüllen, die sich effiziente und effektive Handelsroboter wünschen. Indem wir uns auf die Stärken, Fähigkeiten und Möglichkeiten des äußerst zuverlässigen MQL5 verlassen, können wir einen einfachen Expertenberater für mehrere Währungen erstellen, der die Indikatorsignale aus diesem Artikel verwendet: den Triangulären gleitenden Durchschnitt.

    Anmerkung: Die Entwicklung des Multi-Currency Expert Advisors TriangularMA_MTF_MCEA erfolgte auf Anregung und Wunsch von Händlern.


    Pläne und Eigenschaften

    1. Handel mit Währungspaaren.

    Dieser Multi-Currency Expert Advisor ist für den Handel mit einem der folgenden Symbole oder Paare vorgesehen:

    EURUSD,GBPUSD,AUDUSD,NZDUSD,USDCAD,USDCHF,USDJPY,EURGBP,EURAUD, EURNZD, EURCAD, EURCHF, EURJPY, GBPAUD, GBPNZD, GBPCAD,GBPCHF,GBPJPY,AUDNZD,AUDCAD,AUDCHF,AUDJPY,NZDCAD,NZDCHF,NZDJPY, CADCHF, CADJPY, CHFJPY = 28 Paare,

    plus 2 Metallpaare: XAUUSD (Gold) und XAGUSD (Silber).

    Insgesamt sind es 30 Paare.

    Im vorigen Artikel haben wir für Paare von Maklern mit speziellen Namen für die Paare mit Präfixen und/oder Suffixen eine automatische Funktion verwendet, um die Paarnamen mit Präfixen und/oder Suffixen zu erkennen.
    Aber in diesem Artikel machen wir es uns einfach, indem wir spezielle Eingabeeigenschaften für das Präfix und das Suffix des Paar-Namens hinzufügen.
    Dann behandeln wir mit einer einfachen Funktion die Präfix- und/oder Suffix-Paar-Namen in Kombination mit den 30 registrierten Paar-Namen, sodass, wenn ein EA auf MetaTrader5 von einem Broker mit speziellen Symbol-Namen wie diesem verwendet wird, alles reibungslos läuft.

    Der Schwachpunkt der Funktion zur Erkennung von Symbolnamen mit Präfixen und Suffixen ist, dass diese Funktion nur bei Forex- und Metallsymbolpaaren oder -namen im MT5 funktioniert, nicht aber bei speziellen Symbolen und Indizes.
    Eine weitere Schwäche dieser Methode besteht darin, dass sich der Händler bei der Eingabe des Präfixes und/oder Suffixes des Paares vertippen kann (Groß- und Kleinschreibung muss beachtet werden).

    Wie im vorherigen Artikel haben wir auch in diesem Expert Advisor 10 Optionen für die Paare hinzugefügt, die zu diesem Zeitpunkt gehandelt werden sollen.
    Eines der 10 Optionspaare, die gehandelt werden, ist „Trader Wishes Pairs“ (des Händlers Wunschpaare), wobei die Paare, die gehandelt werden sollen, vom Händler manuell über die Experteneingabeeigenschaft eingegeben werden müssen. Sie müssen aber immer daran denken, dass der Name des eingegebenen Paares bereits in der Liste der 30 Paare enthalten sein muss.

    Immer noch das gleiche wie der vorherige Artikel, in dieser Version des Expert Advisor haben wir auch eine Option für Trading Session (Time Zone bzw. Zeitzone), sodass die Paare, die gehandelt werden, die die Zeit für den Handel Sitzung entsprechen kann.


    2. Signalindikator

    In der Beschreibung des Indikators „Triangulärer gleitender Durchschnitt“ stellt der Autor fest:

    „Verwendung:
    Sie können den Farbwechsel als Signal nutzen...“

    Standardmäßig sind die Farben des Indikators „Triangulärer gleitender Durchschnitt“:

    • 0-DarkGray = Unbekanntes Signal
    • 1-DeepPink = Verkaufssignal
    • 2-MediumSeaGreen = Kaufsignal.

    In dieser Version des Expert Advisors haben wir 2 Optionen für die Verwendung von Zeitrahmen bei der Berechnung des Signals des Indikators Triangulärer gleitender Durchschnitt geschaffen.

    1. Signalberechnung auf der Grundlage von multi-timeframe.
    In einem Multi-Timeframe-Berechnungssystem muss der Händler aus einer Enumerationsliste die gewünschten Zeitrahmenserie auswählen.
    Die ausgewählten Zeitreihen reichen von M5 bis D1 (11 Zeitrahmen).
    Händler können zum Beispiel eine Zeitrahmenserie mit dem Beginn bei M15 und dem Ende bei H4.
    Der Expert Advisor berechnet also das Signal des Triangulären gleitenden Durchschnittsindikators ab dem Zeitrahmen M15 bis H4.

    Die Berechnung des Triangulären gleitenden Durchschnitts auf Multi-Timeframes sind:

    • Kaufsignal, wenn der Indikator auf allen ausgewählten Zeitrahmen MediumSeaGreen gefärbt ist, und
    • Verkaufssignal, wenn der Indikator auf allen ausgewählten Zeitrahmen DeepPink gefärbt ist.

    2. Signalberechnung auf der Grundlage eines einzigen Zeitfensters.
    Beim System zur Berechnung der Signale im Single-Timeframe muss der Händler einen von 11 Zeitrahmen auswählen, angefangen beim M5-Zeitrahmen bis hin zum D1-Zeitrahmen.
    Der Expert Advisor berechnet also das Signal des Triangulären gleitenden Durchschnitts für den ausgewählten Zeitrahmen.

    Die Berechnung des Signals des Triangulären gleitenden Durchschnitts auf einem einzigen Zeitrahmen ist indessen:

    • Kaufsignal, wenn die vorherigen 2 Balken DeepPink sind und der vorherige 1 Balken MediumSeaGreen und der aktuelle Balken MediumSeaGreen ist.
    • Verkaufssignal, wenn die vorherigen 2 Balken MediumSeaGreen sind, der vorherige 1 Balken DeepPink ist und der aktuelle Balken DeepPink ist.

    Eine Illustration des Triangulären gleitenden Durchschnitts für ein KAUF- oder VERKAUFssignal ist in Abbildung 1 und Abbildung 2 zu sehen.

    H4_TriangularMA01

      H4_TriangularMA02


      3. Handel und Auftragsverwaltung.

      Das Handelsmanagement dieses Mehr-Währungs-EAs verfügt über mehrere Optionen:

      1. Stop-Loss-Aufträge

      • Optionen: Use Order Stop Loss (Yes) or (No) (Stop-Loss-Auftrag verwenden, Ja oder Nein)

                  Wenn die Option (No) für Use Stop-Loss für Aufträge verwenden ausgewählt ist, werden alle Aufträge ohne Stop-Loss eröffnet.

                  Wenn die Option Use Order Stop Loss (Yes) (Stop-Loss für Aufträge verwenden (Ja)):

                  Dann gibt es die weiteren Optionen: Use Automatic Calculation Stop Loss (Yes) or (No) (Autom. Berechnung des Stop Loss verwenden, Ja oder Nein)

                  Wenn die Option Automatische Berechnung Stop Loss (Ja), dann wird die Stop-Loss-Berechnung automatisch durch den Experten durchgeführt.

                  Wenn die Option Automatische Berechnung des Stop Loss (No) gewählt wurde, muss der Händler den Stop-Loss-Wert in Pips eingeben.

                  Wenn die Option Use Order Stop Loss (No) (Order Stop Loss verwenden (Nein)):

                  Dann prüft der Experte für jeden geöffneten Auftrag, ob die Signalbedingung noch aufrecht ist, sollte ein bereits profitabler Auftrag

                  geschlossen werden, um den Gewinn zu sichern, oder hat sich das Signal abgeschwächt.

                  Die Gewinn- oder Signalbedingung hat sich umgekehrt und der Auftrag muss als Verlust geschlossen werden.

                  Anmerkung:
                  Speziell für Close Trade (Handel schließen) und Save Profit (Gewinn sichern) aufgrund eines schwachen Signals wird eine Option angeboten, ob diese aktiviert werden kann oder nicht.
                  Wenn sie nicht aktiviert ist (Nein), wird der Auftrag trotz des schwächeren Signals aufrechterhalten oder nicht geschlossen, um den Gewinn zu sichern.


      2. Take-Profit-Aufträge

      • Optionen: Use Order Take Profit (Yes) or (No) (Take-Profit verwenden, Ja oder Nein)

                  Wenn die Option Use Order Take Profit (No) ausgewählt ist, werden alle Aufträge ohne ein Take Profit, einem Gewinnziel eröffnet.

                  Bei Verwendung der Option Order Take Profit (Yes):

                  Dann gibt es die weiteren Optionen: Use Automatic Calculation Order Take Profit (Yes) oder (No) (Take-Profit automatisch berechnen, Ja oder Nein).

                  Bei der Option Automatic Calculation Order Take Profit (Yes), dann wird die Berechnung der Take Profit Order automatisch vom Experten durchgeführt.

                  Wenn die Option Automatic Calculation Order Take Profit (No), gewählt wurde, muss der Händler den Order-Take-Profit-Wert in Pips eingeben.


      3. Trailing Stop und Trailing Take-Profit

      • Optionen: Use Trailing SL/TP (Yes) or (No) (Nachlaufende SL/TP verwenden, Ja oder Nein)

                  Wenn die Option Use Trailing SL/TP (No) gewählt wurde, wird der Experte keinen Trailing-Stop-Loss und keinen Trailing-Take-Profit durchführen.

                  Bei der Option Use Trailing SL/TP (Yes):

                  Dann gibt es die weiteren Optionen: Use Automatic Trailing (Yes) oder (No) (Automatisches Nachziehen verwenden, Ja oder Nein).           

                  Bei Verwendung von der Option Use Automatic Trailing (Yes) (Automatisches Trailing verwenden (Ja)) wird der Trailing-Stop vom Experten ausgeführt, indem er 

                  den Triangulären gleitenden Durchschnittspuffer 0 (Indikatordaten) des Zeitrahmens, der automatisch vom Expert Advisor ausgewählt wird, und gleichzeitig

                  durch Erzielung eines Trailing Profits auf der Grundlage des variablen Werts TPmin (kleinster Wert des Trailing Profits).

                  Bei der Option Use Automatic Trailing (No) wird der Trailing-Stop vom Experten anhand des Wertes in der Eingabeeigenschaft ausgeführt.

                  Anmerkung: Der Experte führt einen Trailing-Take-Profit gleichzeitig mit einem Trailing-Stop aus.


      Die Funktion „Trailing Stop Price“:

      double MCEA::TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type)
        {
      //---
          int br=2;
          double pval=0.0;
          int x=PairsIdxArray(xsymb);
          Pips(xsymb);
          //--
          switch(TS_type)
            {
              case 0:
                {
                  RefreshTick(xsymb);
                  if(ptype==POSITION_TYPE_BUY)  pval=mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip);
                  if(ptype==POSITION_TYPE_SELL) pval=mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip);
                  break;
                }
              case 1:
                {
                  double TriMAID[];
                  //--
                  ArrayResize(TriMAID,br,br);
                  ArraySetAsSeries(TriMAID,true);
                  CopyBuffer(hTriMAt[x],0,0,br,TriMAID); // Copy buffer 0 from the hTriMAt indicator handle
                  //--
                  RefreshTick(xsymb);
                  if(ptype==POSITION_TYPE_BUY  && (mc_symbol.Bid()>mc_symbol.NormalizePrice(TriMAID[0]+TSval*pip))) pval=TriMAID[0];
                  if(ptype==POSITION_TYPE_SELL && (mc_symbol.Ask()<mc_symbol.NormalizePrice(TriMAID[0]-TSval*pip))) pval=TriMAID[0];
                  break;
                }
            }
          //--
          return(pval);
      //---
        } //-end TSPrice()
      //---------//


      Modifikation SL/TP-Funktion:

      bool MCEA::ModifySLTP(const string symbx,int TS_type)
        {
      //---
         ResetLastError();
         MqlTradeRequest req={};
         MqlTradeResult  res={};
         MqlTradeCheckResult check={};
         //--
         int TRSP=TS_type;
         bool modist=false;
         int x=PairsIdxArray(symbx);
         Pips(symbx);
         //--
         int total=PositionsTotal();
         //--        
         for(int i=total-1; i>=0; i--) 
           {
             string symbol=PositionGetSymbol(i);
             if(symbol==symbx && mc_position.Magic()==magicEA)
               {
                 ENUM_POSITION_TYPE opstype = mc_position.PositionType();
                 if(opstype==POSITION_TYPE_BUY) 
                   {
                     RefreshTick(symbol);
                     double price = mc_position.PriceCurrent();
                     double vtrsb = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP));
                     double pos_open   = mc_position.PriceOpen();
                     double pos_stop   = mc_position.StopLoss();
                     double pos_profit = mc_position.Profit();
                     double pos_swap   = mc_position.Swap();
                     double pos_comm   = mc_position.Commission();
                     double netp=pos_profit+pos_swap+pos_comm;
                     double modstart=mc_symbol.NormalizePrice(pos_open+TSmin*pip);
                     double modminsl=mc_symbol.NormalizePrice(vtrsb+TSmin*pip);
                     double modbuysl=vtrsb;
                     double modbuytp=mc_symbol.NormalizePrice(price+TPmin*pip);
                     bool modbuy = (price>modminsl && modbuysl>modstart && (pos_stop==0.0||modbuysl>pos_stop));
                     //--
                     if(modbuy && netp>0.05)
                       {
                         modist=mc_trade.PositionModify(symbol,modbuysl,modbuytp);
                       }  
                   }
                 if(opstype==POSITION_TYPE_SELL) 
                   {
                     RefreshTick(symbol);
                     double price = mc_position.PriceCurrent();
                     double vtrss = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP));
                     double pos_open   = mc_position.PriceOpen();
                     double pos_stop   = mc_position.StopLoss();
                     double pos_profit = mc_position.Profit();
                     double pos_swap   = mc_position.Swap();
                     double pos_comm   = mc_position.Commission();
                     double netp=pos_profit+pos_swap+pos_comm;
                     double modstart=mc_symbol.NormalizePrice(pos_open-TSmin*pip);
                     double modminsl=mc_symbol.NormalizePrice(vtrss-TSmin*pip);
                     double modselsl=vtrss;
                     double modseltp=mc_symbol.NormalizePrice(price-TPmin*pip);
                     bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==0.0||modselsl<pos_stop)); 
                     //--
                     if(modsel && netp>0.05)
                       {
                         modist=mc_trade.PositionModify(symbol,modselsl,modseltp);
                       }  
                   }
               }
           }
          //--
          return(modist);
      //---
        } //-end ModifySLTP()
      //---------//


      4. Manuelle Auftragsverwaltung.

      Um die Effizienz in diesem Mehr-Währungs-EA zu unterstützen, werden mehrere manuelle Klick-Buttons hinzugefügt.

      1. Set SL / TP All Orders (Setzen von SL / TP bei allen Aufträgen)

      Wenn der Händler-Eingabeparameter Use Order Stop Loss (No) und/oder Use Order Take Profit (No) einstellt
      aber der Händler beabsichtigt, Stop-Loss oder Take-Profit für alle Aufträge anzuwenden, dann kann er mit einem einzigen Klick auf die Schaltfläche
      „Set SL / TP All Orders“ (SL/TP für alle Aufträge setzen) alle Aufträge ändern und ein Stop-Loss und/oder Take-Profits setzen.

      2. Close All Orders (Alle Aufträge schließen)
      Wenn ein Händler alle Aufträge schließen möchte, dann kann er mit einem einzigen Klick auf die Schaltfläche „Close All Orders“ alle offenen Aufträge schließen.

      3. Close All Orders Profit (Alle Aufträge im Gewinn schließen)
      Wenn ein Händler alle bereits profitabelen Aufträge schließen will, genügt ein einziger Klick auf die Schaltfläche
      "Close All Orders Profit", um sie alle zu schließen.


      5. Management-Befehle und Chartsymbole.

      Für Mehr-Währungs-EAs, die 30 Paare von nur einem Chartsymbol handeln, ist es sehr effektiv und effizient, wenn eine Panel für alle Symbole vorhanden ist, sodass Händler Charts oder Symbole mit nur einem Klick wechseln können.


      Umsetzung der Planung im Programm MQL5

      1. Programm-Header und Eingabeeigenschaften

      Header-Datei MQL5 einbinden:

      //+------------------------------------------------------------------+
      //|                             Include                              |
      //+------------------------------------------------------------------+
      #include <Trade\Trade.mqh>
      #include <Trade\PositionInfo.mqh>
      #include <Trade\SymbolInfo.mqh>
      #include <Trade\AccountInfo.mqh>
      //--
      CTrade              mc_trade;
      CSymbolInfo         mc_symbol;
      CPositionInfo       mc_position; 
      CAccountInfo        mc_account;
      //---


      Die Enumeration zur Verwendung der Zeitzone:

      //--
      enum tm_zone
       {
         Cus_Session,        // Trading on Custom Session
         New_Zealand,        // Trading on New Zealand Session
         Australia,          // Trading on Autralia Sydney Session
         Asia_Tokyo,         // Trading on Asia Tokyo Session
         Europe_London,      // Trading on Europe London Session
         US_New_York         // Trading on US New York Session
       };
      //--


      Die Enumeration zur Auswahl der Zeitstunde:

      //--
      enum swhour
        {
          hr_00=0,   // 00:00
          hr_01=1,   // 01:00
          hr_02=2,   // 02:00
          hr_03=3,   // 03:00
          hr_04=4,   // 04:00
          hr_05=5,   // 05:00
          hr_06=6,   // 06:00
          hr_07=7,   // 07:00
          hr_08=8,   // 08:00
          hr_09=9,   // 09:00
          hr_10=10,  // 10:00
          hr_11=11,  // 11:00
          hr_12=12,  // 12:00
          hr_13=13,  // 13:00
          hr_14=14,  // 14:00
          hr_15=15,  // 15:00
          hr_16=16,  // 16:00
          hr_17=17,  // 17:00
          hr_18=18,  // 18:00
          hr_19=19,  // 19:00
          hr_20=20,  // 20:00
          hr_21=21,  // 21:00
          hr_22=22,  // 22:00
          hr_23=23   // 23:00
        };
      //--


      Die Enumeration zur Auswahl von Zeitminuten:

      //--
      enum inmnt
        {
          mn_00=0,   // Minute 0
          mn_05=5,   // Minute 5
          mn_10=10,  // Minute 10
          mn_15=15,  // Minute 15
          mn_20=20,  // Minute 20
          mn_25=25,  // Minute 25
          mn_30=30,  // Minute 30
          mn_35=35,  // Minute 35
          mn_40=40,  // Minute 40
          mn_45=45,  // Minute 45
          mn_50=50,  // Minute 50
          mn_55=55   // Minute 55
        };
      //--


      Die Enumeration zur Auswahl von Optionspaaren, die gehandelt werden sollen:

      //--
      enum PairsTrade
       {
         All30,  // All Forex 30 Pairs
         TrdWi,  // Trader Wishes Pairs 
         Usds,   // Forex USD Pairs
         Eurs,   // Forex EUR Pairs
         Gbps,   // Forex GBP Pairs
         Auds,   // Forex AUD Pairs
         Nzds,   // Forex NZD Pairs
         Cads,   // Forex CDD Pairs
         Chfs,   // Forex CHF Pairs
         Jpys    // Forex JPY Pairs
       };   
      //--


      Enumeration YN wird für die Optionen (Ja) oder (Nein) in der Experteneingabeeigenschaft verwendet:

      //--
      enum YN
        {
         No,
         Yes
        };
      //--


      Die Enumeration zur Bestimmung der Losgröße:

      //--
      enum mmt
        {
         FixedLot,   // Fixed Lot Size
         DynamLot    // Dynamic Lot Size
        };
      //--


      Die Enumeration zur Auswahl des Zeitrahmens, ob ein Multi-Zeitrahmen oder ein Einzel-Zeitrahmen verwendet wird:

      //--
      enum TFMTF
        {
         TFM5,     // PERIOD_M5
         TFM15,    // PERIOD_M15
         TFM30,    // PERIOD_M30
         TFH1,     // PERIOD_H1
         TFH2,     // PERIOD_H2
         TFH3,     // PERIOD_H3
         TFH4,     // PERIOD_H4
         TFH6,     // PERIOD_H6
         TFH8,     // PERIOD_H8
         TFH12,    // PERIOD_H12
         TFD1      // PERIOD_D1
        };
      //--


      Die Enumeration zur Verwendung von Multi-Timeframe oder Single-Timeframe:

      //--
      enum SMTF
        {
          MTF,   // Use Multi-Timeframe
          STF    // Use Single-Timeframe
        };
      //--


      Eingabeeigenschaften des Experten:

      //---
      input group               "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter
      input SMTF                tfinuse = MTF;              // Select Calculation in Multi or Single Timeframe
      input TFMTF              singletf = TFH1;             // Select Single Calculation TimeFrame, default PERIOD_H1
      input TFMTF               tfstart = TFM15;            // Select Multi Timeframe calculation start 
      input TFMTF               tfclose = TFH4;             // Select Multi Timeframe calculation end
      input int              Trmaperiod = 14;               // Input Triangular MA Indicator period, default 14
      input ENUM_APPLIED_PRICE  Trprice = PRICE_CLOSE;      // Select Triangular MA Applied Price, default Price Close
      //---
      input group               "=== Select Pairs to Trade ===";  // Selected Pairs to trading
      input PairsTrade         usepairs = All30;           // Select Pairs to Use
      input string         traderwishes = "eg. eurusd,usdchf"; // If Use Trader Wishes Pairs, input pair name here, separate by comma
      input string           sym_prefix = "";              // Input the symbol prefix in case sensitive (if any)
      input string           sym_suffix = "";              // Input the symbol suffix in case sensitive (if any)
      //--
      input group               "=== Money Management Lot Size Parameter ==="; // Money Management Lot Size Parameter
      input mmt                  mmlot = DynamLot;         // Money Management Type
      input double                Risk = 10.0;             // Percent Equity Risk per Trade (Min=1.0% / Max=10.0%)
      input double                Lots = 0.01;             // Input Manual Lot Size FixedLot
      //--Trade on Specific Time
      input group               "=== Trade on Specific Time ==="; // Trade on Specific Time
      input YN           trd_time_zone = Yes;              // Select If You Like to Trade on Specific Time Zone
      input tm_zone            session = Cus_Session;      // Select Trading Time Zone
      input swhour            stsescuh = hr_00;            // Time Hour to Start Trading Custom Session (0-23)
      input inmnt             stsescum = mn_15;            // Time Minute to Start Trading Custom Session (0-55)
      input swhour            clsescuh = hr_23;            // Time Hour to Stop Trading Custom Session (0-23)
      input inmnt             clsescum = mn_55;            // Time Minute to Stop Trading Custom Session (0-55)
      //--Day Trading On/Off
      input group               "=== Day Trading On/Off ==="; // Day Trading On/Off
      input YN                    ttd0 = No;               // Select Trading on Sunday (Yes) or (No)
      input YN                    ttd1 = Yes;              // Select Trading on Monday (Yes) or (No)
      input YN                    ttd2 = Yes;              // Select Trading on Tuesday (Yes) or (No)
      input YN                    ttd3 = Yes;              // Select Trading on Wednesday (Yes) or (No)
      input YN                    ttd4 = Yes;              // Select Trading on Thursday (Yes) or (No)
      input YN                    ttd5 = Yes;              // Select Trading on Friday (Yes) or (No)
      input YN                    ttd6 = No;               // Select Trading on Saturday (Yes) or (No)
      //--Trade & Order management Parameter
      input group               "=== Trade & Order management Parameter ==="; // Trade & Order management Parameter
      input YN                  use_sl = No;               // Use Order Stop Loss (Yes) or (No)
      input YN                  autosl = Yes;              // Use Automatic Calculation Stop Loss (Yes) or (No)
      input double               SLval = 30;               // If Not Use Automatic SL - Input SL value in Pips
      input YN                  use_tp = Yes;               // Use Order Take Profit (Yes) or (No)
      input YN                  autotp = Yes;              // Use Automatic Calculation Take Profit (Yes) or (No)
      input double               TPval = 10;               // If Not Use Automatic TP - Input TP value in Pips
      input YN            TrailingSLTP = Yes;              // Use Trailing SL/TP (Yes) or (No)
      input YN                 autotrl = Yes;              // Use Automatic Trailing (Yes) or (No)
      input double               TSval = 5;                // If Not Use Automatic Trailing Input Trailing value in Pips
      input double               TSmin = 5;                // Minimum Pips to start Trailing Stop
      input double               TPmin = 25;               // Input Trailing Profit Value in Pips
      input YN           Close_by_Opps = Yes;              // Close Trade By Opposite Signal (Yes) or (No)
      input YN               SaveOnRev = Yes;              // Close Trade and Save profit due to weak signal (Yes) or (No)
      //--Others Expert Advisor Parameter
      input group               "=== Others Expert Advisor Parameter ==="; // Others EA Parameter
      input YN                  alerts = Yes;              // Display Alerts / Messages (Yes) or (No)
      input YN           UseEmailAlert = No;               // Email Alert (Yes) or (No)
      input YN           UseSendnotify = No;               // Send Notification (Yes) or (No)
      input YN      trade_info_display = Yes;              // Select Display Trading Info on Chart (Yes) or (No)
      input ulong               magicEA = 2023111;          // Expert ID (Magic Number)
      //---


      In der Experten-Eingabeeigenschaftsgruppe „Global Strategy EA Parameter“ müssen die Händler wählen, ob sie die Signalberechnung für mehrere oder nur einem Zeitrahmen verwenden möchten.

      Wenn der Händler einen Single-Timeframe (STF) wählt, muss er den zu verwendenden Zeitrahmen festlegen.
      In der Experten-Eingabeeigenschaft müssen Sie „Select Single Calculation timeframe“ auswählen, Standardwert ist PERIOD_H1.

      Entscheidet sich der Händler für Multi-Timeframe (MTF), so muss er die zu verwendenden Zeitrahmenreihen festlegen.
      In der Experten-Eingabeeigenschaft werden Sie angewiesen, den Beginn der Multi Timeframe-Berechnung und das Ende der Multi Timeframe-Berechnung auszuwählen.

      In den Zeilen 478 bis 518 der Funktion TriangularMA_MTF_MCEA_Config() wird erläutert, wie Multi- und Single-Timeframe zu behandeln sind.

          ENUM_TIMEFRAMES TFs[]={PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
          int arTFs=ArraySize(TFs);
          //--
          for(int x=0; x<arTFs; x++)
            {
              if(singletf==x) TFt=TFs[x]; // TF for single-timeframe
              if(tfstart==x)  arstr=x;    // multi-timeframe start calculation timeframe
              if(tfclose==x)  arend=x;    // multi-timeframe end calculation timeframe
            }
          //--
          if(arstr>=arend)
            {
              Alert("Error selecting Start and End Timeframe, Start Timeframe must be smaller than End Timeframe");
              Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
              ExpertRemove();
            }
          //--
          switch(tfinuse)
            {
              case MTF: 
                {
                  TFArrays=arend-arstr+1;
                  ArrayResize(TFTri,TFArrays,TFArrays);
                  ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY);
                  tfcinws=arstr+1;
                  tftrlst=(int)TFArrays/2;
                  TFts=TFs[tftrlst+arstr-1];   // TF for Trailing Stop
                  TFCWS=TFs[tfcinws];          // TF for Close Order in weak signal
                  break;
                }
              case STF: 
                {
                  TFArrays=arTFs;
                  ArrayResize(TFTri,TFArrays,TFArrays);
                  ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY);
                  tfcinws=TFIndexArray(TFt)-2 <=0 ? 1 : TFIndexArray(TFt)-2;
                  TFts=TFt;            // TF for Trailing Stop
                  TFCWS=TFs[tfcinws];  // TF for Close Order in weak signal
                  break;
                }
            }


      Die Variable ENUM_TIMEFRAMES TFs[] muss mit der Enumerationsoption enum TFMTF verknüpft sein:

      ENUM_TIMEFRAMES TFs[]={PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
      
      //--
      enum TFMTF
        {
         TFM5,     // PERIOD_M5
         TFM15,    // PERIOD_M15
         TFM30,    // PERIOD_M30
         TFH1,     // PERIOD_H1
         TFH2,     // PERIOD_H2
         TFH3,     // PERIOD_H3
         TFH4,     // PERIOD_H4
         TFH6,     // PERIOD_H6
         TFH8,     // PERIOD_H8
         TFH12,    // PERIOD_H12
         TFD1      // PERIOD_D1
        };
      //--


      Dann muss der Händler die Periode des Triangulären MA-Indikators bestimmen, standardmäßig Periode 14.
      Darüber hinaus müssen Händler auch den angewandten Triangulären MA-Preis angeben, standardmäßig PRICE_CLOSE.

      In der Eigenschaftsgruppe „Select Pairs to Trade“ (Zu handelnde Paare auswählen) müssen die Händler das zu handelnde Paar aus den 10 zur Verfügung stehenden Optionen auswählen; standardmäßig ist All Forex 30 Pairs festgelegt.

      Um das zu handelnde Paar zu konfigurieren, rufen wir die Funktion HandlingSymbolArrays() auf.
      Mit der Funktion HandlingSymbolArrays() werden wir alle Paare behandeln, die gehandelt werden sollen.

      void MCEA::HandlingSymbolArrays(void)
        {
      //---
          string All30[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY","EURGBP",
                          "EURAUD","EURNZD","EURCAD","EURCHF","EURJPY","GBPAUD","GBPNZD","GBPCAD",
                          "GBPCHF","GBPJPY","AUDNZD","AUDCAD","AUDCHF","AUDJPY","NZDCAD","NZDCHF",
                          "NZDJPY","CADCHF","CADJPY","CHFJPY","XAUUSD","XAGUSD"}; // 30 pairs
          string USDs[]={"USDCAD","USDCHF","USDJPY","AUDUSD","EURUSD","GBPUSD","NZDUSD","XAUUSD","XAGUSD"}; // USD pairs
          string EURs[]={"EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD","EURUSD"}; // EUR pairs
          string GBPs[]={"GBPAUD","GBPCAD","GBPCHF","EURGBP","GBPJPY","GBPNZD","GBPUSD"}; // GBP pairs
          string AUDs[]={"AUDCAD","AUDCHF","EURAUD","GBPAUD","AUDJPY","AUDNZD","AUDUSD"}; // AUD pairs
          string NZDs[]={"AUDNZD","NZDCAD","NZDCHF","EURNZD","GBPNZD","NZDJPY","NZDUSD"}; // NZD pairs
          string CADs[]={"AUDCAD","CADCHF","EURCAD","GBPCAD","CADJPY","NZDCAD","USDCAD"}; // CAD pairs
          string CHFs[]={"AUDCHF","CADCHF","EURCHF","GBPCHF","NZDCHF","CHFJPY","USDCHF"}; // CHF pairs
          string JPYs[]={"AUDJPY","CADJPY","CHFJPY","EURJPY","GBPJPY","NZDJPY","USDJPY"}; // JPY pairs
          //--
          sall=ArraySize(All30);
          arusd=ArraySize(USDs);
          aretc=ArraySize(EURs);
          ArrayResize(VSym,sall,sall);
          ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY);
          //--
          if(usepairs==TrdWi && StringFind(traderwishes,"eg.",0)<0)
            {
              string to_split=traderwishes; // A string to split into substrings pairs name
              string sep=",";               // A separator as a character 
              ushort u_sep;                 // The code of the separator character 
              //--- Get the separator code 
              u_sep=StringGetCharacter(sep,0);
              //--- Split the string to substrings 
              int p=StringSplit(to_split,u_sep,SPC); 
              if(p>0)
                {
                  for(int i=0; i<p; i++) StringToUpper(SPC[i]);
                  //--
                  for(int i=0; i<p; i++)
                    {
                      if(ValidatePairs(SPC[i])<0) ArrayRemove(SPC,i,1);
                    }
                }
              arspc=ArraySize(SPC);
            }
          //--
          SetSymbolNamePS();      // With this function we will detect whether the Symbol Name has a prefix and/or suffix
          //--
          if(inpre>0 || insuf>0)
            {
              if(usepairs==TrdWi && arspc>0)
                {
                  for(int t=0; t<arspc; t++)
                    {
                      SPC[t]=pre+SPC[t]+suf;
                    }
                }
              //--
              for(int t=0; t<sall; t++)
                {
                  All30[t]=pre+All30[t]+suf;
                }
              for(int t=0; t<arusd; t++)
                {
                  USDs[t]=pre+USDs[t]+suf;
                }
              for(int t=0; t<aretc; t++)
                {
                  EURs[t]=pre+EURs[t]+suf;
                }
              for(int t=0; t<aretc; t++)
                {
                  GBPs[t]=pre+GBPs[t]+suf;
                }
              for(int t=0; t<aretc; t++)
                {
                  AUDs[t]=pre+AUDs[t]+suf;
                }
              for(int t=0; t<aretc; t++)
                {
                  NZDs[t]=pre+NZDs[t]+suf;
                }
              for(int t=0; t<aretc; t++)
                {
                  CADs[t]=pre+CADs[t]+suf;
                }
              for(int t=0; t<aretc; t++)
                {
                  CHFs[t]=pre+CHFs[t]+suf;
                }
              for(int t=0; t<aretc; t++)
                {
                  JPYs[t]=pre+JPYs[t]+suf;
                }
            }
          //--
          ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY);
          ArrayResize(AS30,sall,sall);
          ArrayCopy(AS30,All30,0,0,WHOLE_ARRAY);
          for(int x=0; x<sall; x++) {SymbolSelect(AS30[x],true);}
          if(ValidatePairs(Symbol())>=0) symbfix=true;
          if(!symbfix) 
            {
              Alert("Expert Advisors will not trade on pairs "+Symbol());
              Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
              ExpertRemove();
            }
          //--
          switch(usepairs)
            {
              case 0: // All Forex 30 Pairs
                {
                  ArrayResize(DIRI,sall,sall);
                  arrsymbx=sall;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY);
                  pairs="Multi Currency 30 Pairs";
                  //--
                  break;
                }
              case 1: // Trader wishes pairs
                {
                  ArrayResize(DIRI,arspc,arspc);
                  arrsymbx=arspc;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,SPC,0,0,WHOLE_ARRAY);
                  pairs="("+string(arspc)+") Trader Wishes Pairs";
                  //--
                  break;
                }
              case 2: // USD pairs
                {
                  ArrayResize(DIRI,arusd,arusd);
                  arrsymbx=arusd;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,USDs,0,0,WHOLE_ARRAY);
                  pairs="("+string(arusd)+") Multi Currency USD Pairs";
                  //--
                  break;
                }
              case 3: // EUR pairs
                {
                  ArrayResize(DIRI,aretc,aretc);
                  arrsymbx=aretc;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,EURs,0,0,WHOLE_ARRAY);
                  pairs="("+string(aretc)+") Forex EUR Pairs";
                  //--
                  break;
                }
              case 4: // GBP pairs
                {
                  ArrayResize(DIRI,aretc,aretc);
                  arrsymbx=aretc;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,GBPs,0,0,WHOLE_ARRAY);
                  pairs="("+string(aretc)+") Forex GBP Pairs";
                  //--
                  break;
                }
              case 5: // AUD pairs
                {
                  ArrayResize(DIRI,aretc,aretc);
                  arrsymbx=aretc;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,AUDs,0,0,WHOLE_ARRAY);
                  pairs="("+string(aretc)+") Forex AUD Pairs";
                  //--
                  break;
                }
              case 6: // NZD pairs
                {
                  ArrayResize(DIRI,aretc,aretc);
                  arrsymbx=aretc;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,NZDs,0,0,WHOLE_ARRAY);
                  pairs="("+string(aretc)+") Forex NZD Pairs";
                  //--
                  break;
                }
              case 7: // CAD pairs
                {
                  ArrayResize(DIRI,aretc,aretc);
                  arrsymbx=aretc;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,CADs,0,0,WHOLE_ARRAY);
                  pairs="("+string(aretc)+") Forex CAD Pairs";
                  //--
                  break;
                }
              case 8: // CHF pairs
                {
                  ArrayResize(DIRI,aretc,aretc);
                  arrsymbx=aretc;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,CHFs,0,0,WHOLE_ARRAY);
                  pairs="("+string(aretc)+") Forex CHF Pairs";
                  //--
                  break;
                }
              case 9: // JPY pairs
                {
                  ArrayResize(DIRI,aretc,aretc);
                  arrsymbx=aretc;
                  ArraySymbolResize();
                  ArrayCopy(DIRI,JPYs,0,0,WHOLE_ARRAY);
                  pairs="("+string(aretc)+") Forex JPY Pairs";
                  //--
                  break;
                }
            }
          //--
          return;
      //---
        } //-end HandlingSymbolArrays()
      //---------//


      Innerhalb der Funktion HandlingSymbolArrays() rufen wir die Funktion SetSymbolNamePS() auf.
      Mit der Funktion SetSymbolNamePS() können wir Symbolnamen behandeln, die Präfixe und/oder Suffixe haben.

      void MCEA::SetSymbolNamePS(void)
        {
      //---
         symbfix=false;
         int ptriml;
         int ptrimr;
         string insymbol=Symbol();
         int sym_Lenpre=StringLen(prefix);
         int sym_Lensuf=StringLen(suffix);
         if(sym_Lenpre>0)
           {
             ptriml=StringTrimLeft(suffix);
             ptriml=StringTrimRight(suffix);
           }
         if(sym_Lensuf>0)
           {
             ptrimr=StringTrimLeft(suffix);
             ptrimr=StringTrimRight(suffix);
           }
         string sym_pre=prefix;
         string sym_suf=suffix;
         //--
         pre=sym_pre;
         suf=sym_suf;
         inpre=StringLen(pre);
         insuf=StringLen(suf);
         posCur1=inpre;
         posCur2=posCur1+3;
         //--
         return;
      //---
        } //-end SetSymbolNamePS()
      //---------//

      Anmerkung:
      Der Experte wird die Paare überprüfen.
      Wenn der Händler einen Fehler bei der Eingabe des Paar-Namens oder des Paar-Präfix-Namens und/oder des Paar-Suffix-Namens macht (Tippfehler) oder
      wenn die Paarvalidierung fehlschlägt, gibt der Experte eine Warnung aus und der Expertenberater wird vom Chart entfernt.


      In der Experten-Eingabeeigenschaftsgruppe Trade on Specific Time (Handel zu einer bestimmten Zeit) kann der Händler wählen, ob er in einer bestimmten Zeitzone handeln möchte (Ja) oder (Nein).
      und Wenn Ja, wählen Sie die Enumerationsoptionen:

      • Handel während einer nutzerdefinierten Sitzung (Custom Session)
      • Handel während der neuseeländischen Sitzung
      • Handel während der Australien Sydney Session
      • Handel während der Asien Tokyo Session
      • Handel während der Europa London Session
      • Handel während der Amerika New York Session

      Handel während der Custom Session: In dieser Sitzung müssen die Händler die Zeit oder Stunden und Minuten für den Handelsbeginn und die Stunden und Minuten für den Handelsschluss festlegen.

      Der EA wird also nur während der angegebenen Zeit von Anfang bis Ende Aktivitäten durchführen.

      Beim Handel an der New Zealand Session bis zum Handel an der US New York Session wird die Zeit vom Handelsbeginn bis zum Handelsschluss vom EA berechnet.


      Um alle Variablen, Objekte und Funktionen zu deklarieren, die in diesem Mehr-Währungs-EA benötigt werden, werden wir eine Klasse erstellen, um den Aufbau und die Konfiguration im Expert Advisor Workflow zu spezifizieren.

      Insbesondere die Variablen, die in der Funktion für die Handhabung von Präfix-Symbolnamen und/oder Suffix-Symbolnamen sowie für die Zeitzonenberechnung verwendet werden, haben wir in der MCEA-Klasse erstellt.

      //+------------------------------------------------------------------+
      //| Class for working Expert Advisor                                 |
      //+------------------------------------------------------------------+
      class MCEA
        {
      //---
          private:
          //---- 
          int              x_year;       // Year 
          int              x_mon;        // Month 
          int              x_day;        // Day of the month 
          int              x_hour;       // Hour in a day 
          int              x_min;        // Minutes 
          int              x_sec;        // Seconds
          //--
          int              oBm,
                           oSm,
                           ldig;
          //--- Variables used in prefix and suffix symbols
          int              posCur1,
                           posCur2;
          int              inpre,
                           insuf;
          bool             symbfix;
          string           pre,suf;
          string           prefix,suffix;       
          //--- Variables are used in Trading Time Zone
          int              ishour,
                           onhour;
          int              tftrlst,
                           tfcinws;
          datetime         rem,
                           znop,
                           zncl,
                           zntm;
          datetime         SesCuOp,
                           SesCuCl,
                           Ses01Op,
                           Ses01Cl,
                           Ses02Op,
                           Ses02Cl,
                           Ses03Op,
                           Ses03Cl,
                           Ses04Op,
                           Ses04Cl,
                           Ses05Op,
                           Ses05Cl,
                           SesNoOp,
                           SesNoCl;
          //--
          string           tz_ses,
                           tz_opn,
                           tz_cls;
          //--
          string           tmopcu,
                           tmclcu,
                           tmop01,
                           tmcl01,
                           tmop02,
                           tmcl02,
                           tmop03,
                           tmcl03,
                           tmop04,
                           tmcl04,
                           tmop05,
                           tmcl05,
                           tmopno,
                           tmclno;      
          //----------------------    
          //--
          double           LotPS;
          double           slv,
                           tpv,
                           pip,
                           xpip;              
          double           floatprofit,
                           fixclprofit;
          //--
          string           pairs,
                           hariini,
                           daytrade,
                           trade_mode;
          //--
          double           OPEN[],
                           HIGH[],
                           LOW[],
                           CLOSE[];
          datetime         TIME[];
          datetime         closetime;
          //--
          //------------
           
          //------------
          void             SetSymbolNamePS(void);
          void             HandlingSymbolArrays(void);
          void             Set_Time_Zone(void);
          void             Time_Zone(void);
          bool             Trade_session(void);
          string           PosTimeZone(void);
          int              ThisTime(const int reqmode);
          int              ReqTime(datetime reqtime,const int reqmode);
          //--
          int              DirectionMove(const string symbol,const ENUM_TIMEFRAMES stf);
          int              TriaMASMTF(const string symbol,ENUM_TIMEFRAMES mtf);
          int              GetTriaMASignalMTF(string symbol);
          int              TriaMASignalSTF(const string symbol);
          int              LotDig(const string symbol);
          //--
          double           MLots(const string symbx);
          double           NonZeroDiv(double val1,double val2);
          double           OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
          double           OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
          double           SetOrderSL(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
          double           SetOrderTP(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
          double           TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type);
          //--
          string           ReqDate(int d,int h,int m);
          string           TF2Str(ENUM_TIMEFRAMES period);
          string           timehr(int hr,int mn);
          string           TradingDay(void);
          string           AccountMode();
          string           GetCommentForOrder(void)             { return(expname); }
          //------------
      
          public:
          //---
          
          //-- TriangularMA_MTF_MCEA Config --
          string           DIRI[],
                           AS30[],
                           VSym[];
          string           SPC[];
          string           USD[];
          string           EUR[];
          string           GBP[];
          string           AUD[];
          string           NZD[];
          string           CAD[];
          string           CHF[];
          string           JPY[];             
          //--                 
          string           expname;
          string           indiname;
          //--
          int              hTriMAt[];
          int              hTriMAs[];
          int              hTriMAm[];
          int              hTriMAb[][11];
          int              ALO,
                           dgts,
                           arrsar,
                           arrsymbx;
          int              sall,
                           arusd,
                           aretc,
                           arspc,
                           arper;
          ulong            slip;        
          //--
          double           profitb[],
                           profits[];
          //--
          int              Buy,
                           Sell;
          int              ccur,
                           psec,
                           xtto,
                           TFArrays,
                           checktml;
          int              OpOr[],xob[],xos[];         
          //--
          int              year,  // Year 
                           mon,   // Month 
                           day,   // Day 
                           hour,  // Hour 
                           min,   // Minutes 
                           sec,   // Seconds 
                           dow,   // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) 
                           doy;   // Day number of the year (January 1st is assigned the number value of zero)
          //--
          ENUM_TIMEFRAMES  TFt,
                           TFts,
                           TFT05,
                           TFCWS;
          ENUM_TIMEFRAMES  TFTri[];
          //--
          bool             PanelExtra;
          //------------
                           MCEA(void);
                           ~MCEA(void);            
          //------------
          //--
          virtual void     TriangularMA_MTF_MCEA_Config(void);
          virtual void     ExpertActionTrade(void);
          //--
          void             ArraySymbolResize(void);
          void             CurrentSymbolSet(const string symbol);
          void             Pips(const string symbol);
          void             TradeInfo(void);
          void             Do_Alerts(const string symbx,string msgText);
          void             CheckOpenPMx(const string symbx);
          void             SetSLTPOrders(void);
          void             CloseBuyPositions(const string symbol);
          void             CloseSellPositions(const string symbol);
          void             CloseAllOrders(void);
          void             CheckClose(const string symbx);
          void             TodayOrders(void);
          void             UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf);
          void             RefreshPrice(const string symbx,ENUM_TIMEFRAMES xtf,int bars);
          //--
          bool             RefreshTick(const string symbx);  
          bool             TradingToday(void);
          bool             OpenBuy(const string symbol);
          bool             OpenSell(const string symbol);
          bool             ModifyOrderSLTP(double mStop,double ordtp);
          bool             ModifySLTP(const string symbx,int TS_type);          
          bool             CloseAllProfit(void);
          bool             ManualCloseAllProfit(void);
          //--
          int              PairsIdxArray(const string symbol);
          int              ValidatePairs(const string symbol);
          int              TFIndexArray(ENUM_TIMEFRAMES TF);
          int              GetOpenPosition(const string symbol);
          int              GetSignalMidTF(const string symbol);
          int              GetCloseInWeakSignal(const string symbol,int exis);
          //--
          string           getUninitReasonText(int reasonCode);
          //--
          //------------
      //---
        }; //-end class MCEA
      //---------//


      Die allererste und wichtigste Funktion im Arbeitsprozess des Multi-Currency Expert Advisors, die von OnInit() aufgerufen wird, ist TriangularMA_MTF_MCEA_Config().

      In der Funktion TriangularMA_MTF_MCEA_Config() werden alle zu verwendenden Symbole, alle verwendeten Handle-Indikatoren und einige wichtige Funktionen des Include-Dateikopfes für den Expert Advisor Workflow konfiguriert.

      void MCEA::TriangularMA_MTF_MCEA_Config(void) 
        {
      //---
          //--
          HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded
          //--
          int arstr=0,
              arend=0;
          TFT05=PERIOD_M5;
          ENUM_TIMEFRAMES TFs[]={PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
          int arTFs=ArraySize(TFs);
          //--
          for(int x=0; x<arTFs; x++)
            {
              if(singletf==x) TFt=TFs[x]; // TF for single-timeframe
              if(tfstart==x)  arstr=x;    // multi-timeframe start calculation timeframe
              if(tfclose==x)  arend=x;    // multi-timeframe end calculation timeframe
            }
          //--
          if(arstr>=arend)
            {
              Alert("Error selecting Start and End Timeframe, Start Timeframe must be smaller than End Timeframe");
              Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
              ExpertRemove();
            }
          //--
          switch(tfinuse)
            {
              case MTF: 
                {
                  TFArrays=arend-arstr+1;
                  ArrayResize(TFTri,TFArrays,TFArrays);
                  ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY);
                  tfcinws=arstr+1;
                  tftrlst=(int)TFArrays/2;
                  TFts=TFs[tftrlst+arstr-1];   // TF for Trailing Stop
                  TFCWS=TFs[tfcinws];          // TF for Close Order in weak signal
                  break;
                }
              case STF: 
                {
                  TFArrays=arTFs;
                  ArrayResize(TFTri,TFArrays,TFArrays);
                  ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY);
                  tfcinws=TFIndexArray(TFt)-2 <=0 ? 1 : TFIndexArray(TFt)-2;
                  TFts=TFt;            // TF for Trailing Stop
                  TFCWS=TFs[tfcinws];  // TF for Close Order in weak signal
                  break;
                }
            }
          //--
          //-- Triangular MA Indicators handle for all symbol
          for(int x=0; x<arrsymbx; x++) 
            {
              hTriMAs[x]=iCustom(DIRI[x],TFT05,indiname,Trmaperiod,Trprice);
              hTriMAm[x]=iCustom(DIRI[x],TFCWS,indiname,Trmaperiod,Trprice);
              hTriMAt[x]=iCustom(DIRI[x],TFts,indiname,Trmaperiod,Trprice);
              //--
              for(int i=0; i<TFArrays; i++)
                {
                  if(tfinuse==MTF) // MTF indicator handle
                    {
                      hTriMAb[x][i]=iCustom(DIRI[x],TFTri[i],indiname,Trmaperiod,Trprice);
                    }
                  if(tfinuse==STF)
                    {
                      if(TFs[i]==TFt) // Single-TF indicator handle
                        {
                          hTriMAb[x][i]=iCustom(DIRI[x],TFs[i],indiname,Trmaperiod,Trprice);
                          break;
                        }
                    }
                }
            }
          //--
          ALO=(int)mc_account.LimitOrders()>sall ? sall : (int)mc_account.LimitOrders();
          //--
          LotPS=(double)ALO;
          //--
          mc_trade.SetExpertMagicNumber(magicEA);
          mc_trade.SetDeviationInPoints(slip);
          mc_trade.SetMarginMode();
          Set_Time_Zone();
          //--
          return;
      //---
        } //-end TriangularMA_MTF_MCEA_Config()
      //---------//


      2. Die OnTick-Funktion des Experten

      Innerhalb der Funktion OnTick() des EAs werden wir eine der Hauptfunktionen in einem Mehr-Währungs-EA aufrufen, nämlich die Funktion ExpertActionTrade().

      //+------------------------------------------------------------------+
      //| Expert tick function                                             |
      //+------------------------------------------------------------------+
      void OnTick(void)
        {
      //---
          mc.ExpertActionTrade();
          //--
          return;
      //---
        } //-end OnTick()
      //---------//


      Der Ablauf des EA-Arbeitsprozesses innerhalb dieser Funktion.

      Die Funktion ExpertActionTrade() führt alle Aktivitäten durch und verwaltet den automatischen Handel, angefangen bei Positionen eröffnen und schließen (Open Orders, Close Orders), Trailing-Stop oder Trading-Profits und anderen zusätzlichen Aktivitäten.

      void MCEA::ExpertActionTrade(void)
        {
      //---
          //--Check Trading Terminal
          ResetLastError();
          //--
          if(!MQLInfoInteger(MQL_TRADE_ALLOWED) && mc.checktml==0) //-- Check whether MT5 Algorithmic trading is Allow or Prohibit
            {
              mc.Do_Alerts(Symbol(),"Trading Expert at "+Symbol()+" are NOT Allowed by Setting.");
              mc.checktml=1;  //-- Variable checktml is given a value of 1, so that the alert is only done once.
              return;
            }
          //--
          if(!DisplayManualButton("M","C","R")) DisplayManualButton(); //-- Show the expert manual button panel
          //--
          if(trade_info_display==Yes) mc.TradeInfo(); //-- Displayed Trading Info on Chart
          //---
          //--
          int mcsec=mc.ThisTime(mc.sec); 
          //--
          if(fmod((double)mcsec,5.0)==0) mc.ccur=mcsec;
          //--
          if(mc.ccur!=mc.psec)
            {
              string symbol;
              //-- Here we start with the rotation of the name of all symbol or pairs to be traded
              for(int x=0; x<mc.arrsymbx && !IsStopped(); x++) 
                {
                  //-- 
                  if(mc.DIRI[x]==Symbol()) symbol=Symbol();
                  else symbol=mc.DIRI[x];
                  //--
                  mc.CurrentSymbolSet(symbol);
                  //--
                  if(mc.TradingToday() && mc.Trade_session())
                    {
                      //--
                      mc.OpOr[x]=mc.GetOpenPosition(symbol); //-- Get trading signals to open positions
                      //--                                   //-- and store in the variable OpOr[x]
                      if(mc.OpOr[x]==mc.Buy) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Buy" (value=1)
                        {
                          //--
                          mc.CheckOpenPMx(symbol);
                          //--
                          if(Close_by_Opps==Yes && mc.xos[x]>0) mc.CloseSellPositions(symbol);
                          //--
                          if(mc.xob[x]==0 && mc.xtto<mc.ALO) mc.OpenBuy(symbol);
                          else
                          if(mc.xtto>=mc.ALO)
                            {
                              //--
                              mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+
                                                  "\n the limit = "+string(mc.ALO)+" Orders ");
                              //--
                              mc.CheckOpenPMx(symbol);
                              //--
                              if(mc.xos[x]>0 && mc.profits[x]<-1.02 && mc.xob[x]==0) {mc.CloseSellPositions(symbol); mc.OpenBuy(symbol);}
                              else
                              if(SaveOnRev==Yes) mc.CloseAllProfit();
                            }
                        }
                      if(mc.OpOr[x]==mc.Sell) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Sell" (value=-1)
                        {
                          //--
                          mc.CheckOpenPMx(symbol);
                          //--
                          if(Close_by_Opps==Yes && mc.xob[x]>0) mc.CloseBuyPositions(symbol);
                          //--
                          if(mc.xos[x]==0 && mc.xtto<mc.ALO) mc.OpenSell(symbol);
                          else
                          if(mc.xtto>=mc.ALO)
                            {
                              //--
                              mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+
                                                  "\n the limit = "+string(mc.ALO)+" Orders ");
                              //--
                              mc.CheckOpenPMx(symbol);
                              //--
                              if(mc.xob[x]>0 && mc.profitb[x]<-1.02 && mc.xos[x]==0) {mc.CloseBuyPositions(symbol); mc.OpenSell(symbol);}
                              else
                              if(SaveOnRev==Yes) mc.CloseAllProfit();
                            }
                        }
                    }
                  //--
                  mc.CheckOpenPMx(symbol);
                  //--
                  if(mc.xtto>0)
                    {
                      //--
                      if(SaveOnRev==Yes) //-- Close Trade and Save profit due to weak signal (Yes)
                        {
                          mc.CheckOpenPMx(symbol);
                          if(mc.profitb[x]>0.02 && mc.xob[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Buy)==mc.Sell) 
                            {
                              mc.CloseBuyPositions(symbol); 
                              mc.Do_Alerts(symbol,"Close BUY order "+symbol+" to save profit due to weak signal.");
                            }
                          if(mc.profits[x]>0.02 && mc.xos[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Sell)==mc.Buy)
                            {
                              mc.CloseSellPositions(symbol); 
                              mc.Do_Alerts(symbol,"Close SELL order "+symbol+" to save profit due to weak signal.");
                            }
                        }
                      //--
                      if(TrailingSLTP==Yes) //-- Use Trailing SL/TP (Yes)
                        {
                          if(autotrl==Yes) mc.ModifySLTP(symbol,1); //-- If Use Automatic Trailing (Yes)
                          if(autotrl==No)  mc.ModifySLTP(symbol,0); //-- Use Automatic Trailing (No)
                        }
                    }
                  //--
                  mc.CheckClose(symbol);
                }
              //--
              mc.psec=mc.ccur;
            }
          //--
          return;
      //---
        } //-end ExpertActionTrade()
      //---------//


      Speziell für den Zeitzonenhandel wurde in der Funktion ExpertActionTrade() ein Aufruf der booleschen Funktion Trade_session() hinzugefügt.
      Wenn Trade_session() true ist, dann wird der EA-Arbeitsprozess fortgesetzt, bis er beendet ist, aber wenn er false ist, dann führt der EA nur die Aufgaben „Close Trade and Save profit due to weak signal (Yes)“ and „Trailing Stop (Yes)“. (Positionen schließen und Gewinn sichern aufgrund eines schwachen Signals (Ja) und Trailing-Stop (Ja)) aus.

      bool MCEA::Trade_session(void)
        {
      //---
         bool trd_ses=false;
         ishour=ThisTime(hour);
         if(ishour!=onhour) Set_Time_Zone();
         datetime tcurr=TimeCurrent(); // Server Time
         //--
         switch(session)
           {
             case Cus_Session:
               {
                 if(tcurr>=SesCuOp && tcurr<=SesCuCl) trd_ses=true;
                 break;
               }
             case New_Zealand:
               {
                 if(tcurr>=Ses01Op && tcurr<=Ses01Cl) trd_ses=true;
                 break;
               }
             case Australia:
               {
                 if(tcurr>=Ses02Op && tcurr<=Ses02Cl) trd_ses=true;
                 break;
               }
             case Asia_Tokyo:
               {
                 if(tcurr>=Ses03Op && tcurr<=Ses03Cl) trd_ses=true;
                 break;
               }
             case Europe_London:
               {
                 if(tcurr>=Ses04Op && tcurr<=Ses04Cl) trd_ses=true;
                 break;
               }
             case US_New_York:
               {
                 if(tcurr>=Ses05Op && tcurr<=Ses05Cl) trd_ses=true;
                 break;
               }
           }
         //--
         if(trd_time_zone==No) 
           {
            if(tcurr>=SesNoOp && tcurr<=SesNoCl) trd_ses=true;
           }
         //--
         onhour=ishour;
         //--
         return(trd_ses);
      //---  
        } //-end Trade_session()
      //---------//


      3. Wie kann ich Handelssignale für offene Positionen erhalten?

      Um ein Signal zu erhalten, ruft die Funktion ExpertActionTrade() die Funktion GetOpenPosition() auf.

      int MCEA::GetOpenPosition(const string symbol) // Signal Open Position 
        {
      //---
          int ret=0;
          int rise=1,
              down=-1;
          //--
          int trimOp=GetTriaMASignalMTF(symbol);
          int getmid=GetSignalMidTF(symbol);
          if(trimOp==rise && getmid==rise) ret=rise;
          if(trimOp==down && getmid==down) ret=down;
          //--
          return(ret);
      //---
        } //-end GetOpenPosition()
      //---------//


      Die Funktion GetOpenPosition() ruft 2 Funktionen auf, die Signalberechnungen durchführen:

      1. GetSignalMidTF(const string symbol); //-- Funktion zum Abrufen von Signalen auf dem mittleren Zeitrahmen und Preisbewegungspositionen:

      int MCEA::GetSignalMidTF(const string symbol) // Signal Indicator Position Close in profit
        {
      //---
          int ret=0;
          int rise=1,
              down=-1;
          //--
          int br=2;
          //--
          double TriMACI[];
          //--
          ArrayResize(TriMACI,br,br);
          ArraySetAsSeries(TriMACI,true);
          int xx=PairsIdxArray(symbol);
          CopyBuffer(hTriMAm[xx],1,0,br,TriMACI);
          //#property indicator_color1  clrDarkGray,clrDeepPink,clrMediumSeaGreen
          //                                 0          1             2
          //--
          int dirmove=DirectionMove(symbol,TFCWS);
          //--
          if(TriMACI[0]==2.0 && dirmove==rise) ret=rise;
          if(TriMACI[0]==1.0 && dirmove==down) ret=down;
          //--
          return(ret);
      //---
        } //-end GetSignalMidTF()
      //---------//


      2. GetTriaMASignalMTF(const string symbol); //-- Funktion zur Berechnung der Formel des Triangulären gleitenden Durchschnitts.

      Die Funktion GetTriaMASignalMTF() ruft eine Funktion TriaMASMTF() auf, die das Signal des Triangulären gleitenden Durchschnitts entsprechend dem gewünschten Zeitrahmen berechnet:

      int MCEA::GetTriaMASignalMTF(string symbol)
        {
      //---
          int mv=0;
          int rise=1,
              down=-1;
          int tfloop=tfinuse==MTF ? TFArrays : 1;
          //--
          int trimup=0,
              trimdw=0;
          //--    
          for(int x=0; x<tfloop; x++)
            {
              if(TriaMASMTF(symbol,TFTri[x])>0) trimup++;
              if(TriaMASMTF(symbol,TFTri[x])<0) trimdw++;
            }   
          //--
          if(trimup==tfloop) mv=rise;
          if(trimdw==tfloop) mv=down;
          //--
          return(mv);
      //---
        } //- end GetTriaMASignalMTF()
      //---------//


      int MCEA::TriaMASMTF(const string symbol,const ENUM_TIMEFRAMES mtf) // formula Triangular MA on the requested Timeframe
        {
      //---
          int ret=0;
          int rise=1,
              down=-1;
          int br=3;
          ENUM_TIMEFRAMES TFUse=tfinuse==MTF ? mtf : TFt;
          //--
          double TriMACI[];
          ArrayResize(TriMACI,br,br);
          ArraySetAsSeries(TriMACI,true);
          int xx=PairsIdxArray(symbol);
          int tx=TFIndexArray(TFUse);
          CopyBuffer(hTriMAb[xx][tx],1,0,br,TriMACI);
          //#property indicator_color1  clrDarkGray,clrDeepPink,clrMediumSeaGreen
          //                                 0          1             2
          //Print("Symbol = "+symbol+" TF = "+EnumToString(mtf)+" TriMACI[0] = "+string(TriMACI[0]));
          //--
          switch(tfinuse)
            {
              case MTF:
                {
                  if(TriMACI[0]==2.0) ret=rise;
                  if(TriMACI[0]==1.0) ret=down;
                  //--
                  break;
                }
              case STF:
                {
                  if(TriMACI[2]==1.0 && TriMACI[1]==2.0 && TriMACI[0]==2.0) ret=rise;
                  if(TriMACI[2]==2.0 && TriMACI[1]==1.0 && TriMACI[0]==1.0) ret=down;
                  //--
                  break;
                }
            }
          //--
          return(ret);
      //---
        } //-end TriaMASMTF()
      //---------//


      Wie Sie sehen können, werden innerhalb der Funktion TriaMASMTF() 2 Funktionen verwendet und aufgerufen:

      • 1. int xx= PairsIdxArray(symbol)
      • 2. int tx=TFIndexArray(mtf).

      Die Funktion PairsIdxArray() wird verwendet, um den Namen des angeforderten Symbols zu erhalten, und die Funktion TFIndexArray() wird verwendet, um die Zeitrahmen-Array-Sequenz des angeforderten Zeitrahmens zu erhalten.
      Dann wird das entsprechende Indikator-Handle aufgerufen, um den Pufferwert des Triangulären gleitenden Durchschnittssignals aus diesem Zeitrahmen zu erhalten.

      Wie der Autor des Indikators „Triangulärer gleitender Durchschnitt“ sagt:
      „Verwendung:
      Sie können den Farbwechsel als Signal nutzen...“

      Wie soll das Signal des Triangulären gleitenden Durchschnitts beurteilte werden?

      In der Eigenschaft des Indikators Triangulärer gleitender Durchschnitt:

      #property indicator_color1  clrDarkGray,clrDeepPink,clrMediumSeaGreen
      //                               0            1             2
      SetIndexBuffer(1,valc,INDICATOR_COLOR_INDEX);
      valc[i] = (i>0) ?(val[i]>val[i-1]) ? 2 :(val[i]<val[i-1]) ? 1 : valc[i-1]: 0;


      Das wissen wir also:

      • 0-DarkGray = Unbekanntes Signal
      • 1-DeepPink = Verkaufssignal
      • 2-MediumSeaGreen = Kaufsignal.

      Wir können also den Wert des Puffers 1 des Indikators „Triangulärer gleitender Durchschnitt“ als Signal verwenden, indem wir die Funktion CopyBuffer wie in der Funktion TriaMASMTF() verwenden.

          double TriMACI[];
          ArrayResize(TriMACI,br,br);
          ArraySetAsSeries(TriMACI,true);
          int xx=PairsIdxArray(symbol);
          int tx=TFIndexArray(TFUse);
          CopyBuffer(hTriMAb[xx][tx],1,0,br,TriMACI);
          //#property indicator_color1  clrDarkGray,clrDeepPink,clrMediumSeaGreen
          //                                 0           1             2
      


      4. Die Funktion ChartEvent

      Um die Effektivität und Effizienz bei der Verwendung von Multi-Currency Expert Advisors zu unterstützen, wird es als notwendig erachtet, mehrere manuelle Schaltflächen für die Verwaltung von Aufträgen einzurichten
      und dem Wechseln zwischen den Charts oder den Symbolen.

      //+------------------------------------------------------------------+
      //| ChartEvent function                                              |
      //+------------------------------------------------------------------+
      void OnChartEvent(const int id,
                        const long &lparam,
                        const double &dparam,
                        const string &sparam)
        {
      //---
      //--- handling CHARTEVENT_CLICK event ("Clicking the chart")
         ResetLastError();
         //--
         ENUM_TIMEFRAMES CCS=mc.TFt;
         //--
         if(id==CHARTEVENT_OBJECT_CLICK) 
           {
             int lensymbol=StringLen(Symbol());
             int lensparam=StringLen(sparam);
             //--
             //--- if "Set SL All Orders" button is click
             if(sparam=="Set SL/TP All Orders") 
               { 
                 mc.SetSLTPOrders();
                 Alert("-- "+mc.expname+" -- ",Symbol()," -- Set SL/TP All Orders");
                 //--- unpress the button 
                 ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_STATE,false);
                 ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_ZORDER,0);
                 CreateManualPanel();
               }
             //--- if "Close All Order" button is click
             if(sparam=="Close All Order") 
               { 
                 mc.CloseAllOrders();
                 Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Orders");
                 //--- unpress the button 
                 ObjectSetInteger(0,"Close All Order",OBJPROP_STATE,false);
                 ObjectSetInteger(0,"Close All Order",OBJPROP_ZORDER,0);
                 CreateManualPanel();
               }
             //--- if "Close All Profit" button is click
             if(sparam=="Close All Profit") 
               { 
                 mc.ManualCloseAllProfit();
                 Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Profit");
                 //--- unpress the button 
                 ObjectSetInteger(0,"Close All Profit",OBJPROP_STATE,false);
                 ObjectSetInteger(0,"Close All Profit",OBJPROP_ZORDER,0);
                 CreateManualPanel();
               }
             //--- if "X" button is click
             if(sparam=="X") 
               { 
                 ObjectsDeleteAll(0,0,OBJ_BUTTON);
                 ObjectsDeleteAll(0,0,OBJ_LABEL);
                 ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
                 //--- unpress the button 
                 ObjectSetInteger(0,"X",OBJPROP_STATE,false);
                 ObjectSetInteger(0,"X",OBJPROP_ZORDER,0);
                 //--
                 DeleteButtonX();
                 mc.PanelExtra=false;
                 DisplayManualButton();
               }
             //--- if "M" button is click
             if(sparam=="M") 
               { 
                 //--- unpress the button 
                 ObjectSetInteger(0,"M",OBJPROP_STATE,false);
                 ObjectSetInteger(0,"M",OBJPROP_ZORDER,0);
                 mc.PanelExtra=true;
                 CreateManualPanel();
               }
             //--- if "C" button is click
             if(sparam=="C") 
               { 
                 //--- unpress the button 
                 ObjectSetInteger(0,"C",OBJPROP_STATE,false);
                 ObjectSetInteger(0,"C",OBJPROP_ZORDER,0);
                 mc.PanelExtra=true;
                 CreateSymbolPanel();
               }
             //--- if "R" button is click
             if(sparam=="R") 
               { 
                 Alert("-- "+mc.expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
                 ExpertRemove();
                 //--- unpress the button 
                 ObjectSetInteger(0,"R",OBJPROP_STATE,false);
                 ObjectSetInteger(0,"R",OBJPROP_ZORDER,0);
                 if(!ChartSetSymbolPeriod(0,Symbol(),Period()))
                   ChartSetSymbolPeriod(0,Symbol(),Period());
                 DeletePanelButton();
                 ChartRedraw(0);
               }
             //--- if Symbol button is click
             if(lensparam==lensymbol)
               {
                 int sx=mc.ValidatePairs(sparam);
                 ChangeChartSymbol(mc.AS30[sx],CCS);
                 mc.PanelExtra=false;
               }
             //--
           }
          //--
          return;
      //---
        } //-end OnChartEvent()
      //---------//


      Um die Chartsymbole mit einem Klick zu ändern, wird der Befehl OnChartEvent() ChangeChartSymbol() aufgerufen, wenn einer der Symbolnamen angeklickt wird:

      void ChangeChartSymbol(string c_symbol,ENUM_TIMEFRAMES cstf)
        {
      //---
         //--- unpress the button 
         ObjectSetInteger(0,c_symbol,OBJPROP_STATE,false);
         ObjectSetInteger(0,c_symbol,OBJPROP_ZORDER,0);
         ObjectsDeleteAll(0,0,OBJ_BUTTON);
         ObjectsDeleteAll(0,0,OBJ_LABEL);
         ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
         //--
         ChartSetSymbolPeriod(0,c_symbol,cstf);
         //--
         ChartRedraw(0);
         //--
         return;
      //---
        } //-end ChangeChartSymbol()
      //---------//


      Da wir einen Expertenhandelsmodus mit mehreren Zeitrahmen oder einem einzigen Zeitrahmen und einer Handelssitzung oder einer Handelszeitzone und Optionen für die zu handelnden Paare hinzufügen, benötigen wir zusätzliche Informationen in den angezeigten Handelsinformationen auf dem Chart.
      Um Informationen zu den angezeigten Handelsinformationen im Chart hinzuzufügen, haben wir Änderungen an der Funktion TradeInfo() vorgenommen:

      void MCEA::TradeInfo(void) // function: write comments on the chart
        {
      //----
         Pips(Symbol());
         double spread=SymbolInfoInteger(Symbol(),SYMBOL_SPREAD)/xpip;
         rem=zntm-TimeCurrent();
         string postime=PosTimeZone();
         string eawait=" - Waiting for active time..!";
         //--
         string tradetf=tfinuse==MTF ? EnumToString(Period()) : EnumToString(TFts);
         string eamode=tfinuse==MTF ? "Multi-Timeframe" : "Single-Timeframe";
         string comm="";
         TodayOrders();
         //--
         comm="\n     :: Server Date Time : "+string(ThisTime(year))+"."+string(ThisTime(mon))+"."+string(ThisTime(day))+ "   "+TimeToString(TimeCurrent(),TIME_SECONDS)+
              "\n     ------------------------------------------------------------"+
              "\n      :: Broker               :  "+ TerminalInfoString(TERMINAL_COMPANY)+
              "\n      :: Expert Name      :  "+ expname+
              "\n      :: Acc. Name         :  "+ mc_account.Name()+
              "\n      :: Acc. Number      :  "+ (string)mc_account.Login()+
              "\n      :: Acc. TradeMode :  "+ AccountMode()+
              "\n      :: Acc. Leverage    :  1 : "+ (string)mc_account.Leverage()+
              "\n      :: Acc. Equity       :  "+ DoubleToString(mc_account.Equity(),2)+
              "\n      :: Margin Mode     :  "+ (string)mc_account.MarginModeDescription()+
              "\n      :: Magic Number   :  "+ string(magicEA)+
              "\n      :: Trade on TF      :  "+ tradetf+
              "\n      :: Trade Mode      :  "+ eamode+
              "\n      :: Today Trading   :  "+ TradingDay()+" : "+hariini+
              "\n      :: Trading Session :  "+ tz_ses+
              "\n      :: Trading Time    :  "+ postime;
              if(TimeCurrent()<zntm)
                {
                  comm=comm+
                  "\n      :: Time Remaining :  "+(string)ReqTime(rem,hour)+":"+(string)ReqTime(rem,min)+":"+(string)ReqTime(rem,sec) + eawait;
                }
              comm=comm+
              "\n     ------------------------------------------------------------"+
              "\n      :: Trading Pairs     :  "+pairs+
              "\n      :: BUY Market      :  "+string(oBm)+
              "\n      :: SELL Market     :  "+string(oSm)+
              "\n      :: Total Order       :  "+string(oBm+oSm)+
              "\n      :: Order Profit      :  "+DoubleToString(floatprofit,2)+
              "\n      :: Fixed Profit       :  "+DoubleToString(fixclprofit,2)+
              "\n      :: Float Money     :  "+DoubleToString(floatprofit,2)+
              "\n      :: Nett Profit        :  "+DoubleToString(floatprofit+fixclprofit,2);
         //--
         Comment(comm);
         ChartRedraw(0);
         return;
      //----
        } //-end TradeInfo()  
      //---------//


      Wir haben auch eine Funktion zur Beschreibung der Zeit gemäß den Bedingungen der Handelszeitzone als Teil der Funktion TradeInfo() hinzugefügt:

      string MCEA::PosTimeZone(void)
        {
      //---
          string tzpos="";
          //--
          if(ReqTime(zntm,day)>ThisTime(day))
           {
             tzpos=tz_opn+ " Next day to " +tz_cls + " Next day";
           }
          else
          if(TimeCurrent()<znop)
            {
              if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)==ReqTime(zncl,day))
                tzpos=tz_opn+" to " +tz_cls+ " Today";
              //else
              if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day))
                tzpos=tz_opn+ " Today to " +tz_cls+ " Next day";
            }
          else
          if(TimeCurrent()>=znop && TimeCurrent()<zncl)
            {
              if(ThisTime(day)<ReqTime(zncl,day))
                tzpos=tz_opn+ " Today to " +tz_cls+ " Next day";
              else
              if(ThisTime(day)==ReqTime(zncl,day))
                tzpos=tz_opn+" to " +tz_cls+ " Today";
            }
          else
          if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day))
            {
              tzpos=tz_opn+" Today to " +tz_cls+ " Next day";
            }
          //--
          return(tzpos);
      //----
        } //-end PosTimeZone()
      //---------//


      Die Schnittstelle des Multi-Currency Expert Advisor TriangularMA_MTF_MCEA sieht wie in der folgenden Abbildung dargestellt aus:

      TradeInfo


      Unter dem Namen des Expert Advisors TriangularMA_MTF_MCEA finden Sie die Schaltflächen „M“, „C“ und „R“:

      Expert_manual_button

      Wenn die Schaltfläche M angeklickt wird, wird ein manuelles Schaltflächenfeld angezeigt (siehe unten):

      Expert_manual_button_01

      Dann kann der Händler die Aufträge, wie im Abschnitt Manuelle Auftragsverwaltung beschrieben, verwalten.

      • 1. Set SL/TP All Orders (SL/TP für alle Aufträge einstellen)
      • 2. Close All Orders (Alle Aufträge schließen)
      • 3. Close All Profits (Alle Positionen im Gewinn schließen)


      Wenn die Schaltfläche C angeklickt wird, wird eine Schaltfläche mit 30 Symbolnamen oder -paaren angezeigt, und die Händler können auf einen der Paar- oder Symbolnamen klicken.
      Wird einer der Namen des Paars oder der Symbole angeklickt, wird das Chartsymbol sofort durch das Symbol ersetzt, dessen Name angeklickt wurde.

      Expert_manual_button_02


      Wenn die Schaltfläche R angeklickt wird, wird der Multi-Currency Expert Advisor TriangularMA_MTF_MCEA aus dem Chart entfernt,
      sodass die Händler die Experten nicht manuell ablösen müssen.



      Strategietester

      Wie bekannt, unterstützt das MetaTrader5-Terminal Strategy Tester und ermöglicht es uns, Strategien zu testen, auf mehreren Symbolen zu handeln oder den automatischen Handel für alle verfügbaren Symbole und auf allen verfügbaren Zeitrahmen zu testen.

      Bei dieser Gelegenheit werden wir also einen TriangularMA_MTF_MCEA als Multi-Timeframe und Single-Timeframe in Multi-Currency Expert Advisor auf der MetaTrader5 Strategy Tester Plattform testen.

      1. Test TriangularMA_MTF_MCEA mit Multi-Timeframe-Modus.

      st-mtfst-mtf/p>


      st-mtf-ergebnis


      2. Test TriangularMA_MTF_MCEA mit Single-Timeframe-Modus.

      st-stf


      st-stf-ergebnis



      Schlussfolgerung

      Die Schlussfolgerung bei der Erstellung eines Multi-Currency Expert Advisors sowohl im Multi-Timeframe-Modus als auch im Single-Timeframe-Modus mit MQL5 lautet wie folgt:

      • Es stellt sich heraus, dass die Erstellung eines Mehr-Währungs-EA in MQL5 sehr einfach ist und sich nicht wesentlich von einem Single-Currency Expert Advisor unterscheidet. Aber gerade bei Mehr-Währungs-EAs mit Multi-Timeframes ist es ein wenig komplizierter als einer für einen einzelnen Zeitrahmen.
      • Die Erstellung eines Mehr-Währungs-EAs erhöht die Effizienz und Effektivität von Händlern, da sie nicht viele Chart-Symbole für den Handel öffnen müssen.
      • Durch die Anwendung der richtigen Handelsstrategie erhöht sich die Gewinnwahrscheinlichkeit im Vergleich zur Verwendung eines Single-Currency Expert Advisors. Denn die Verluste, die bei einem Paar auftreten, werden durch Gewinne bei anderen Paaren ausgeglichen.
      • Dieser TriangularMA_MTF_MCEA Multi-Currency Expert Advisor ist nur ein Beispiel, um zu lernen und Ideen zu entwickeln. 
      • Die Testergebnisse des Strategietesters sind immer noch nicht gut. Wenn also eine bessere Strategie mit genaueren Signalberechnungen implementiert wird und einige bessere Zeitrahmen hinzugefügt werden, glaube ich, dass die Ergebnisse besser sein werden als die aktuelle Strategie.
      • Aus den Testergebnissen auf dem Strategy Tester des TriangularMA_MTF_MCEA geht hervor, dass die Ergebnisse von Single-Timeframe immer noch besser sind als Multi-Timeframe.

      Anmerkung:
      Wenn Sie eine Idee für die Erstellung eines einfachen Mehr-Währungs-EA auf der Grundlage der eingebauten MQL5-Standardindikatoren haben, schlagen Sie sie bitte in den Kommentaren vor.
      Wir hoffen, dass dieser Artikel und das MQL5 Mehr-Währungs-EA-Programm für Händler beim Lernen und Entwickeln von Ideen nützlich sein werden. Danke fürs Lesen.

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

      Letzte Kommentare | Zur Diskussion im Händlerforum (5)
      Mohammed Yousif
      Mohammed Yousif | 22 Nov. 2023 in 14:17
      Wie erhalte ich Zugang zum Multiwährungs-Expertenhändler?
      Fernando Carreiro
      Fernando Carreiro | 22 Nov. 2023 in 15:03
      @Mohammed Yousif #: Wie erhalte ich Zugang zum Multi Currency Expert Trader?

      Indem Sie den Artikel lesen, daraus lernen und den Beispielcode am Ende herunterladen.

      Usman Akram
      Usman Akram | 7 Dez. 2023 in 07:37
      Fernando Carreiro #:

      Indem ich den Artikel lese, von ihm lerne und den Beispielcode am Ende herunterlade.

      Bitte sagen Sie mir, wo Beispielcode herunterladen
      Roberto Jacobs
      Roberto Jacobs | 7 Dez. 2023 in 11:15
      Usman Akram #:
      Bitte sagen Sie mir, wo ich den Beispielcode herunterladen kann.

      Wie von Moderator Fernando Carreiro erklärt, schauen Sie ganz unten im Artikel auf die Bezeichnung Attached files und klicken Sie auf den Dateinamen.

      Aleksandr Slavskii
      Aleksandr Slavskii | 24 März 2024 in 04:54
      Usman Akram #:
      Können Sie mir bitte sagen, wo ich den Beispielcode herunterladen kann?
      Sie können ihn nur auf Ihrem Computer herunterladen. Wenn Sie den Artikel auf Ihrem Telefon lesen, wird die EA-Datei nicht angezeigt.
      MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 08): Perceptrons MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 08): Perceptrons
      Perceptrons, Netze mit einer einzigen ausgeblendeten Schicht, sind ein guter Einstieg für alle, die mit den Grundlagen des automatisierten Handels vertraut sind und sich mit neuronalen Netzen vertraut machen wollen. Wir sehen uns Schritt für Schritt an, wie dies in einer Signalklassen-Assembly realisiert werden könnte, die Teil der MQL5 Wizard-Klassen für Expert Advisors ist.
      Entwurfsmuster in der Softwareentwicklung und MQL5 (Teil 3): Verhaltensmuster 1 Entwurfsmuster in der Softwareentwicklung und MQL5 (Teil 3): Verhaltensmuster 1
      Ein neuer Artikel aus der Reihe der Artikel über Entwurfmuster. Wir werden einen Blick auf einen seiner Typen werfen, nämlich den Verhaltensmuster, um zu verstehen, wie wir Kommunikationsmethoden zwischen erstellten Objekten effektiv aufbauen können. Durch die Vervollständigung dieser Verhaltensmuster werden wir in der Lage sein zu verstehen, wie wir eine wiederverwendbare, erweiterbare und getestete Software erstellen und aufbauen können.
      Datenwissenschaft und maschinelles Lernen (Teil 16): Ein frischer Blick auf die Entscheidungsbäume Datenwissenschaft und maschinelles Lernen (Teil 16): Ein frischer Blick auf die Entscheidungsbäume
      Tauchen wir ein in die komplizierte Welt der Entscheidungsbäume in der neuesten Folge unserer Serie über Datenwissenschaft und maschinelles Lernen. Dieser Artikel ist auf Händler zugeschnitten, die nach strategischen Einsichten suchen, und dient als umfassende Zusammenfassung, die die wichtige Rolle von Entscheidungsbäumen bei der Analyse von Markttrends beleuchtet. Wir erforschen die Wurzeln und Äste dieser algorithmischen Bäume und erschließen Sie deren Potenzial zur Verbesserung Ihrer Handelsentscheidungen. Erleben Sie mit uns eine erfrischende Perspektive auf Entscheidungsbäume und entdecken Sie, wie sie Ihnen bei der Navigation durch die Komplexität der Finanzmärkte behilflich sein können.
      Wie man einen einfachen Multi-Currency Expert Advisor mit MQL5 erstellt (Teil 5):  Die Bollinger Bänder mit dem Keltner-Kanal — Indikatoren Signal Wie man einen einfachen Multi-Currency Expert Advisor mit MQL5 erstellt (Teil 5): Die Bollinger Bänder mit dem Keltner-Kanal — Indikatoren Signal
      Der Multi-Currency Expert Advisor in diesem Artikel ist ein Expert Advisor oder Handelsroboter, der handeln kann (z.B. Aufträge eröffnen, schließen und verwalten, Trailing Stop Loss und Trailing Profit) für mehr als ein Symbolpaar aus nur einem Symbolchart. In diesem Artikel werden wir Signale von zwei Indikatoren verwenden, in diesem Fall Bollinger Bänder® und dem Keltner Kanal.