English 日本語
preview
Wie man einen einfachen Multi-Currency Expert Advisor mit MQL5 erstellt (Teil 6): Zwei RSI-Indikatoren kreuzen ihre Linien

Wie man einen einfachen Multi-Currency Expert Advisor mit MQL5 erstellt (Teil 6): Zwei RSI-Indikatoren kreuzen ihre Linien

MetaTrader 5Beispiele | 2 Mai 2024, 12:53
362 0
Roberto Jacobs
Roberto Jacobs

Einführung

Ein Multi-Currency Expert Advisor 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 1 Symbolpaar von nur einem Symbolchart aus, wobei in diesem Artikel Expert Advisor für 30 Paare handeln wird.
In diesem Artikel werden wir zwei RSI-Indikatoren, die sich kreuzen, als Signal verwenden, den Fast RSI, der sich mit dem Slow RSI kreuzt.

Wie in den vorangegangenen Artikeln bewiesen wurde, wissen wir alle, dass der Handel mit mehreren Währungen bereits mit der Leistung, den Fähigkeiten und den Möglichkeiten von MQL5 möglich ist, sowohl im Handelsterminal als auch im Strategietester.

Mit dem Ziel der Erfüllung der wichtigen Bedürfnisse der Händler, die eine effiziente und effektive Trading-Roboter wollen, sodass unter Berufung auf die Kraft, Fähigkeiten und Einrichtungen der sehr zuverlässigen MQL5, können wir uns vorstellen, verschiedene Ideen und Strategien eines einfachen Multi-Währung Expert Advisors, der, wie in diesem Artikel beschrieben, die Linien von zwei RSI-Indikatoren kreuzen lässt.


Pläne und Eigenschaften


1. Handel mit Währungspaaren.

Dieser Mehr-Währungs-EA ist für den Handel mit einem der folgenden Symbole oder Paare vorgesehen:

Für Forex:
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.

Was Symbole oder Paare mit Namenspräfixen und/oder -suffixen betrifft, so verwende ich für den Expert Advisor in diesem Artikel die Funktion zur automatischen Behandlung von Symbolnamen mit Präfixen und/oder Suffixen, sodass bei der Verwendung eines EA auf MetaTrader 5 von einem Broker mit solchen speziellen Symbolnamen alles reibungslos funktioniert.
Die Funktion zur Erkennung von Symbolnamen mit Präfixen und Suffixen funktioniert jedoch nur bei Forex- und Metall-Symbolpaarnamen im MetaTrader 5, nicht aber bei speziellen Symbolen und Indizes.

In Bezug auf den Multi-Currency Expert Advisor in meinem vorherigen Artikel, gibt es einige Händler, die fragen, wie man einen Multi-Currency EA als Einzelwährungs-EA oder als eigenständigen EA verwenden kann.

Eigentlich, in der Expert Advisor in der vorherigen Artikel, gibt es eine Anlage oder Option, um die Expert Advisor als EA durch den Handel nur auf eine einzige Währung oder arbeiten als Stand-alone-EA.

Im Expert Advisor verwenden wir diesmal immer noch 10 verschiedene Paare, die gehandelt werden sollen. Eines der 10 Optionspaare, die gehandelt werden, ist „Trader's Desired Pairs“ (Des Händlers Wunschpaar), wobei die zu handelnden Paare vom Händler manuell in der Eigenschaft Expert Input eingegeben werden müssen. Sie müssen jedoch immer daran denken, dass der Name des Paares, das Sie eingeben, bereits in der Liste der 30 Paare enthalten sein muss.

Diese Option „Trader's Desired Pairs“ (Des Händlers Wunschpaar) kann tatsächlich verwendet werden, sodass Expert Advisors wird nur auf Einzel-Währung Handel oder arbeiten als Stand-alone-EA, durch die Eingabe des Namens von nur einem gewünschten Paar, und dann wird der Experte Berater nur mit diesem einen Paar handeln und arbeiten.

Die Parametereinstellungen für den Experteneingang müssen wie in der folgenden Abbildung gezeigt vorgenommen werden.

stand-alone-twp

Im obigen Beispiel der Eingabeeigenschaft, bei dem der Händler nur den Namen des XAUUSD-Paares eingibt, wird der Expert Advisor unter dieser Bedingung nur mit dem XAUUSD-Paar handeln. Unabhängig davon, wo der Expert Advisor unter den 30 verfügbaren Paaren platziert wird, handelt er nur mit dem Paar XAUUSD.

Abgesehen davon habe ich im Expert Advisor in diesem Artikel eine Option hinzugefügt, um die Bedingungen für das Handelspaar auszuwählen, d.h. ob mit einer einzigen Währung oder mit mehreren Währungen gehandelt werden soll.

Die Experten-Eingabeparameter müssen wie in der folgenden Abbildung dargestellt eingestellt werden.

trading-pair-option

stand-alone-sp

Bei der Option „SP“ (Single-Pair) handelt der Expert Advisor nur mit dem Paar, auf dessen Chart er platziert ist.
Wenn beispielsweise ein Expert Advisor auf das EURUSD-Paar platziert wird, dann wird der Expert Advisor nur mit dem EURUSD-Paar handeln.

Bei den Expert Advisors in diesem Artikel gibt es also zwei Möglichkeiten, mit Einzelwährungen zu handeln oder als eigenständiger Expertenberater zu arbeiten.

1. Bleiben Sie bei der Option Multi-Pair oder „MP“ und wählen Sie die Option Trader's Desired Pairs, aber geben Sie nur einen Paar-Namen ein, zum Beispiel XAUUSD.
Bei dieser Option handelt der Expert Advisor, unabhängig vom Paar, auf das er eingestellt ist, nur mit dem Paar, das in Trader Wishes Pairs eingegeben wurde.

2. Wählen Sie im Modus Handelspaare auswählen die Option „SP“ oder Einzelpaar.
Wenn ein Expert Advisor auf das EURUSD-Paar platziert wird, handelt der Expert Advisor nur mit dem EURUSD-Paar.

Außerdem werden in der Gruppe Handel zu bestimmten Zeiten Optionen für Händler angeboten, die in der Zeitzone handeln möchten.
Vielleicht möchten viele Händler nach der Zeitzone handeln, sodass die Paare, die gehandelt werden, der Zeit für die Handelssitzung entsprechen können, sodass wir in diesem Expert Advisor noch die Option für die Handelssitzung (Zeitzone) verwenden.


2. Indikatoren.

Der Relative-Stärke-Index (RSI) wurde von J. Welles Wilder entwickelt und 1978 in einem Buch „New Concepts in Technical Trading Systems“ sowie in der Zeitschrift Commodities (heute Modern Trader) in der Juni-Ausgabe 1978 veröffentlicht. Er hat sich zu einem der beliebtesten Oszillator-Indizes entwickelt.

Der Relative-Stärke-Index (RSI) ist ein technischer Indikator, der bei der Analyse der Finanzmärkte verwendet wird. Er soll die aktuelle und historische Stärke oder Schwäche einer Aktie oder eines Marktes auf der Grundlage der Schlusskurse des letzten Handelszeitraums darstellen.

Der technische Indikator Relative Strength Index (RSI) ist ein preisverfolgender Oszillator, der zwischen 0 und 100 liegt. Wilder empfahl für den Relative Strength Index eine Periodenlänge von 14. Seitdem haben RSI mit Periodenlängen von 9 und 25 an Beliebtheit gewonnen.

Der RSI wird in der Regel auf einer 14-Tage-Skala von 0 bis 100 gemessen, wobei die Höchst- und Tiefstwerte bei 70 bzw. 30 liegen. Kürzere oder längere Zeitrahmen werden für abwechselnd kürzere oder längere Prognosen verwendet. Hohe und niedrige Werte - 80 und 20 oder 90 und 10 - treten seltener auf, zeigen aber eine stärkere Dynamik an.

Außerdem wird in der technischen Analyse MetaTrader 5 angegeben, dass das RSI-Signal für die Chartanalyse verwendet wird:

  • Hochs und Tiefs
  • Chart-Formationen
  • Falsche Ausbrüche (Failure Swing, Durchbruch der Unterstützung oder des Widerstands)
  • Unterstützungs- und Widerstandsniveaus
  • Divergenzen

Es gibt also sehr viele Varianten der RSI-Handelsstrategie.

Auch ein Analyst und Investor in einem Q&A in seinem Artikel bei der Beantwortung der Frage:

„Was ist die beste RSI-Einstellung für das Daytrading?

Leider funktioniert der RSI am besten auf täglichen Balken. Wir haben viele Daten auf der Grundlage von Intraday-Daten getestet, aber sie sind nicht besonders nützlich.“

„Wie handeln Sie mit dem RSI?

Zunächst einmal bevorzugen wir die Verwendung von Tagesbalken. Zweitens ziehen wir es vor, eine kurze Anzahl von Tagen in den Einstellungen zu verwenden, vorzugsweise maximal 5 Tage. Drittens funktioniert der RSI am besten bei Aktien und mittelwertumkehrenden Vermögenswerten mit einer Grenze über Nacht. Im Bereich Forex waren wir nicht erfolgreich.“

Allerdings werde ich in diesem Artikel Signale der Kreuzung von Fast RSI und Slow RSI für den Devisenhandel verwenden.
Ob es erfolgreich sein wird oder nicht, muss noch erprobt und getestet werden.

Eine Illustration des schnellen RSI-Signals, das die langsame RSI-Linie kreuzt, ist in Abbildung 1 und 2 zu sehen.

Abbildung 1
RSIxRSI_signal_00

Abbildung 2
RSIcross_variation


3. Handels- & Auftragsmanagement

Es gibt mehrere Möglichkeiten, Ihre Trades mit diesem Multiwährungs-Expertenberater zu verwalten:

3.1. Stop Loss-Aufträge

Optionen: Use Order Stop Loss (Yes) oder (No)

  • Wenn die Option (No) für Use Order Stop Loss für Aufträge verwenden ausgewählt ist, werden alle Aufträge ohne Stop Loss eröffnet.
  • Bei Verwendung der Option Use Order Stop Loss für Aufträge verwenden (Yes): Dann gibt es die weiteren Optionen: Use Automatic Calculation (automatische Berechnung) des Stop Loss verwenden (Yes) oder (No).
  • Bei der Option automatische Berechnung Stop Loss (Yes), 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): Dann prüft der Experte für jede eröffnete Order, ob die Signalbedingung noch gut ist und die Order mit Gewinn aufrechterhalten werden kann oder ob sich das Signal abgeschwächt hat und die Order geschlossen werden muss, um den Gewinn zu sichern oder ob sich die Signalbedingung umgekehrt hat und die Order mit Verlust geschlossen werden muss.
Anmerkung: Speziell für Close Trade und Save Profit aufgrund eines schwachen Signals wird eine Option angeboten, ob diese aktiviert werden soll oder nicht.

  • Wenn sie nicht aktiviert ist (No), wird der Auftrag trotz des schwächeren Signals aufrechterhalten oder nicht geschlossen, um den Gewinn zu sichern.
  • Wenn aktiviert (Yes), sind die Bedingungen für die Indikatoren Fast RSI und Slow RSI:

 

Für das Schließen von Kaufpositionen: 

Wenn der Fast RSI über dem Slow RSI liegt und der Fast RSI-Wert des aktuellen Balkens kleiner ist als der Fast RSI-Wert des vorherigen Balkens, wird der Kaufauftrag geschlossen.


Für das Schließen von Verkaufspositionen:

Wenn der Fast RSI unter dem Slow RSI liegt und der Fast RSI-Wert des aktuellen Balkens größer ist als der Fast RSI-Wert des vorherigen Balkens, wird der Verkaufsauftrag geschlossen.

Der Code zum Setzen eines Stop Loss-Auftrags lautet wie folgt:

double MCEA::OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice)
  {
//---
    slv=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    RefreshTick(xsymb);
    //--
    switch(type) 
      { 
       case (ORDER_TYPE_BUY):
         {
           if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice-38*pip);
           else
           if(use_sl==Yes && autosl==No)  slv=mc_symbol.NormalizePrice(atprice-SLval*pip);
           else slv=0.0;
           //--
           break;
         }
       case (ORDER_TYPE_SELL):
         {
           if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice+38*pip);
           else
           if(use_sl==Yes && autosl==No)  slv=mc_symbol.NormalizePrice(atprice+SLval*pip);
           else slv=0.0;
         }
      }
    //---
    return(slv);
//---
  } //-end OrderSLSet()
//---------//

Der Code, um den Handel zu schließen und den Gewinn aufgrund eines schwachen Signals zu sichern, lautet wie folgt:

int MCEA::GetCloseInWeakSignal(const string symbol,int exis) // Signal Indicator Position Close in profit
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    int bar=3;
    //--
    double rdif=rsidiff;
    double RSIFast[],
           RSISlow[];
    //--
    ArrayResize(RSIFast,bar,bar);
    ArrayResize(RSISlow,bar,bar);
    ArraySetAsSeries(RSIFast,true);
    ArraySetAsSeries(RSISlow,true);
    //--
    int x=PairsIdxArray(symbol);
    UpdatePrice(symbol,TFt);
    //--
    CopyBuffer(hRSIFast[x],0,0,bar,RSIFast);
    CopyBuffer(hRSISlow[x],0,0,bar,RSISlow);
    //--
    if(exis==down && RSIFast[1]<=RSISlow[1] && RSIFast[1]<RSIFast[2] && RSIFast[0]>RSIFast[1]+rdif) ret=rise;
    if(exis==rise && RSIFast[1]>=RSISlow[1] && RSIFast[1]>RSIFast[2] && RSIFast[0]<RSIFast[1]-rdif) ret=down;
    //--
    return(ret);
//---
  } //-end GetCloseInWeakSignal()
//---------//


2. Take Profit-Aufträge.

Optionen: Use Order Take Profit (Yes) oder (No)

  • 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 Use Order Take Profit (Yes): Dann gibt es die weiteren Optionen: Use Automatic Calculation Order Take Profit (Yes) oder (No).
  • Bei der Option der automatischen Berechnung von Take Profit (Yes), dann wird die Berechnung der Take Profit Order automatisch vom Experten durchgeführt.
  • Wenn die Option der automatischen Berechnung von Take Profit (No), gewählt wurde, muss der Händler den Order-Take Profit-Wert in Pips eingeben.

Der Code zum Festlegen von Take Profit lautet wie folgt:

double MCEA::OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice)
  {
//---
    tpv=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    RefreshTick(xsymb);
    //--
    switch(type) 
      { 
       case (ORDER_TYPE_BUY):
         {
           if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice+50*pip);
           else
           if(use_tp==Yes && autotp==No)  tpv=mc_symbol.NormalizePrice(atprice+TPval*pip);
           else tpv=0.0;
           //--
           break;
         }
       case (ORDER_TYPE_SELL):
         {
           if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice-50*pip);
           else
           if(use_tp==Yes && autotp==No)  tpv=mc_symbol.NormalizePrice(atprice-TPval*pip);
           else tpv=0.0;
         }
      }
    //---
    return(tpv);
//---
  } //-end OrderTPSet()
//---------//

3. Trailing Stop und Trailing Take Profit.

Optionen: Use Trailing SL/TP (Yes) oder (No)

  • 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): Händler können zwischen 2 Optionen wählen:

1. Trailing durch Preis.
Der Trailing-Stop wird vom Experten anhand der Preisbewegungen und des Wertes in der Eingabeeigenschaft ausgeführt, und gleichzeitig wird der Trailing-Profit auf der Grundlage des variablen Wertes TPmin (minimaler Trailing-Profit-Wert) gemacht.

2. Trailing durch Indikator.
Der Trailing-Stop wird vom Experten mit Hilfe des VIDYA-Indikators ausgeführt, wobei gleichzeitig ein Trailing-Profit auf der Grundlage des variablen Werts TPmin (minimaler Trailing-Profit-Wert) erzielt wird.

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

Meinen Untersuchungen und Experimenten zufolge ist der VIDYA-Indikator etwas besser und ideal für Trailing-Stops im Vergleich zum Parabolic SAR oder verschiedenen Varianten von Moving Average-Indikatoren.

Im Vergleich zum Parabolic SAR-Indikator ist der VIDYA-Indikator näher an den Kursbewegungen, und im Vergleich zu den AMA-, DEMA- und MA-Indikatoren ist der VIDYA-Indikator noch weiter von den Kursbewegungen entfernt.

Daher habe ich in diesem Artikel beschlossen, den VIDYA-Indikator für die auf dem Indikator basierende Trailing-Stop-Funktion zu verwenden.

Der Code für die Funktion TSPrice, „Trailing Stop Price“ and Indicator:

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 VIDyAv[];
            ArrayResize(VIDyAv,br,br);
            ArraySetAsSeries(VIDyAv,true);
            CopyBuffer(hVIDyAv[x],0,0,br,VIDyAv);
            RefreshPrice(xsymb,TFt,br);
            //--
            if(ptype==POSITION_TYPE_BUY  && (VIDyAv[0]<mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip)))
               pval=VIDyAv[0];
            if(ptype==POSITION_TYPE_SELL && (VIDyAv[0]>mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip)))
               pval=VIDyAv[0];
            break;
          }
      }
    //--
    return(pval);
//---
  } //-end TSPrice()
//---------//

Ändern wir den SL/TP-Funktionscode:

bool MCEA::ModifySLTP(const string symbx,int TS_type)
  {
//---
   ResetLastError();
   MqlTradeRequest req={};
   MqlTradeResult  res={};
   MqlTradeCheckResult check={};
   //--
   int TRSP=(Close_by_Opps==No && TS_type==1) ? 0 : 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-1.0)*pip));
               double modbuysl=vtrsb;
               double modbuytp=mc_symbol.NormalizePrice(price+TPval*pip);
               bool modbuy = (price>modminsl && modbuysl>modstart && (pos_stop==0.0||modbuysl>pos_stop));
               //--
               if(modbuy && netp>minprofit)
                 {
                   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+1.0)*pip));
               double modselsl=vtrss;
               double modseltp=mc_symbol.NormalizePrice(price-TPval*pip);
               bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==0.0||modselsl<pos_stop)); 
               //--
               if(modsel && netp>minprofit)
                 {
                   modist=mc_trade.PositionModify(symbol,modselsl,modseltp);
                 }  
             }
         }
     }
    //--
    return(modist);
//---
  } //-end ModifySLTP()
//---------//


4. Manuelle Auftragsverwaltung.

In diesem Multi-Currency Expert Advisor wurden mehrere manuelle Schaltflächen hinzugefügt, um die Effizienz und Effektivität für Händler bei der Überwachung der Arbeit des Expert Advisors zu erhöhen.

4.1. SL / TP Alle Aufträge einstellen: 
Diese Schaltfläche ist nützlich, wenn der Händler die Parameter „Use Order Stop Loss (No)“ und/oder „Use Order Take Profit (No)“ eingegeben hat, dann aber Stop Loss oder Take Profit für alle Aufträge verwenden möchte, dann werden mit einem einzigen Klick auf die Schaltfläche „Set SL/TP All Orders“ alle Orders geändert und ein Stop Loss und/oder Take Profit angewendet.

4.2. Alle Positionen schließen:
Wenn ein Händler alle Positionen schließen möchte, genügt ein einziger Klick auf die Schaltfläche „Alle Aufträge schließen“, um alle offenen Aufträge zu schließen.

4.3. Alle Positionen mit Gewinn schließen:

Wenn ein Händler alle Aufträge schließen möchte, die bereits profitabel sind, genügt ein einziger Klick auf die Schaltfläche „Close All Orders Profit“, um alle offenen Positionen, die bereits profitabel sind, zu schließen.


5. Management-Befehle und Chartsymbole.

Für Multi-Währungs-Expertenberater, die 30 Paare mit nur einem Chart-Symbol handeln, ist es sehr effektiv und effizient, eine Schalttafel für alle Symbole zur Verfügung zu stellen, sodass Händler den Chart-Zeitrahmen oder die Symbole mit nur einem Klick ändern können, um die Genauigkeit des Indikatorsignals zu sehen, wenn der Experte eine Order öffnet oder schließt.


Umsetzung der Planung im Programm MQL5

1. Programmkopf 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 10 Optionspaaren für den Handel

//--
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
 };   
//--

Die Enumeration YN wird für die Optionen (Yes) oder (No) in der Eigenschaft Experteneingabe verwendet.

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

Die Enumeration zur Verwendung von Money Management Lot Size

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

Die Enumeration zur Auswahl des Zeitrahmens, der für die Berechnung der Signalindikatoren verwendet werden soll

//--
enum TFUSE
  {
   TFM5,     // 00_PERIOD_M5
   TFM15,    // 01_PERIOD_M15
   TFM30,    // 02_PERIOD_M30
   TFH1,     // 03_PERIOD_H1
   TFH2,     // 04_PERIOD_H2
   TFH3,     // 05_PERIOD_H3
   TFH4,     // 06_PERIOD_H4
   TFH6,     // 07_PERIOD_H6
   TFH8,     // 08_PERIOD_H8
   TFH12,    // 09_PERIOD_H12
   TFD1      // 10_PERIOD_D1
  };
//--

Bei der TFUSE-Enumeration beschränke ich die Verwendung der Zeitrahmenberechnungen für die Experten nur von TF-M5 bis TF-D1.

Die Enumeration zur Auswahl des Typs, der für die Berechnung des Trailing-Stops verwendet werden soll

//--
enum TrType
  {
    byprice, // Trailing Stop by Price
    byindi   // Trailing Stop by Indicator
  };
//--

Die Enumeration zur Auswahl der Handelsart, mit der der Experte handelt, Einzelwährung oder Mehrfachwährung.

//--
enum MS
 {
   SP, // Single Pair
   MP  // Multi Pairs
 };
//--

Eingabeeigenschaften des Experten:

//---
input group               "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter
input TFUSE               tfinuse = TFH4;             // Select Expert TimeFrame, default PERIOD_H4
input int                 rsifast = 10;               // Input Period for Fast RSI
input ENUM_APPLIED_PRICE  frsiapp = PRICE_WEIGHTED;   // Select Fast RSI Applied Price
input int                 rsislow = 30;               // Input Period for Slow RSI
input ENUM_APPLIED_PRICE  srsiapp = PRICE_WEIGHTED;   // Select Slow RSI Applied Price
input double              rsidiff = 4.56;             // Input Differentiation between RSIs
//---
input group               "=== Select Pairs to Trade ===";  // Selected Pairs to trading
input MS                trademode = MP;              // Select Trading Pairs Mode (Multi or Single)
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 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.0;             // 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 = 60.0;             // If Not Use Automatic TP - Input TP value in Pips
input YN            TrailingSLTP = Yes;              // Use Trailing SL/TP (Yes) or (No)
input TrType               trlby = byindi;           // Select Trailing Stop Type
input double               TSval = 10.0;             // If Use Trailing Stop by Price Input value in Pips
input double               TSmin = 5.0;              // Minimum Pips to start Trailing Stop
input double               TPmin = 25.0;             // 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 = 20240111;         // Expert ID (Magic Number)
//---
//---------//

Hinweis: Wenn die Eingabeeigenschaft der Experten-ID (Magic Number) leer gelassen wird, kann der Expert Advisor manuell eröffnete Aufträge verwalten.

In der Eigenschaftsgruppe Globale Strategie-EA-Parameter Experteneingabe werden die Händler aufgefordert, den Zeitrahmen des Experten für die Berechnung der Indikatorsignale auszuwählen und Parameter einzugeben:

  1. Eingabe der Periodenlänge für RSI Fast und Auswahl von RSI Fast Applied Price
  2. Eingabe der Periodenlänge für RSI Slow und Auswahl RSI Slow Applied Price
  3. Eingabewert für die Unterscheidung zwischen RSI

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

Um das zu handelnde Paar zu konfigurieren, rufen wir die Funktion HandlingSymbolArrays() auf. Mit der FunktionHandlingSymbolArrays() 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);
    areur=ArraySize(EURs);
    aretc=ArraySize(JPYs);
    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<areur; 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 & Metal 30 Pairs
          {
            ArrayResize(DIRI,sall,sall);
            arrsymbx=sall;
            ArraySymbolResize();
            ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY);
            pairs="Multi Currency "+string(sall)+" 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,areur,areur);
            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 SetSymbolNamePS() werden wir in der Lage sein, Symbolnamen mit Präfixen und/oder Suffixen zu behandeln.

void MCEA::SetSymbolNamePS(void)
  {
//---
   int sym_Lenpre=0;
   int sym_Lensuf=0;
   string sym_pre="";
   string sym_suf="";
   SymbolSelect(Symbol(),true);
   string insymbol=Symbol();
   int inlen=StringLen(insymbol);
   int toseek=-1;
   string dep="";
   string bel="";
   string sym_use ="";
   int pairx=-1;
   string xcur[]={"EUR","GBP","AUD","NZD","USD","CAD","CHF"}; // 7 major currency
   int xcar=ArraySize(xcur);
   //--
   for(int x=0; x<xcar; x++)
     {
       toseek=StringFind(insymbol,xcur[x],0);
       if(toseek>=0)
         {
           pairx=x;
           break;
         }
     }
   if(pairx>=0)
     {
       int awl=toseek-3 <0 ? 0 : toseek-3;
       int sd=StringFind(insymbol,"SD",0);
       if(toseek==0 && sd<4)
         {
           dep=StringSubstr(insymbol,toseek,3);
           bel=StringSubstr(insymbol,toseek+3,3);
           sym_use=dep+bel;
         }
       else
       if(toseek>0)
         {
           dep=StringSubstr(insymbol,toseek,3);
           bel=StringSubstr(insymbol,toseek+3,3);
           sym_use=dep+bel;
         }
       else
         {
           dep=StringSubstr(insymbol,awl,3);
           bel=StringSubstr(insymbol,awl+3,3);
           sym_use=dep+bel;
         }
     }
   //--
   string sym_nmx=sym_use;
   int lensx=StringLen(sym_nmx);
   //--
   if(inlen>lensx && lensx==6)
     {
       sym_Lenpre=StringFind(insymbol,sym_nmx,0);
       sym_Lensuf=inlen-lensx-sym_Lenpre;
       //--
       if(sym_Lenpre>0)
         {
           sym_pre=StringSubstr(insymbol,0,sym_Lenpre);
           for(int i=0; i<xcar; i++)
             if(StringFind(sym_pre,xcur[i],0)>=0) sym_pre="";
         }
       if(sym_Lensuf>0)
         {
           sym_suf=StringSubstr(insymbol,sym_Lenpre+lensx,sym_Lensuf);
           for(int i=0; i<xcar; i++)
             if(StringFind(sym_suf,xcur[i],0)>=0) sym_suf="";
         }
     }
   //--
   pre=sym_pre;
   suf=sym_suf;
   inpre=StringLen(pre);
   insuf=StringLen(suf);
   posCur1=inpre;
   posCur2=posCur1+3;
   //--
   return;
//---
  } //-end SetSymbolNamePS()
//---------//

Hinweis: Der Experte validiert die Paare.  Wenn der Händler bei der Eingabe des Paarnamens einen Fehler macht (Tippfehler) oder wenn die Paarvalidierung fehlschlägt, erhält der Experte eine Warnung und der Expertenberater wird vom Chart entfernt.


In der Experten-Eingabeeigenschaftsgruppe Trade on Specific Time (Handel zu bestimmten Zeiten) kann der Händler wählen, ob er in einer bestimmten Zeitzone handeln möchte (Yes) oder (No).

Wenn die Option „Trade on Specific Time Zone“ (Handel in einer bestimmten Zeitzone) auf „No“ eingestellt ist, handelt der Experte von MT5 00:15 bis 23:59 Uhr.

Wenn Ja, dann wählen Sie die Enumerations-Optionen:

  • Trading on Custom Session (Handel während einer nutzerdefinierten Sitzung)
  • Trading on New Zealand Session (Handel während der neuseeländischen Sitzung)
  • Trading on Australia Sydney Session (Handel während der Australien Sydney Session)
  • Trading on Asia Tokyo Session (Handel während der Asien Tokyo Session)
  • Trading on Europe London Session (Handel während der Europa London Session)
  • Trading on America New York Session (Handel während der Amerika New York Session)

Standardmäßig ist der Handel in bestimmten Zeitzonen auf „Yes“ und auf Handel in nutzerdefinierten Sitzungen eingestellt.

Handel während der Custom Session:
In dieser Sitzung müssen die Händler die Zeit oder die Stunden und Minuten für den Handelsbeginn und die Stunden und Minuten für das Handelsende festlegen. Das bedeutet, dass der EA nur während des angegebenen Zeitraums vom Start bis zum Ende Aktivitäten durchführt.

In der Zwischenzeit wird in der New Zealand Trading Session bis zur New York US Trading Session die Zeit vom Beginn des Handels bis zum Ende des Handels vom EA berechnet.


Klasse für funktionierenden Expert Advisor

Um den Expert Advisor-Workflow zu erstellen und zu konfigurieren, haben wir eine Klasse erstellt, die alle Variablen, Objekte und Funktionen deklariert, die für einen Expert Advisor mit mehreren Währungen erforderlich sind.

//+------------------------------------------------------------------+
//| 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           point;
    double           slv,
                     tpv,
                     pip,
                     xpip;
    double           SARstep,
                     SARmaxi;
    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              GetRSIxx(const string symbol);
    int              PARSAR05(const string symbol);
    int              PARSAR15(const string symbol);
    int              LotDig(const string symbol);
    //--
    bool             CheckProfit(const string symbol,ENUM_POSITION_TYPE intype);
    bool             CheckLoss(const string symbol,ENUM_POSITION_TYPE intype);
    //--
    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:
    //---
    
    //-- RSIxRSI_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;
    //--
    int              hRSIFast[],
                     hRSISlow[];
    int              hVIDyAv[];
    int              hPar05[],
                     hPar15[];
    int              ALO,
                     dgts,
                     arrsar,
                     arrsymbx;
    int              sall,
                     arusd,
                     areur,
                     aretc,
                     arspc,
                     arper;
    ulong            slip;        
    //--
    double           profitb[],
                     profits[];
    double           minprofit;
    //--
    int              Buy,
                     Sell;
    int              ccur,
                     psec,
                     xtto,
                     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,
                     TFT05,
                     TFT15;
    //--
    bool             PanelExtra;
    //------------
                     MCEA(void);
                     ~MCEA(void);            
    //------------
    //--
    virtual void     RSIxRSI_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             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);
    bool             CheckProfitLoss(const string symbol);
    bool             CloseBuyPositions(const string symbol);
    bool             CloseSellPositions(const string symbol);
    //--
    int              PairsIdxArray(const string symbol);
    int              ValidatePairs(const string symbol);
    int              GetOpenPosition(const string symbol);
    int              GetCloseInWeakSignal(const string symbol,int exis);
    //--
    string           getUninitReasonText(int reasonCode);
    //--
    //------------
//---
  }; //-end class MCEA
//---------//
 
MCEA mc;

//---------//

Die erste und wichtigste Funktion im Arbeitsablauf des Multi-Currency Expert Advisors wird vom OnInit() aufgerufen: RSIxRSI_MCEA_Config().

Die Funktion RSIxRSI_MCEA_Config() konfiguriert alle zu verwendenden Symbole, alle Timeframes, alle Handle-Indikatoren und einige wichtige Funktionen des Include-Dateikopfes für den Expert Advisor Workflow.

Die Funktion RSIxRSI_MCEA_Config() beschreibt und implementiert die Handhabung von Zeitrahmen und die Erstellung von Indikator-Handles für alle im Expert Advisor Workflow verwendeten Indikatoren.

//+------------------------------------------------------------------+
//| Expert Configuration                                             |
//+------------------------------------------------------------------+
void MCEA::RSIxRSI_MCEA_Config(void) 
  {
//---
    //--
    HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded
    //--
    TFT05=PERIOD_M5;
    TFT15=PERIOD_M15;
    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(tfinuse==x) TFt=TFs[x]; // TF for calculation signal
    //--
    //-- Indicators handle for all symbol
    for(int x=0; x<arrsymbx; x++) 
      {
        hRSISlow[x]=iRSI(DIRI[x],TFt,rsislow,srsiapp);          //-- Handle for the Slow RSI indicator
        hRSIFast[x]=iRSI(DIRI[x],TFt,rsifast,frsiapp);          //-- Handle for the Fast RSI indicator
        hVIDyAv[x]=iVIDyA(DIRI[x],TFt,9,12,0,PRICE_WEIGHTED);   //-- Handle for the VIDYA indicator for Trailing Stop
        hPar05[x]=iSAR(DIRI[x],TFT05,SARstep,SARmaxi);          //-- Handle for the iSAR indicator for M5 Timeframe
        hPar15[x]=iSAR(DIRI[x],TFT15,SARstep,SARmaxi);          //-- Handle for the iSAR indicator for M15 Timeframe
        //--
      }
    //--
    minprofit=NormalizeDouble(TSmin/100.0,2);
    //--
    ALO=(int)mc_account.LimitOrders()>sall ? sall : (int)mc_account.LimitOrders();
    if(Close_by_Opps==No) 
      {
        if((int)mc_account.LimitOrders()>=(sall*2)) ALO=sall*2;
        else 
        ALO=(int)(mc_account.LimitOrders()/2);
      }
    //--
    LotPS=(double)ALO;
    //--
    mc_trade.SetExpertMagicNumber(magicEA);
    mc_trade.SetDeviationInPoints(slip);
    mc_trade.SetMarginMode();
    Set_Time_Zone();
    //--
    return;
//---
  } //-end RSIxRSI_MCEA_Config()
//---------//


2. Die Funktion OnTick() des Experten

Innerhalb der Expert Tick Funktion OnTick() werden wir eine der wichtigsten Funktionen in einem Multi-Currency Expert Advisor aufrufen, nämlich die ExpertActionTrade() Funktion. Der gesamte Prozess der EA-Arbeit für den Handel ist in dieser Funktion enthalten.

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

Das bedeutet, dass der ExpertActionTrade()-Befehl alle Aktivitäten durchführt und den automatischen Handel verwaltet, angefangen von Eröffnungs-, Schließaufträgen, Trailing-Stops oder Trailing-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++) 
          {
            //--
            switch(trademode)
              {
                case SP:
                  {
                    if(mc.DIRI[x]!=Symbol()) continue;
                    symbol=Symbol();
                    mc.pairs=mc.pairs+" ("+symbol+")";
                    break;
                  }
                case MP:
                  {
                    if(mc.DIRI[x]==Symbol()) symbol=Symbol();
                    else symbol=mc.DIRI[x];
                    break;
                  }
              }
            //--
            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]>mc.minprofit && 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]>mc.minprofit && 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)
                  {
                    mc.ModifySLTP(symbol,trlby);
                  }
              }
            //--
            mc.CheckOpenPMx(symbol);
            if(Close_by_Opps==No && (mc.xob[x]+mc.xos[x]>1))
              {
                mc.CheckProfitLoss(symbol);
                mc.Do_Alerts(symbol,"Close order due stop in loss.");
              }
            //--
            mc.CheckClose(symbol);
          }
        //--
        mc.psec=mc.ccur;
      }
    //--
    return;
//---
  } //-end ExpertActionTrade()
//---------//

Die Eigenschaftsgruppe Day Trading On/Off ermöglicht es Händlern, an bestimmten Tagen von Sonntag bis Samstag zu handeln. Hier können Händler mit den Optionen (Yes) oder (No) Experten für den Handel an einem bestimmten Tag aktivieren oder deaktivieren.

//--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)

Die Ausführung für den Day Trading On/Off ist wie folgt:

bool MCEA::TradingToday(void)
  {
//---
    bool tradetoday=false;
    int trdday=ThisTime(dow);
    hariini="No";
    //--
    int ttd[];
    ArrayResize(ttd,7);
    ttd[0]=ttd0;
    ttd[1]=ttd1;
    ttd[2]=ttd2;
    ttd[3]=ttd3;
    ttd[4]=ttd4;
    ttd[5]=ttd5;
    ttd[6]=ttd6;
    //--
    if(ttd[trdday]==Yes) {tradetoday=true; hariini="Yes";}
   //--
   return(tradetoday);
//---
  } //-end TradingToday()
//---------//

Anmerkungen: Die Bedingungen für den Tageshandel (Day Trading On/Off) werden in der Handelsinfo im Chart angezeigt.

Sie wird von der Funktion TradingDay() ausgeführt.

string MCEA::TradingDay(void)
  {
//---
   int trdday=ThisTime(dow);
   switch(trdday)
     {
        case 0: daytrade="Sunday";    break;
        case 1: daytrade="Monday";    break;
        case 2: daytrade="Tuesday";   break;
        case 3: daytrade="Wednesday"; break;
        case 4: daytrade="Thursday";  break;
        case 5: daytrade="Friday";    break;
        case 6: daytrade="Saturday";  break;
     }
   return(daytrade);
//---
  } //-end TradingDay()  
//---------//

Händler haben die Möglichkeit, in der Eigenschaftsgruppe „Trade at Specific Time“ des Expert Advisors nach Zeitzonen zu handeln.

Anmerkungen: Wie oben erläutert, wird im Falle des Handels an der New Zealand Session zum Handel an der US New York Session die Zeit vom Beginn des Handels bis zum Ende des Handels vom EA berechnet. 
Daher müssen Händler in den Eigenschaften des Experteneintrags nur die Zeit für die Stunde und Minute des Handelsbeginns und die Zeit für die Stunde und Minute des Handelsendes für die nutzerdefinierte Sitzung festlegen.


Die Funktion ExpertActionTrade() wurde um einen Aufruf der booleschen Funktion Trade_session() speziell für den Zeitzonenhandel erweitert.

Wenn Trade_session() true ist, dann wird der EA-Arbeitsprozess fortgesetzt, bis er beendet ist, aber wenn er false ist, dann wird der EA nur die Aufgaben „Close Trade and Save Profit due to Weak Signal if it is (Yes)“ (Schließen der Position und Sichern des Gewinns aufgrund schwachen Signals, wenn es (Yes) ist) und „Trailing Stop if it is (Yes)“ (Trailing Stop, wenn ja (Yes)) ausführen.

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()
//---------//

Der Arbeitsablauf in Trade at Specific Time sieht folgendermaßen aus: Zuerst ruft die Funktion ExpertActionTrade() die Funktion Trade_session() auf, dann ruft die Funktion Trade_session() die Funktion Set_Time_Zone() auf, und schließlich ruft die Funktion Set_Time_Zone() die Funktion Time_Zone() auf.

void MCEA::Set_Time_Zone(void)
  {
//---
    //-- Server Time==TimeCurrent()
    datetime TTS=TimeTradeServer();
    datetime GMT=TimeGMT();
    //--
    MqlDateTime svrtm,gmttm; 
    TimeToStruct(TTS,svrtm); 
    TimeToStruct(GMT,gmttm); 
    int svrhr=svrtm.hour;  // Server time hour
    int gmthr=gmttm.hour;  // GMT time hour
    int difhr=svrhr-gmthr; // Time difference Server time to GMT time
    //--
    int NZSGMT=12;  // New Zealand Session GMT/UTC+12
    int AUSGMT=10;  // Australia Sydney Session GMT/UTC+10
    int TOKGMT=9;   // Asia Tokyo Session GMT/UTC+9
    int EURGMT=0;   // Europe London Session GMT/UTC 0
    int USNGMT=-5;  // US New York Session GMT/UTC-5
    //--
    int NZSStm=8;   // New Zealand Session time start: 08:00 Local Time
    int NZSCtm=17;  // New Zealand Session time close: 17:00 Local Time 
    int AUSStm=7;   // Australia Sydney Session time start: 07:00 Local Time 
    int AUSCtm=17;  // Australia Sydney Session time close: 17:00 Local Time  
    int TOKStm=9;   // Asia Tokyo Session time start: 09:00 Local Time 
    int TOKCtm=18;  // Asia Tokyo Session time close: 18:00 Local Time  
    int EURStm=9;   // Europe London Session time start: 09:00 Local Time 
    int EURCtm=19;  // Europe London Session time close: 19:00 Local Time  
    int USNStm=8;   // US New York Session time start: 08:00 Local Time 
    int USNCtm=17;  // US New York Session time close: 17:00 Local Time  
    //--
    int nzo = (NZSStm+difhr-NZSGMT)<0 ? 24+(NZSStm+difhr-NZSGMT) : (NZSStm+difhr-NZSGMT);
    int nzc = (NZSCtm+difhr-NZSGMT)<0 ? 24+(NZSCtm+difhr-NZSGMT) : (NZSCtm+difhr-NZSGMT);
    //--
    int auo = (AUSStm+difhr-AUSGMT)<0 ? 24+(AUSStm+difhr-AUSGMT) : (AUSStm+difhr-AUSGMT);
    int auc = (AUSCtm+difhr-AUSGMT)<0 ? 24+(AUSCtm+difhr-AUSGMT) : (AUSCtm+difhr-AUSGMT);
    //--
    int tko = (TOKStm+difhr-TOKGMT)<0 ? 24+(TOKStm+difhr-TOKGMT) : (TOKStm+difhr-TOKGMT);
    int tkc = (TOKCtm+difhr-TOKGMT)<0 ? 24+(TOKCtm+difhr-TOKGMT) : (TOKCtm+difhr-TOKGMT);
    //--
    int euo = (EURStm+difhr-EURGMT)<0 ? 24+(EURStm+difhr-EURGMT) : (EURStm+difhr-EURGMT);
    int euc = (EURCtm+difhr-EURGMT)<0 ? 24+(EURCtm+difhr-EURGMT) : (EURCtm+difhr-EURGMT);
    //--
    int uso = (USNStm+difhr-USNGMT)<0 ? 24+(USNStm+difhr-USNGMT) : (USNStm+difhr-USNGMT);
    int usc = (USNCtm+difhr-USNGMT)<0 ? 24+(USNCtm+difhr-USNGMT) : (USNCtm+difhr-USNGMT);
    if(usc==0||usc==24) usc=23;
    //--
    //---Trading on Custom Session
    int _days00=ThisTime(day);
    int _days10=ThisTime(day);
    if(stsescuh>clsescuh) _days10=ThisTime(day)+1;
    tmopcu=ReqDate(_days00,stsescuh,stsescum); 
    tmclcu=ReqDate(_days10,clsescuh,clsescum); 
    //--
    //--Trading on New Zealand Session GMT/UTC+12
    int _days01=ThisTime(hour)<nzc ? ThisTime(day)-1 : ThisTime(day);
    int _days11=ThisTime(hour)<nzc ? ThisTime(day) : ThisTime(day)+1;
    tmop01=ReqDate(_days01,nzo,0);    // start: 08:00 Local Time == 20:00 GMT/UTC
    tmcl01=ReqDate(_days11,nzc-1,59); // close: 17:00 Local Time == 05:00 GMT/UTC
    //--
    //--Trading on Australia Sydney Session GMT/UTC+10
    int _days02=ThisTime(hour)<auc ? ThisTime(day)-1 : ThisTime(day);
    int _days12=ThisTime(hour)<auc ? ThisTime(day) : ThisTime(day)+1;
    tmop02=ReqDate(_days02,auo,0);    // start: 07:00 Local Time == 21:00 GMT/UTC
    tmcl02=ReqDate(_days12,auc-1,59); // close: 17:00 Local Time == 07:00 GMT/UTC
    //--
    //--Trading on Asia Tokyo Session GMT/UTC+9
    int _days03=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1;
    int _days13=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1;
    tmop03=ReqDate(_days03,tko,0);    // start: 09:00 Local Time == 00:00 GMT/UTC
    tmcl03=ReqDate(_days13,tkc-1,59); // close: 18:00 Local Time == 09:00 GMT/UTC
    //--
    //--Trading on Europe London Session GMT/UTC 00:00
    int _days04=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1;
    int _days14=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1;
    tmop04=ReqDate(_days04,euo,0);     // start: 09:00 Local Time == 09:00 GMT/UTC
    tmcl04=ReqDate(_days14,euc-1,59);  // close: 19:00 Local Time == 19:00 GMT/UTC
    //--
    //--Trading on US New York Session GMT/UTC-5
    int _days05=ThisTime(hour)<usc  ? ThisTime(day) : ThisTime(day)+1;
    int _days15=ThisTime(hour)<=usc ? ThisTime(day) : ThisTime(day)+1;
    tmop05=ReqDate(_days05,uso,0);  // start: 08:00 Local Time == 13:00 GMT/UTC
    tmcl05=ReqDate(_days15,usc,59); // close: 17:00 Local Time == 22:00 GMT/UTC
    //--
    //--Not Use Trading Time Zone
    if(trd_time_zone==No)
      {
        tmopno=ReqDate(ThisTime(day),0,15); 
        tmclno=ReqDate(ThisTime(day),23,59);
      }
    //--
    Time_Zone();
    //--
    return;
//---
  } //-end Set_Time_Zone()
//---------//
void MCEA::Time_Zone(void)
  {
//---
   //--
   tz_ses="";
   //--
   switch(session)
     {
       case Cus_Session:
         {
           SesCuOp=StringToTime(tmopcu);
           SesCuCl=StringToTime(tmclcu);
           zntm=SesCuOp;
           znop=SesCuOp;
           zncl=SesCuCl;
           tz_ses="Custom_Session";
           tz_opn=timehr(stsescuh,stsescum);
           tz_cls=timehr(clsescuh,clsescum);
           break;
         }
       case New_Zealand:
         {
           Ses01Op=StringToTime(tmop01);
           Ses01Cl=StringToTime(tmcl01);
           zntm=Ses01Op;
           znop=Ses01Op;
           zncl=Ses01Cl;
           tz_ses="New_Zealand/Oceania";
           tz_opn=timehr(ReqTime(Ses01Op,hour),ReqTime(Ses01Op,min));
           tz_cls=timehr(ReqTime(Ses01Cl,hour),ReqTime(Ses01Cl,min));
           break;
         }
       case Australia:
         {
           Ses02Op=StringToTime(tmop02);
           Ses02Cl=StringToTime(tmcl02);
           zntm=Ses02Op;
           znop=Ses02Op;
           zncl=Ses02Cl;
           tz_ses="Australia Sydney";
           tz_opn=timehr(ReqTime(Ses02Op,hour),ReqTime(Ses02Op,min));
           tz_cls=timehr(ReqTime(Ses02Cl,hour),ReqTime(Ses02Cl,min));
           break;
         }
       case Asia_Tokyo:
         {
           Ses03Op=StringToTime(tmop03);
           Ses03Cl=StringToTime(tmcl03);
           zntm=Ses03Op;
           znop=Ses03Op;
           zncl=Ses03Cl;
           tz_ses="Asia/Tokyo";
           tz_opn=timehr(ReqTime(Ses03Op,hour),ReqTime(Ses03Op,min));
           tz_cls=timehr(ReqTime(Ses03Cl,hour),ReqTime(Ses03Cl,min));
           break;
         }
       case Europe_London:
         {
           Ses04Op=StringToTime(tmop04);
           Ses04Cl=StringToTime(tmcl04);
           zntm=Ses04Op;
           znop=Ses04Op;
           zncl=Ses04Cl;
           tz_ses="Europe/London";
           tz_opn=timehr(ReqTime(Ses04Op,hour),ReqTime(Ses04Op,min));
           tz_cls=timehr(ReqTime(Ses04Cl,hour),ReqTime(Ses04Cl,min));
           break;
         }
       case US_New_York:
         {
           Ses05Op=StringToTime(tmop05);
           Ses05Cl=StringToTime(tmcl05);
           zntm=Ses05Op;
           znop=Ses05Op;
           zncl=Ses05Cl;
           tz_ses="US/New_York";
           tz_opn=timehr(ReqTime(Ses05Op,hour),ReqTime(Ses05Op,min));
           tz_cls=timehr(ReqTime(Ses05Cl,hour),ReqTime(Ses05Cl,min));
           break;
         }
     }
   //--
   if(trd_time_zone==No)
     {
       SesNoOp=StringToTime(tmopno);
       SesNoCl=StringToTime(tmclno);
       zntm=SesNoOp;
       znop=SesNoOp;
       zncl=SesNoCl;
       tz_ses="Not Use Time Zone";
       tz_opn=timehr(ReqTime(SesNoOp,hour),ReqTime(SesNoOp,min));
       tz_cls=timehr(ReqTime(SesNoCl,hour),ReqTime(SesNoCl,min));
     }
   //--
   return;
//---
  } //-end Time_Zone()
//---------//


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

Um ein Signal zum Eröffnen einer Position 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 rsix=GetRSIxx(symbol);
    int par15=PARSAR15(symbol);
    //--
    if(rsix==rise && par15==rise) ret=rise;
    if(rsix==down && par15==down) ret=down;
    //--
    return(ret);
//---
  } //-end GetOpenPosition()
//---------//

Und die Funktion GetOpenPosition() wird 2 Funktionen aufrufen:

  1. GetRSIxx() Funktion, die den Pufferwert von 2 RSI nimmt und den Signalalgorithmus berechnet.
  2. PARSAR15() Funktion als Filter.

int MCEA::GetRSIxx(const string symbol) // Signal Open Position 
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    int bar=3;
    //--
    double rdif=rsidiff;
    double RSIFast[],
           RSISlow[];
    //--
    ArrayResize(RSIFast,bar,bar);
    ArrayResize(RSISlow,bar,bar);
    ArraySetAsSeries(RSIFast,true);
    ArraySetAsSeries(RSISlow,true);
    //--
    int x=PairsIdxArray(symbol);
    UpdatePrice(symbol,TFt);
    //--
    CopyBuffer(hRSIFast[x],0,0,bar,RSIFast);
    CopyBuffer(hRSISlow[x],0,0,bar,RSISlow);
    //--
    if(RSIFast[1]<=RSISlow[1] && RSIFast[0]>RSISlow[0]+rdif) ret=rise;
    if(RSIFast[1]>=RSISlow[1] && RSIFast[0]<RSISlow[0]-rdif) ret=down;
    //--
    return(ret);
//---
  } //-end GetRSIxx()
//---------//        
int MCEA::PARSAR15(const string symbol) // formula Parabolic SAR M5
  {
//---
   int ret=0;
   int rise=1,
       down=-1;
   int br=2;
//--
   double PSAR[];
   ArrayResize(PSAR,br,br);
   ArraySetAsSeries(PSAR,true);
   int xx=PairsIdxArray(symbol);
   CopyBuffer(hPar15[xx],0,0,br,PSAR);
//--
   RefreshPrice(symbol,TFT15,br);
   double HIG0=iHigh(symbol,TFT15,0);
   double LOW0=iLow(symbol,TFT15,0);
//--
   if(PSAR[0]<LOW0)
      ret=rise;
   if(PSAR[0]>HIG0)
      ret=down;
//--
   return(ret);
//---
  } //-end PARSAR15()
//---------//

Innerhalb der Funktion GetRSIxx() und der Funktion PARSAR15() wird eine Funktion verwendet und aufgerufen, nämlich die FunktionPairsIdxArray().

int xx=PairsIdxArray(symbol);
int MCEA::PairsIdxArray(const string symbol)
  {
//---
    int pidx=-1;
    //--
    for(int x=0; x<arrsymbx; x++)
      {
        if(DIRI[x]==symbol)
          {
            pidx=x;
            break;
          }
      } 
    //--
    return(pidx);
//---
  } //-end PairsIdxArray()
//---------//

Die Funktion PairsIdxArray() wird verwendet, um den Namen des gewünschten Symbols und die Handles seiner Indikatoren zu erhalten. Dann wird das entsprechende Indikator-Handle aufgerufen, um den Pufferwert des RSI-Indikators und des PSAR-Indikators für dieses Symbol und diesen Zeitrahmen zu erhalten.

In diesem Expert Advisor werden wir 2 RSI-Indikatoren verwenden.
Sie haben unterschiedliche Eingabeparameter:

Fast RSI:

  • symbol = das gewünschte Symbol,
  • timeframe = wie im Zeitrahmen des Experten angegeben.
  • ma_period = 10, entsprechend der Periodenlänge für Fast RSI
  • applied_price = PRICE_WEIGHTED, entsprechend dem Fast RSI Applied Price

Slow RSI:

  • symbol = das gewünschte Symbol,
  • timeframe = wie im Zeitrahmen des Experten angegeben.
  • ma_period = 30,entsprechend der Periodenlänge für Slow RSI
  • applied_price = PRICE_WEIGHTED, entsprechend dem Slow RSI Applied Price

    //-- Indicators handle for all symbol
    for(int x=0; x<arrsymbx; x++) 
      {
        hRSISlow[x]=iRSI(DIRI[x],TFt,rsislow,srsiapp);          //-- Handle for the Slow RSI indicator
        hRSIFast[x]=iRSI(DIRI[x],TFt,rsifast,frsiapp);          //-- Handle for the Fast RSI indicator
        hVIDyAv[x]=iVIDyA(DIRI[x],TFt,9,12,0,PRICE_WEIGHTED);   //-- Handle for the VIDYA indicator for Trailing Stop
        hPar05[x]=iSAR(DIRI[x],TFT05,SARstep,SARmaxi);          //-- Handle for the iSAR indicator for M5 Timeframe
        //--
      }

Um also den Pufferwert für jeden RSI-Indikator zu erhalten, kopieren wir jeden Puffer aus dem Indikatoren-Handle.

Kopieren des Fast RSI-Puffers (Puffer 0) vom Fast-RSI-Handle in das Ziel-Array:

CopyBuffer(hRSIFast[x],0,0,bar,RSIFast);

Kopieren des Slow RSI-Puffers (Puffer 0) vom langsamen RSI-Handle in das Ziel-Array:

CopyBuffer(hRSISlow[x],0,0,bar,RSISlow);

Nach Ausführung der beiden Funktionen GetRSIxx() und PARSAR05() liefert die Funktion GetOpenPosition() die Werte:

  • Wert 0, Signal unbekannt.
  • Der Wert 1 ist das Signal für einen Kaufauftrag;
  • Der Wert -1 ist das Signal für einen Verkaufsauftrag.

Wenn die Funktion GetOpenPosition() den Wert 1 zurückgibt, ruft der Expert Advisor die Funktion OpenBuy() auf, um eine Kauforder zu eröffnen.

bool MCEA::OpenBuy(const string symbol) 
  {
//---
    ResetLastError();
    //--
    bool buyopen      = false;
    string ldComm     = GetCommentForOrder()+"_Buy";
    double ldLot      = MLots(symbol);
    ENUM_ORDER_TYPE type_req = ORDER_TYPE_BUY;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    CurrentSymbolSet(symbol);
    double SL=OrderSLSet(symbol,type_req,mc_symbol.Bid());
    double TP=OrderTPSet(symbol,type_req,mc_symbol.Ask());
    //--
    if(RefreshTick(symbol))
       buyopen=mc_trade.Buy(ldLot,symbol,mc_symbol.Ask(),SL,TP,ldComm);
    //--
    int error=GetLastError();
    if(buyopen||error==0)
      {
        string bsopen="Open BUY Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        Do_Alerts(symbol,bsopen);
      }
    else
      {
        mc_trade.CheckResult(check);
        Do_Alerts(Symbol(),"Open BUY order for "+symbol+" FAILED!!. Return code= "+
                 (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
        return(false);   
      }
    //--
    return(buyopen);
    //--
//---
  } //-end OpenBuy
//---------//


Wenn die Funktion GetOpenPosition() den Wert -1 zurückgibt, ruft der Expert Advisor die Funktion OpenSell() auf, um eine Verkaufsorder zu eröffnen.

bool MCEA::OpenSell(const string symbol) 
  {
//---
    ResetLastError();
    //--
    bool selopen      = false;
    string sdComm     = GetCommentForOrder()+"_Sell";
    double sdLot      = MLots(symbol);
    ENUM_ORDER_TYPE type_req = ORDER_TYPE_SELL;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    CurrentSymbolSet(symbol);
    double SL=OrderSLSet(symbol,type_req,mc_symbol.Ask());
    double TP=OrderTPSet(symbol,type_req,mc_symbol.Bid());
    //--
    if(RefreshTick(symbol))
       selopen=mc_trade.Sell(sdLot,symbol,mc_symbol.Bid(),SL,TP,sdComm);
    //--
    int error=GetLastError();
    if(selopen||error==0)

      {
        string bsopen="Open SELL Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        Do_Alerts(symbol,bsopen);
      }
    else
      {
        mc_trade.CheckResult(check);
        Do_Alerts(Symbol(),"Open SELL order for "+symbol+" FAILED!!. Return code= "+
                 (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
        return(false);   
      }
    //--
    return(selopen);
    //--
//---
  } //-end OpenSell
//---------//


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, eine oder mehrere manuelle Schaltflächen für die Verwaltung von Aufträgen und die Änderung von Charts, Zeitrahmen oder Symbolen zu erstellen.

//+------------------------------------------------------------------+
//| 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()
//---------//

In der Gruppe Other Expert Advisor Parameters der Eingabeeigenschaften kann der Händler auswählen, ob Handelsinformationen auf dem Chart angezeigt werden sollen (Yes) oder (No).

Wenn diese Option ausgewählt ist (Yes), werden die Handelsinformationen auf dem Chart angezeigt, auf dem der Expert Advisor durch Aufruf der Funktion TradeInfo() läuft.

Wir haben auch eine Funktion hinzugefügt, um die Zeit gemäß den Bedingungen der Handelszeitzone als Teil der Funktion TradeInfo() zu beschreiben.

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()
//---------//
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 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      :  "+ EnumToString(TFt)+
        "\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()  
//---------//

Die Schnittstelle des Multi-Currency Expert Advisors RSIxRSI_MCEA ist in der folgenden Abbildung dargestellt.

RSIxRSI_Look


Wie Sie sehen können, befinden sich unter dem Namen des Expert Advisors RSIxRSI_MCEA die Schaltflächen „M“, „C“ und „R“.

Wenn Sie auf die Schaltfläche „M“ klicken, wird ein Feld mit Schaltflächen zum manuellen Klicken angezeigt (siehe unten).

Experte_Handbuch_Schaltfläche_01


Der Händler kann Aufträge manuell verwalten, wenn die Schaltfläche für manuelle Klicks angezeigt wird:

1. Set SL/TP All Orders (SL/TP für alle Aufträge einstellen)
Wie oben erklärt, wenn der Händler die Parameter Use Order Stop Loss (No) und/oder Use Order Take Profit (No) eingibt, dann aber Stop Loss oder Take Profit auf alle Aufträge anwenden möchte, dann wird ein einziger Klick auf die Schaltfläche „Set SL / TP All Orders“ alle Aufträge ändern und Stop Loss und/oder Take Profit anwenden.

void MCEA::SetSLTPOrders(void) 
  {
//---
   ResetLastError();
   MqlTradeRequest req={};
   MqlTradeResult  res={};
   MqlTradeCheckResult check={};
   //--
   double modbuysl=0;
   double modselsl=0;
   double modbuytp=0;
   double modseltp=0;
   string position_symbol;
   int totalorder=PositionsTotal();
   //--    
   for(int i=totalorder-1; i>=0; i--) 
     {
       string symbol=PositionGetSymbol(i);
       position_symbol=symbol;
       if(mc_position.Magic()==magicEA)
         {
           ENUM_POSITION_TYPE opstype = mc_position.PositionType();
           if(opstype==POSITION_TYPE_BUY) 
             {
               Pips(symbol);
               RefreshTick(symbol);
               double price    = mc_position.PriceCurrent();
               double pos_open = mc_position.PriceOpen();
               double pos_stop = mc_position.StopLoss();
               double pos_take = mc_position.TakeProfit();
               modbuysl=SetOrderSL(symbol,opstype,pos_open);
               if(price<modbuysl) modbuysl=mc_symbol.NormalizePrice(price-slip*pip);
               modbuytp=SetOrderTP(symbol,opstype,pos_open);
               if(price>modbuytp) modbuytp=mc_symbol.NormalizePrice(price+slip*pip);
               //--
               if(pos_stop==0.0 || pos_take==0.0)
                 {
                   if(!mc_trade.PositionModify(position_symbol,modbuysl,modbuytp))
                     {
                       mc_trade.CheckResult(check);
                       Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+
                                (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
                     }
                 }
             }
           if(opstype==POSITION_TYPE_SELL) 
             {
               Pips(symbol);
               RefreshTick(symbol);
               double price    = mc_position.PriceCurrent();
               double pos_open = mc_position.PriceOpen();
               double pos_stop = mc_position.StopLoss();
               double pos_take = mc_position.TakeProfit();
               modselsl=SetOrderSL(symbol,opstype,pos_open);
               if(price>modselsl) modselsl=mc_symbol.NormalizePrice(price+slip*pip);
               modseltp=SetOrderTP(symbol,opstype,pos_open);
               if(price<modseltp) modseltp=mc_symbol.NormalizePrice(price-slip*pip);
               //--
               if(pos_stop==0.0 || pos_take==0.0)
                 {
                   if(!mc_trade.PositionModify(position_symbol,modselsl,modseltp))
                     {
                       mc_trade.CheckResult(check);
                       Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+
                                (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
                     }
                 }
             }
         }
     }
    //--
    return;
//---
  } //-end SetSLTPOrders
//---------//

2. Close All Orders (Alle Aufträge schließen)
Wenn ein Händler alle Positionen schließen möchte, genügt ein einziger Klick auf die Schaltfläche „Alle Aufträge schließen“, um alle offenen Aufträge zu schließen.

void MCEA::CloseAllOrders(void) //-- function: close all order
   {
//----
    ResetLastError();
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int total=PositionsTotal(); // number of open positions
    //--- iterate over all open positions
    for(int i=total-1; i>=0; i--)
      {
        //--- if the MagicNumber matches
        if(mc_position.Magic()==magicEA)
          { 
            //--
            string position_Symbol   = PositionGetSymbol(i);  // symbol of the position
            ulong  position_ticket   = PositionGetTicket(i);  // ticket of the the opposite position
            ENUM_POSITION_TYPE  type = mc_position.PositionType();
            RefreshTick(position_Symbol);
            bool closepos = mc_trade.PositionClose(position_Symbol,slip);
            //--- output information about the closure
            PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
            //---
          }
      }
   //---
   return;
//----
   } //-end CloseAllOrders()
//---------//

3. Close All Profits (Alle Positionen im Gewinn schließen)
Wenn ein Händler alle bereits profitablen Positionen schließen möchte, genügt ein einziger Klick auf die Schaltfläche „Close All Profits“, um alle offenen Positionen, die bereits profitabel sind, zu schließen.

bool MCEA::ManualCloseAllProfit(void)
   {
//----
    ResetLastError();
    //--
    bool orclose=false;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int ttlorder=PositionsTotal(); // number of open positions
    //--
    for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         orclose=false;
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double pos_profit = mc_position.Profit();
                  double pos_swap   = mc_position.Swap();
                  double pos_comm   = mc_position.Commission();
                  double cur_profit = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
                  ulong  position_ticket = PositionGetTicket(i);
                  //---
                  if(type==POSITION_TYPE_BUY && cur_profit>0.02)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                    }
                  if(type==POSITION_TYPE_SELL && cur_profit>0.02)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                    }
                }
            }
       }
     //--
     return(orclose);
//----
   } //-end ManualCloseAllProfit()
//---------//

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. 
Wenn Sie auf einen der Paar- oder Symbolnamen klicken, wird das Chartsymbol sofort durch das Symbol ersetzt, auf dessen Namen Sie geklickt haben.

Experte_Handbuch_Schaltfläche_02

void CreateSymbolPanel()
  {
//---    
    //--
    ResetLastError();
    DeletePanelButton();
    int sydis=83;
    int tsatu=int(mc.sall/2);
    //--
    CreateButtonTemplate(0,"Template",180,367,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,187,45,true);
    CreateButtonTemplate(0,"TempCCS",167,25,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBlue,clrWhite,CORNER_RIGHT_UPPER,181,50,true);
    CreateButtonClick(0,"X",14,14,"Arial Black",10,BORDER_FLAT,"X",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,22,48,true,"Close Symbol Panel");
    //--
    string chsym="Change SYMBOL";
    int cspos=int(181/2)+int(StringLen(chsym)/2);
    CreateButtontLable(0,"CCS","Bodoni MT Black",chsym,11,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,cspos,62,true,"Change Chart Symbol");
    //--
    for(int i=0; i<tsatu; i++)
      CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,180,sydis+(i*22),true,"Change to "+mc.AS30[i]);
    //--
    for(int i=tsatu; i<mc.sall; i++)
      CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,94,sydis+((i-tsatu)*22),true,"Change to "+mc.AS30[i]);
    //--
    ChartRedraw(0);
    //--
    return;
//---
   } //-end CreateSymbolPanel()
//---------//

In diesem Fall wird die Funktion OnChartEvent() die Funktion ChangeChartSymbol() aufrufen, wenn einer der Symbolnamen angeklickt wird.

   if(id==CHARTEVENT_OBJECT_CLICK) 
     {
       int lensymbol=StringLen(Symbol());
       int lensparam=StringLen(sparam);

       //--- if Symbol button is click
       if(lensparam==lensymbol)
         {
           int sx=mc.ValidatePairs(sparam);
           ChangeChartSymbol(mc.AS30[sx],CCS);
           mc.PanelExtra=false;
         }
       //--
     }
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()
//---------//


Und schließlich wird durch Klicken auf die Schaltfläche R der Multi-Currency Expert Advisor RSIxRSI_MCEA aus dem Chart entfernt, sodass der Händler die Experten nicht manuell entfernen muss.

   if(id==CHARTEVENT_OBJECT_CLICK) 
     {
       //--
       //--- 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);
         }
       //---
     }


Strategietester

Der Vorteil des MetaTrader 5 Strategy Testers ist, dass er Strategien unterstützt, die auf mehreren Symbolen handeln oder den automatischen Handel für alle verfügbaren Symbole und auf allen verfügbaren Zeitrahmen testen.
Daher werden wir auf der MetaTrader 5 Strategy Tester Plattform den RSIxRSI_MCEA Multi-Currency Expert Advisor testen.

Im ersten Test haben wir den RSIxRSI_MCEA auf das XAGUSD-Paar und den H4-Zeitrahmen gelegt, mit einer angepassten Zeitspanne von 2023.10.01 bis 2024.01.05
Der Test wurde mit zwei verschiedenen Eingabeeigenschaften durchgeführt, und zwar in der Parametergruppe Global Strategy EA und der Parametergruppe Trade & Order Management.

1. Der RSIxRSI_MCEA für das Paar XAGUSD und den H4-Zeitrahmen

ST_07_e1

ST_07_e2


Die Ergebnisse des ersten Tests sind in der folgenden Abbildung dargestellt.

ST_07_e3

2. Der RSIxRSI_MCEA für das Paar XAGUSD und den H12-Zeitrahmen

ST_08_e1

ST_08_e2

Die Ergebnisse des zweiten Tests sind in der nachstehenden Abbildung dargestellt.

ST_08_e3


Schlussfolgerung

Die Schlussfolgerung bei der Erstellung eines Multi-Currency Expert Advisors mit Signalen von Fast RSI, die Slow RSI kreuzen, oder RSI cross RSI für den Forex-Handel mit MQL5 ist wie folgt:

  1. Es stellt sich heraus, dass die Erstellung eines Multiwährungs-Expert Advisors in MQL5 sehr einfach ist und sich nicht wesentlich von der Erstellung eines Expert Advisors für eine einzelne Währung unterscheidet.
  2. Die Erstellung eines Multi-Currency Expert Advisors wird die Effizienz und Effektivität der Händler erhöhen, da sie nicht mehr viele Chart-Symbole für den Handel öffnen müssen.
  3. Die Anwendung der richtigen Handelsstrategie erhöht die Gewinnwahrscheinlichkeit im Vergleich zur Verwendung eines Expert Advisors für eine einzige Währung. Das liegt daran, dass Verluste in einem Paar durch Gewinne in anderen Paaren ausgeglichen werden.
  4. Dieser RSIxRSI_MCEA Multi-Currency Expert Advisor ist nur ein Beispiel zum Lernen und zur Ideenfindung. Die Testergebnisse des Strategietesters sind immer noch nicht gut. Daher ist es möglich, durch Experimentieren und Testen mit verschiedenen Zeitrahmen oder Berechnungen verschiedener Indikatorperioden eine bessere Strategie und profitablere Ergebnisse zu erzielen.
  5. Meiner Meinung nach sollte diese RSI-Cross-RSI-Strategie mit verschiedenen Experimenten weiter erforscht werden, beginnend mit dem Zeitrahmen, dem RSI der schnellen Periode, dem RSI der langsamen Periode und dem Differenzierungswert beider RSIs.
  6. Basierend auf den Ergebnissen meiner Experimente auf Strategy Tester, auf Zeitrahmen unter H4 die Ergebnisse sind nicht gut, nur auf Zeitrahmen H4 und darüber, zum Beispiel auf Zeitrahmen H8 und H12, die Ergebnisse sind gut mit wenigen offenen Trades, im Vergleich zu kleinen Zeitrahmen mit vielen offenen Trades, aber in Verlust.

Wir hoffen, dass dieser Artikel und das MQL5 Multi-Currency Expert Advisor Programm für Händler nützlich sein werden, um zu lernen und Ideen zu entwickeln.


Danke fürs Lesen.

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

Beigefügte Dateien |
RSIxRSI_MCEA.mq5 (112.24 KB)
Einführung in MQL5 (Teil 3): Beherrschung der Kernelemente von MQL5 Einführung in MQL5 (Teil 3): Beherrschung der Kernelemente von MQL5
Entdecken Sie die Grundlagen der MQL5-Programmierung in diesem einsteigerfreundlichen Artikel, in dem wir Arrays, nutzerdefinierte Funktionen, Präprozessoren und die Ereignisbehandlung entmystifizieren, wobei jede Codezeile verständlich erklärt wird. Erschließen wir die Leistungsfähigkeit von MQL5 mit einem einzigartigen Ansatz, der das Verständnis bei jedem Schritt sicherstellt. Dieser Artikel legt den Grundstein für die Beherrschung von MQL5, indem er die Erklärung jeder Codezeile hervorhebt und eine eindeutige und bereichernde Lernerfahrung bietet.
Aufbau und Test des Handelssystems Aroon Aufbau und Test des Handelssystems Aroon
In diesem Artikel erfahren wir, wie wir ein Aroon-Handelssystem aufbauen können, nachdem wir die Grundlagen der Indikatoren und die erforderlichen Schritte zum Aufbau eines Handelssystems auf der Grundlage des Aroon-Indikators gelernt haben. Nachdem wir dieses Handelssystem aufgebaut haben, werden wir es testen, um zu sehen, ob es profitabel sein kann oder noch optimiert werden muss.
Implementierung des verallgemeinerten Hurst-Exponenten und des Varianz-Verhältnis-Tests in MQL5 Implementierung des verallgemeinerten Hurst-Exponenten und des Varianz-Verhältnis-Tests in MQL5
In diesem Artikel untersuchen wir, wie der verallgemeinerte Hurst-Exponent und der Varianzverhältnis-Test verwendet werden können, um das Verhalten von Preisreihen in MQL5 zu analysieren.
Datenwissenschaft und maschinelles Lernen (Teil 19): Überladen Sie Ihre AI-Modelle mit AdaBoost Datenwissenschaft und maschinelles Lernen (Teil 19): Überladen Sie Ihre AI-Modelle mit AdaBoost
AdaBoost, ein leistungsstarker Boosting-Algorithmus, der die Leistung Ihrer KI-Modelle steigert. AdaBoost, die Abkürzung für Adaptive Boosting, ist ein ausgeklügeltes Ensemble-Lernverfahren, das schwache Lerner nahtlos integriert und ihre kollektive Vorhersagestärke erhöht.