English Русский 中文 Español 日本語 Português
preview
Wie man einen einfachen EA für mehrere Währungen mit MQL5 erstellt (Teil 2): Indikator-Signale: Multi-Zeitrahmen Parabolic SAR Indikator

Wie man einen einfachen EA für mehrere Währungen mit MQL5 erstellt (Teil 2): Indikator-Signale: Multi-Zeitrahmen Parabolic SAR Indikator

MetaTrader 5Beispiele | 26 Januar 2024, 13:12
429 0
Roberto Jacobs
Roberto Jacobs

Einführung

Die Definition eines Mehr-Währungs-EA in diesem Artikel ist ein Expert Advisor oder Handelsroboter, der mehr als 1 Symbolpaar von nur einem Symbolchart aus handeln kann (z.B. Aufträge eröffnen, schließen und verwalten, Trailing Stop Loss und Trailing Profit), wobei in diesem Artikel der Expert Advisor 30 Paare handeln wird. Dieses Mal werden wir nur 1 Indikator verwenden, nämlich Parabolic SAR oder iSAR in mehreren Zeitrahmen von PERIOD_M15 bis PERIOD_D1

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

Daher ist das Ziel, die wesentlichen Bedürfnisse der Händler, die effiziente und effektive Handelsroboter wollen zu erfüllen, sodass durch den Rückgriff auf die Stärken, Fähigkeiten und Einrichtungen, die von der sehr zuverlässigen MQL5, können wir eine einfache Mehr-Währungs-EA, die in diesem Artikel verwendet Indicator Signals erstellen: Multi-Zeitrahmen Parabolic SAR oder iSAR Indikator.



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.

Anmerkung: Alle diese Symbole oder Paare sind Symbole oder Paare, die üblicherweise von Brokern verwendet werden. Daher funktioniert dieser Mehr-Währungs-EAs nicht mit Brokern, deren Symbol- oder Paarnamen Präfixe oder Suffixe enthalten.


2. Indikatoren.

Der Mehr-Währungs-EA verwendet 1 Indikatorsignal, aber mit 5 Zeitrahmen, und zwar PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4 und PERIOD_D1.

In diesem Expert Advisor wird kein fester Zeitrahmen für die Berechnung der Indikatorsignale verwendet, sodass es nicht notwendig ist, den Zeitrahmen für die Signalberechnung zu bestimmen.

Das bedeutet, dass der FXSAR_MTF_MCEA Expert Advisor auf jedem Zeitrahmen von PERIOD_M1 bis PERIOD_MN1 eingesetzt werden kann und FXSAR_MTF_MCEA weiterhin Signale auf Basis von iSAR PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4 und PERIOD_D1 berechnet.

Diese fünf Zeitrahmen des Parabolic SAR bestimmen das Signal für das Eröffnen von Aufträge.

Um Aufträge zu schließen, wenn das Signal schwächer wird, verwenden Sie den iSAR-Indikator PERIOD_M15, vorausgesetzt, der Auftrag befindet sich in der Gewinnphase.

Und für Trailing-Stop und Trailing-Profit verwenden wir den iSAR-Indikator PERIOD_H1.


Die Formel und die Bedingung der Strategie für die iSAR Signale:

UP = (PRICE_LOW[0] ist größer als iSAR Line) oder PRICE_LOW[0] > iSAR[0]

DOWN = (PRICE-HIGH[0] ist kleiner als iSAR Line) oder PRICE-HIGH[0] < iSAR[0]

Wo wir ein KAUF- oder VERKAUFS-Signal erhalten:

Die fünf Zeitrahmen des iSAR-Indikators müssen insgesamt 5 x UP für BUY und 5 x DOWN für SELL betragen.

Eine Illustration des iSAR-Indikators von BUY und SELL ist in Abbildung 1 zu sehen.

iSAR_Signal_Kaufen und Verkaufen


3. Handels- & Auftragsmanagement

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

1. Stop-Loss-Aufträge.   

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

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

Bei der Option Use Order Stop Loss (Yes), gibt es eine weitere Option: Use Automatic Calculation Stop Loss (Yes) or (No) (Autom. Berechnung des Stop Loss verwenden, Ja oder Nein)            

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

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

Wenn die Option Use Order Stop Loss (No) gewählt wurde, dann wird der Experte für jede geöffnete Order prüfen, ob die Signalbedingung noch gut ist und die Order            

mit Gewinn aufrechterhalten werden kann ODER ob die Signalbedingung sich abgeschwächt hat und die Order geschlossen werden muss, um den Gewinn zu sichern            

oder ob die Signalbedingung die Richtung umgekehrt hat und die Order mit Verlust geschlossen werden muss.


2. Take-Profit-Aufträge.

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

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

Bei der Option Use Order Take Profit (Yes) gibt es die weitere Option: Take-Profit automatisch berechnen, Ja (Yes) oder Nein (No).

Wenn die Option Automatische Berechnung Order Take Profit (Ja), dann wird die Berechnung der Take Profit Order automatisch vom Experten durchgeführt.

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


3. Trailing Stop und Trailing Take-Profit
  • Optionen: Use Trailing SL/TP (Yes) or (No) (Nachlaufende SL/TP verwenden, Ja oder Nein)
Wenn die Option Use Trailing SL/TP (No) gewählt wurde, wird der Experte keinen Trailing-Stop-Loss und keinen Trailing-Take-Profit durchführen. Wenn die Option Nachlaufende SL/TP verwendet wird (Ja), gibt es wieder die Option: Use Automatic Trailing (Yes) or (No) (Autom. Nachlauf verwenden, Ja oder Nein). Wenn Sie die Option Use Automatic Trailing (Yes) wählen, wird der Trailing-Stop vom Experten unter Verwendung des Parabolic SAR-Wertes PERIOD_H1 ausgeführt, wobei gleichzeitig ein Trailing-Profit auf Basis des variablen Wertes TPmin (Trailing Profit Value) gemacht wird. Bei der Option Use Automatic Trailing (No) wird der Trailing-Stop vom Experten anhand des Wertes in der Eingabeeigenschaft ausgeführt.
Anmerkung: Der Experte führt einen Trailing-Take-Profit gleichzeitig mit einem Trailing-Stop aus.


4. Manuelle Auftragsverwaltung.

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

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

Wenn der Händler-Eingabeparameter Use Order Stop Loss (No) und/oder Use Order Take Profit (No) einstellt,

Wenn der Händler jedoch beabsichtigt, Stop-Loss oder Take-Profit für alle Aufträge zu verwenden, dann werden mit einem einzigen Klick auf die Schaltfläche „Set SL / TP All Orders“ (SL / TP für alle Aufträge setzen) alle Aufträge geändert und ein Stop-Loss und/oder Take-Profit angewendet.


2. Close All Orders (Alle Aufträge schließen)

Wenn ein Händler alle Aufträge schließen möchte, dann werden mit einem einzigen Klick auf die Schaltfläche „Close All Orders“ alle offenen Aufträge geschlossen.


3. Close All Orders Profit (Alle Aufträge im Gewinn schließen)

Wenn ein Händler alle Positionen, die bereits profitabel sind, mit einem einzigen Klick auf die Schaltfläche „Close All Orders Profit“ schließen möchte, dann 

dann werden alle offenen Aufträge, die bereits rentabel sind, geschlossen.


5. Verwaltung von Aufträgen und Symbolen.

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



Umsetzung der Planung im Programm MQL5

1. Eingabe des Programmkopf und der Eigenschaften.

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 YN wird für die Optionen (Ja) oder (Nein) in den Experteneingabeeigenschaften verwendet.

enum YN
 {
   No,
   Yes
 };


Die Enumeration zur Bestimmung der Losgröße

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


Eigenschaften der Eingabe des Experten:

//---
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
//--Day Trading On/Off
input group               "=== Day Trading On/Off ==="; // Day Trading On/Off
input YN                    ttd0 = No;               // Select Trading on Sunday (Yes) or (No)
input YN                    ttd1 = Yes;              // Select Trading on Monday (Yes) or (No)
input YN                    ttd2 = Yes;              // Select Trading on Tuesday (Yes) or (No)
input YN                    ttd3 = Yes;              // Select Trading on Wednesday (Yes) or (No)
input YN                    ttd4 = Yes;              // Select Trading on Thursday (Yes) or (No)
input YN                    ttd5 = Yes;              // Select Trading on Friday (Yes) or (No)
input YN                    ttd6 = No;               // Select Trading on Saturday (Yes) or (No)
//--Trade & Order management Parameter
input group               "=== Trade & Order management Parameter ==="; // Trade & Order management Parameter
input YN                  use_sl = No;               // Use Order Stop Loss (Yes) or (No)
input YN                  autosl = Yes;              // Use Automatic Calculation Stop Loss (Yes) or (No)
input double               SLval = 30;               // If Not Use Automatic SL - Input SL value in Pips
input YN                  use_tp = Yes;               // Use Order Take Profit (Yes) or (No)
input YN                  autotp = Yes;              // Use Automatic Calculation Take Profit (Yes) or (No)
input double               TPval = 10;               // If Not Use Automatic TP - Input TP value in Pips
input YN            TrailingSLTP = Yes;              // Use Trailing SL/TP (Yes) or (No)
input YN                 autotrl = Yes;              // Use Automatic Trailing (Yes) or (No)
input double               TSval = 5;                // If Not Use Automatic Trailing Input Trailing value in Pips
input double               TSmin = 5;                // Minimum Pips to start Trailing Stop
input double               TPmin = 25;               // Input Trailing Profit Value in Pips
input YN           Close_by_Opps = Yes;              // Close Trade By Opposite Signal (Yes) or (No)
input YN               SaveOnRev = Yes;              // Close Trade and Save profit due to weak signal (Yes) or (No)
//--Others Expert Advisor Parameter
input group               "=== Others Expert Advisor Parameter ==="; // Others EA Parameter
input YN                  alerts = Yes;              // Display Alerts / Messages (Yes) or (No)
input YN           UseEmailAlert = No;               // Email Alert (Yes) or (No)
input YN           UseSendnotify = No;               // Send Notification (Yes) or (No)
input YN      trade_info_display = Yes;              // Select Display Trading Info on Chart (Yes) or (No)
input ulong               magicEA = 2023102;          // Expert ID (Magic Number)
//---


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

//+------------------------------------------------------------------+
//| 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;
    int              posCur1,
                     posCur2;        
    //--
    double           LotPS;
    double           slv,
                     tpv,
                     pip,
                     xpip;
    double           differ;                 
    double           floatprofit,
                     fixclprofit;
    //--
    string           pairs,
                     hariini,
                     daytrade,
                     trade_mode;
    //--
    double           OPEN[],
                     HIGH[],
                     LOW[],
                     CLOSE[];
    datetime         TIME[];
    datetime         closetime;
     
    //------------
    int              DirectionMove(const string symbol);
    int              GetPSARSignalMTF(string symbol);
    int              PARSAR05(const string symbol);
    int              PARSARMTF(const string symbol,ENUM_TIMEFRAMES mtf);
    int              LotDig(const string symbol);
    //--
    double           MLots(const string symbx);
    double           NonZeroDiv(double val1,double val2);
    double           OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
    double           OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
    double           SetOrderSL(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
    double           SetOrderTP(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
    double           TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type);
    //--
    string           ReqDate(int d,int h,int m);
    string           TF2Str(ENUM_TIMEFRAMES period);
    string           timehr(int hr,int mn);
    string           TradingDay(void);
    string           AccountMode();
    string           GetCommentForOrder(void)             { return(expname); }
    //------------

    public:
    
    //-- FXSAR_MTF_MCEA Config --
    string           DIRI[],
                     AS30[];
    string           expname;
    int              hPar05[];   // Handle for the iSAR indicator for M5 Timeframe
    int              hPSAR[][5]; // Handle Indicator, where each Symbol has 5 arrays for Timeframe starting from TF_M15 to TF_D1
    int              ALO,
                     dgts,
                     arrsar,
                     arrsymbx;
    int              sall,
                     arper;
    ulong            slip;        
    //--
    double           SARstep,
                     SARmaxi;
    double           profitb[],
                     profits[];
    //--
    int              Buy,
                     Sell;
    int              ccur,
                     psec,
                     xtto,
                     TFArrays,
                     checktml;
    int              OpOr[],xob[],xos[];         
    //--
    int              year,  // Year 
                     mon,   // Month 
                     day,   // Day 
                     hour,  // Hour 
                     min,   // Minutes 
                     sec,   // Seconds 
                     dow,   // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) 
                     doy;   // Day number of the year (January 1st is assigned the number value of zero)
    //--
    ENUM_TIMEFRAMES  TFt,
                     TFT05,
                     TFSAR[];
    //--
    bool             PanelExtra;
    //------------
                     MCEA(void);
                     ~MCEA(void);            
    //------------
    virtual void     FXSAR_MTF_MCEA_Config(void);
    virtual void     ExpertActionTrade(void);
    //--
    void             ArraySymbolResize(void);
    void             CurrentSymbolSet(const string symbol);
    void             Pips(const string symbol);
    void             TradeInfo(void);
    void             Do_Alerts(const string symbx,string msgText);
    void             CheckOpenPMx(const string symbx);
    void             SetSLTPOrders(void);
    void             CloseBuyPositions(const string symbol);
    void             CloseSellPositions(const string symbol);
    void             CloseAllOrders(void);
    void             CheckClose(const string symbx);
    void             TodayOrders(void);
    void             UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf);
    void             RefreshPrice(const string symbx,ENUM_TIMEFRAMES xtf,int bars);
    //--
    bool             RefreshTick(const string symbx);  
    bool             TradingToday(void);
    bool             OpenBuy(const string symbol);
    bool             OpenSell(const string symbol);
    bool             ModifyOrderSLTP(double mStop,double ordtp);
    bool             ModifySLTP(const string symbx,int TS_type);          
    bool             CloseAllProfit(void);
    bool             ManualCloseAllProfit(void);
    //--
    int              PairsIdxArray(const string symbol);
    int              TFIndexArray(ENUM_TIMEFRAMES TF);
    int              GetOpenPosition(const string symbol);
    int              GetCloseInWeakSignal(const string symbol,int exis);
    int              ThisTime(const int reqmode);
    //--
    string           getUninitReasonText(int reasonCode);
    //------------
//---
  }; //-end class MCEA


Die allererste und wichtigste Funktion im Arbeitsprozess des Mehr-Währungs-EAs, die von OnInit() aufgerufen wird, ist FXSAR_MTF_MCEA_Config().

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//---
   mc.FXSAR_MTF_MCEA_Config();
   //--
   return(INIT_SUCCEEDED);
//---
  } //-end OnInit()


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

//+------------------------------------------------------------------+
//| Expert Configuration                                             |
//+------------------------------------------------------------------+
void MCEA::FXSAR_MTF_MCEA_Config(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
    //--
    sall=ArraySize(All30);
    ArrayResize(AS30,sall,sall);
    ArrayCopy(AS30,All30,0,0,WHOLE_ARRAY);
    //--
    arrsymbx=sall;
    ArraySymbolResize();
    ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY);
    for(int x=0; x<arrsymbx; x++) {SymbolSelect(DIRI[x],true);}
    pairs="Multi Currency 30 Pairs";
    //--
    TFT05=PERIOD_M5;
    ENUM_TIMEFRAMES TFA[]={PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4,PERIOD_D1};
    TFArrays=ArraySize(TFA);
    ArrayResize(TFSAR,TFArrays,TFArrays);
    ArrayCopy(TFSAR,TFA,0,0,WHOLE_ARRAY);
    //--
    TFt=TFSAR[2];
    //--
    //-- iSAR Indicators handle for all symbol
    for(int x=0; x<arrsymbx; x++) 
      {
        hPar05[x]=iSAR(DIRI[x],TFT05,SARstep,SARmaxi);  //-- Handle for the iSAR indicator for M5 Timeframe
        //--
        for(int i=0; i<TFArrays; i++)
          {
            hPSAR[x][i]=iSAR(DIRI[x],TFSAR[i],SARstep,SARmaxi); // Handle for iSAR Indicator array sequence of the requested timeframe
          }
      }
    //--
    ALO=(int)mc_account.LimitOrders()>arrsymbx ? arrsymbx : (int)mc_account.LimitOrders();
    //--
    LotPS=(double)ALO;
    //--
    mc_trade.SetExpertMagicNumber(magicEA);
    mc_trade.SetDeviationInPoints(slip);
    mc_trade.SetMarginMode();
    //--
    return;
//---
  } //-end FXSAR_MTF_MCEA_Config()


2. Experten-Tick-Funktion

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

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


Die Funktion ExpertActionTrade() führt alle Aktivitäten aus und verwaltet den automatischen Handel, angefangen bei Eröffnen und Schließen der Positionen, den Trailing Stops oder Trailing Profits und anderen zusätzlichen Aktivitäten.

Der Ablauf des Arbeitsprozesses ist wie folgt, wie ich am Rande des Programms erklärt habe.

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


3. Wie erhalten wir die Handelssignale für das Öffnen oder Schließen von Positionen?

Um das Indikatorsignal zu erhalten, müssen wir die Funktion GetOpenPosition(Symbol) aufrufen, um ein Handelssignal für eine offene Position zu erhalten.

int MCEA::GetOpenPosition(const string symbol) // Signal Open Position 
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    //--
    int dirmov=DirectionMove(symbol);
    int parsOp=GetPSARSignalMTF(symbol);
    //--
    if(parsOp==rise && dirmov==rise) ret=rise;
    if(parsOp==down && dirmov==down) ret=down;
    //--
    return(ret);
//---
  } //-end GetOpenPosition()

Die Funktion GetOpenPosition() ruft 2 Signalfunktionen auf und speichert sie in der Variablen OpOr[].

1. DirectionMove(symbol); //-- Die Funktion prüft, ob sich der Preis auf dem Candlestick-Balken im Expertenzeitraum bewegt.
2. GetPSARSignalMTF(symbol); //-- Funktion zur Berechnung der Parabolic iSAR Formel für den angeforderten Zeitrahmen.
int MCEA::GetPSARSignalMTF(string symbol) // iSAR MTF signal calculation
  {
//---
    int mv=0;
    int rise=1,
        down=-1;
    //--
    int sarup=0,
        sardw=0;
    //--    
    for(int x=0; x<TFArrays; x++) // The TFArrays variable has a value of 5 which is taken from the number of time frames from TF_M1 to TF_H1.
      {
        if(PARSARMTF(symbol,TFSAR[x])>0) sarup++;
        if(PARSARMTF(symbol,TFSAR[x])<0) sardw++;
      }   
    //--
    if(sarup==TFArrays) mv=rise;
    if(sardw==TFArrays) mv=down;
    //--
    return(mv);
//---
  } //- end GetPSARSignalMTF()


Die Funktion GetPSARSignalMTF() ruft eine Funktion PARSARMTF() auf, die das iSAR-Signal entsprechend dem gewünschten Zeitrahmen berechnet.

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

1. int xx= PairsIdxArray(Symbol)

2. int tx=TFIndexArray(mtf).

Die Funktion PairsIdxArray() wird verwendet, um den Namen des angeforderten Symbols zu erhalten, und die Funktion TFIndexArray() wird verwendet, um die Zeitrahmen-Array-Sequenz des angeforderten Zeitrahmens zu erhalten.

Dann wird das entsprechende Indikator-Handle aufgerufen, um den Pufferwert des iSAR-Indikators für den angeforderten Zeitrahmen zu erhalten.

int MCEA::PARSARMTF(const string symbol,ENUM_TIMEFRAMES mtf) // formula Parabolic iSAR on the requested Timeframe
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    //--
    int br=2;
    //--
    double PSAR[];
    ArrayResize(PSAR,br,br);
    ArraySetAsSeries(PSAR,true);
    int xx=PairsIdxArray(symbol);
    int tx=TFIndexArray(mtf);
    CopyBuffer(hPSAR[xx][tx],0,0,br,PSAR);
    //--
    double OPN0=iOpen(symbol,TFSAR[tx],0);
    double HIG0=iHigh(symbol,TFSAR[tx],0);
    double LOW0=iLow(symbol,TFSAR[tx],0);
    double CLS0=iClose(symbol,TFSAR[tx],0);
    //--
    if(PSAR[0]<LOW0 && CLS0>OPN0) ret=rise;
    if(PSAR[0]>HIG0 && CLS0<OPN0) ret=down;
    //--
    return(ret);
//---
  } //-end PARSARMTF()


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

int MCEA::TFIndexArray(ENUM_TIMEFRAMES TF)
  {
//---
    int res=-1;
    //--
    for(int x=0; x<TFArrays; x++)
      {
        if(TF==TFSAR[x])
          {
            res=x;
            break;
          }
      }
    //--
    return(res);
//---
  } //-end TFIndexArray() 


4. Die Funktion ChartEvent


Um die Effektivität und Effizienz bei der Verwendung von Mehr-Währungs-EAs zu unterstützen, wird es als notwendig erachtet, manuelle Schaltflächen für die Verwaltung von Aufträgen und das Ändern von Charts oder Symbolen einzurichten.
//+------------------------------------------------------------------+
//| 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.PairsIdxArray(sparam);
           ChangeChartSymbol(mc.AS30[sx],CCS);
           mc.PanelExtra=false;
         }
       //--
     }
    //--
    return;
//---
  } //-end OnChartEvent()


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

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


Wenn die Option in der Experteneigenschaft Display Trading Info on Chart (Handelsinformationen auf dem Chart anzeigen) auf „Ja“ gesetzt ist, dann werden auf dem Chart, auf dem der Expertenberater platziert ist, Handelsinformationen durch den Aufruf der Funktion TradeInfo() angezeigt.

void MCEA::TradeInfo(void) // function: write comments on the chart
  {
//----
   Pips(Symbol());
   double spread=SymbolInfoInteger(Symbol(),SYMBOL_SPREAD)/xpip;
   //--
   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     ------------------------------------------------------------"+ 
      "\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 Mehr-Währungs-EA FXSAR_MTF_MCEA sieht wie in der folgenden Abbildung aus.

FXSAR_MTF_MCEA_Blick


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

Wenn die Schaltfläche „M“ oder „C“ angeklickt wird, wird ein manuelles Schaltflächenfeld angezeigt (siehe unten).

MCR_Kombinieren

Wenn die Schaltfläche M angeklickt wird, wird ein manuelles Schaltfeld angezeigt, über das der Händler Aufträge verwalten kann:

1. Set SL/TP All Orders (SL/TP für alle Aufträge einstellen)

2. Close All Orders (Alle Aufträge schließen)

3. Close All Profits (Alle Positionen im Gewinn schließen)

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

Wenn die Schaltfläche R angeklickt wird, wird der Mehr-Währungs-EA FXSAR_MTF_MCEA aus dem Chart entfernt.



Strategietester

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

Bei dieser Gelegenheit werden wir FXSAR_MTF_MCEA als Multi-Timeframe und Mehr-Währungs-EA auf der MetaTrader 5 Strategy Tester Plattform testen.




Schlussfolgerung

Die Schlussfolgerung bei der Erstellung eines Multi-Currency und Multi-Timeframe Expert Advisors mit MQL5 ist wie folgt:

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


Anmerkung:

Wenn Sie eine Idee für die Erstellung eines einfachen Mehr-Währungs-EA auf der Grundlage der eingebauten MQL5-Standardindikatoren haben, schlagen Sie sie bitte in den Kommentaren vor.

Wir hoffen, dass dieser Artikel und das MQL5 Mehr-Währungs-EA-Programm für Händler beim Lernen und Entwickeln von Ideen nützlich sein werden. Danke fürs Lesen.

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

Beigefügte Dateien |
FXSAR_MTF_MCEA.mq5 (80.52 KB)
Fertige Vorlagen für die Verwendung von Indikatoren in Expert Advisors (Teil 1): Oszillatoren Fertige Vorlagen für die Verwendung von Indikatoren in Expert Advisors (Teil 1): Oszillatoren
Der Artikel berücksichtigt Standardindikatoren aus der Kategorie der Oszillatoren. Wir werden gebrauchsfertige Vorlagen für ihre Verwendung in EAs erstellen — Deklaration und Einstellung von Parametern, Initialisierung und Deinitialisierung von Indikatoren sowie das Abrufen von Daten und Signalen aus den Indikatorpuffern in den EAs.
Schätzung der zukünftigen Leistung mit Konfidenzintervallen Schätzung der zukünftigen Leistung mit Konfidenzintervallen
In diesem Artikel befassen wir uns mit der Anwendung von Bootstrapping-Techniken (Bootstrapping: am eigenen Schopf aus dem Sumpf ziehen) als Mittel zur Schätzung der künftigen Leistung einer automatisierten Strategie.
Datenkennzeichnung für die Zeitreihenanalyse (Teil 3):Beispiel für die Verwendung von Datenkennzeichnungen Datenkennzeichnung für die Zeitreihenanalyse (Teil 3):Beispiel für die Verwendung von Datenkennzeichnungen
In dieser Artikelserie werden verschiedene Methoden zur Kennzeichnung (labeling) von Zeitreihen vorgestellt, mit denen Daten erstellt werden können, die den meisten Modellen der künstlichen Intelligenz entsprechen. Eine gezielte und bedarfsgerechte Kennzeichnung von Daten kann dazu führen, dass das trainierte Modell der künstlichen Intelligenz besser mit dem erwarteten Design übereinstimmt, die Genauigkeit unseres Modells verbessert wird und das Modell sogar einen qualitativen Sprung machen kann!
Entwicklung eines MQTT-Clients für MetaTrader 5: ein TDD-Ansatz — Teil 3 Entwicklung eines MQTT-Clients für MetaTrader 5: ein TDD-Ansatz — Teil 3
Dieser Artikel ist der dritte Teil einer Serie, die unsere Entwicklungsschritte für einen nativen MQL5-Client für das MQTT-Protokoll beschreibt. In diesem Teil wird detailliert beschrieben, wie wir die testgetriebene Entwicklung nutzen, um den Teil des Betriebsverhaltens des CONNECT/CONNACK-Paketaustauschs zu implementieren. Am Ende dieses Schritts MUSS unser Client in der Lage sein, sich angemessen zu verhalten, wenn er mit einem der möglichen Ergebnisse eines Verbindungsversuchs auf dem Server konfrontiert wird.