English Русский Español Deutsch 日本語
preview
Criando um Expert Advisor simples multimoeda usando MQL5 (Parte 2): Sinais do indicador - Parabolic SAR multiframe

Criando um Expert Advisor simples multimoeda usando MQL5 (Parte 2): Sinais do indicador - Parabolic SAR multiframe

MetaTrader 5Exemplos | 11 março 2024, 17:06
148 0
Roberto Jacobs
Roberto Jacobs

Introdução

Neste artigo, por EA multimoeda, entendemos um robô investidor ou um robô de negociação que pode negociar (abrir/fechar ordens, gerenciar ordens como trailing-stop-loss e trailing profit) mais de um par de moedas em um gráfico. Neste artigo, o robô investidor negociará 30 pares. Desta vez, usaremos apenas um indicador, o Parabolic SAR ou iSAR, em vários timeframes, começando com PERIOD_M15 e terminando com PERIOD_D1.

Sabemos que a negociação multimoeda, tanto no terminal de negociação quanto no testador de estratégias, é possível graças ao poder e às capacidades do MQL5.

Assim, o objetivo é atender às necessidades básicas dos traders que precisam de robôs de negociação eficazes e práticos. Confiando nas fortalezas e capacidades do MQL5, podemos criar um simples EA multimoeda que, neste artigo, utiliza o Parabolic SAR multiframe ou iSAR.



Características

1. Pares de negociação.

O robô investidor negociará nos seguintes pares:

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 pairs

Mais 2 pares de metais: XAUUSD (ouro) e XAGUSD (prata).

Total de 30 pares.

Nota: Todos esses pares são normalmente oferecidos por corretoras. Portanto, este EA multimoeda não funcionará com corretoras cujos nomes de símbolos ou pares tenham prefixos ou sufixos.


2. Indicadores de sinal.

O EA multimoeda usará 1 sinal de indicador em 5 timeframes, começando com PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, e PERIOD_D1.

Este EA não utiliza um timeframe fixo para o cálculo dos sinais dos indicadores, portanto, não é necessário definir o timeframe de cálculo do sinal.

Isso significa que o EA FXSAR_MTF_MCEA pode ser usado em qualquer timeframe de PERIOD_M1 a PERIOD_MN1, e o FXSAR_MTF_MCEA ainda calculará os sinais com base no iSAR PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, e PERIOD_D1.

Estes cinco timeframes do Parabolic SAR definirão o sinal para abrir ordens.

Entretanto, para fechar ordens quando o sinal enfraquecer, usamos o indicador iSAR PERIOD_M15, desde que a ordem esteja em estado de lucro.

Para usar o trailing-stop e o trailing profit, utilizamos o iSAR PERIOD_H1.


A fórmula da estratégia de estado dos sinais iSAR:

UP (para cima) = (PRICE_LOW[0] maior que a linha iSAR) ou PRICE_LOW[0] > iSAR[0]

DOWN (para baixo) = (PRICE_HIGH[0] menor que a linha iSAR) ou PRICE_HIGH[0] < iSAR[0]

Onde obter o sinal de COMPRA ou VENDA:

Os cinco timeframes do indicador iSAR devem somar 5 x UP para COMPRA e 5 x DOWN para VENDA.

Na figura 1, mostra-se o indicador iSAR.

iSAR_Signal_Buy e Sell


3. Gestão de operações e ordens

A gestão de operações neste EA multimoeda tem várias opções:

1. Ordens de stop-loss.   

  • Opções: Use Order Stop Loss (Yes) ou (No) - usar ordem de stop-loss: sim ou não           

Ao escolher Use Order Stop Loss (No), todas as ordens serão abertas sem stop-loss.            

Ao escolher Use Order Stop Loss (Yes), surge novamente a escolha: Use Automatic Calculation Stop Loss (Yes) ou (No) - usar cálculo automático de stop-loss: sim ou não            

Ao escolher Automatic Calculation Stop Loss (Yes), o stop-loss é calculado pelo EA.

Ao escolher Automatic Calculation Stop Loss (No), o trader precisa inserir o valor do stop-loss em pips.

Ao escolher Use Order Stop Loss (No), o EA verificará a execução das condições do sinal. Se elas forem atendias,            

a ordem é mantida. Se o sinal enfraquecer, a ordem deve ser fechada para preservar o lucro            

ou se o sinal indicar uma mudança de direção, e a ordem deve ser fechada com perda.


2. Ordens de take-profit

  • Opções: Use Order Take Profit (Yes) ou (No) - usar take-profit da ordem: sim ou não

Ao escolher Use Order Take Profit (Não), todas as ordens serão abertas sem take-profit.

Ao escolher Use Order Take Profit (Yes), surge novamente a opção: Use Automatic Calculation Order Take Profit (Yes) ou (No) - usar take-profit calculado automaticamente: sim ou não

Ao escolher Automatic Calculation Order Take Profit (Yes), o take-profit é calculado pelo EA.

Ao escolher Automatic Calculation Order Take Profit (No), o trader precisa inserir o valor do take-profit em pips.


3. Trailing stop e trailing take-profit
  • Opções: Use Trailing SL/TP (Yes) ou (No) - usar stop-loss/take-profit de trailing: sim ou não
Com a opção Use Trailing SL/TP (No), o EA não usará stop-loss e take-profit de trailing. Com Use Trailing SL/TP (Yes), uma nova escolha é fornecida - Use Automatic Trailing (Yes) ou (No) (usar autotrailing). Com Use Automatic Trailing (Yes), o trailing-stop é executado pelo EA usando o valor do Parabolic SAR PERIOD_H1, ao mesmo tempo ganhando um lucro móvel com base no valor da variável TPmin (valor do lucro móvel). Com Use Automatic Trailing (No), o trailing-stop é executado pelo EA usando o valor do parâmetro de entrada.
Nota: O EA executa o trailing do take-profit simultaneamente com o trailing-stop.


4. Gestão manual de ordens.

Para aumentar a eficiência, serão adicionados vários botões.

1. Set SL / TP All Orders (definir stop-loss/take-profit para todas as ordens)

Se o trader configurar Use Order Stop Loss (No) e/ou Use Order Take Profit (No),

mas depois desejar usar stop-loss ou take-profit para todas as ordens, ele precisará apenas clicar no botão Set SL / TP All Orders para alterar todas as ordens e aplicar stop-loss e/ou take-profit.


2. Close All Orders (fechar todas as ordens)


3. Close All Orders Profit (fechar todas as ordens lucrativas)

Se o trader deseja fechar todas as ordens que já são lucrativas, basta um clique no botão Close All Orders Profit 

para fechar todas as ordens lucrativas abertas.


5. Gestão de ordens e gráficos de símbolos.

Uma função muito útil para EAs multimoeda, que operam 30 pares de um único gráfico, será ter um painel unificado de botões para que os traders possam mudar gráficos ou símbolos com um clique do mouse.



Implementação em um programa MQL5

1. Título do programa e parâmetros de entrada.

Inclusão do arquivo de cabeçalho em MQL5

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


A enumeração YN é usada para opções (Yes) ou (No) nos parâmetros do EA.

enum YN
 {
   No,
   Yes
 };


A enumeração para usar o tamanho do lote na gestão de capital

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


Parâmetros de entrada do EA:

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


Para declarar todas as variáveis, objetos e funções necessários neste EA multimoeda, criaremos uma classe para especificar a estrutura e as configurações operacionais do EA.

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


A primeira e principal função no funcionamento do EA multimoeda, chamada de OnInit(), é FXSAR_MTF_MCEA_Config().

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


Na função FXSAR_MTF_MCEA_Config(), configuram-se todos os símbolos utilizados, todos os manipuladores usados e algumas funções importantes do arquivo de cabeçalho include.

//+------------------------------------------------------------------+
//| 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. Função Expert tick

Na função Expert tick (OnTick()), chamaremos uma das funções principais do EA multimoeda, a saber, a função ExpertActionTrade().

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


A função ExpertActionTrade() executará todas as ações e gerenciará a negociação automática, incluindo a abertura/fechamento de ordens, trailing-stop, trailing take-profit, e outras ações adicionais.

A sequência de trabalho é a seguinte.

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. Recuperação de sinais de negociação para abrir/fechar posições

Para obter o sinal do indicador, chamaremos a função GetOpenPosition(symbol) para obter o sinal de abertura.

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

A função GetOpenPosition() chamará duas funções de sinal e as salvará na variável OpOr[].

1. DirectionMove(symbol);         //-- Função para verificar a presença de preço na barra de vela no timeframe do EA
2. GetPSARSignalMTF(symbol);   //-- Função de cálculo da fórmula Parabolic iSAR no timeframe solicitado.
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()


A função GetPSARSignalMTF() chamará a função PARSARMTF(), que calcula o sinal iSAR de acordo com o timeframe solicitado.

Como você pode ver, dentro da função PARSARMTF(), usamos e chamamos duas funções:

1. int xx= PairsIdxArray(symbol)

2. int tx=TFIndexArray(mtf).

A função PairsIdxArray() é usada para obter o nome do símbolo solicitado, e a função TFIndexArray() para obter a sequência do array do timeframe solicitado.

Então, o descritor do indicador correspondente é chamado para obter o valor do buffer do indicador iSAR desse timeframe solicitado.

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. Função ChartEvent


Para maior eficiência dos EAs multimoedas, criaremos vários botões para gerenciar ordens e alterar gráficos ou símbolos.
//+------------------------------------------------------------------+
//| 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()


Para alterar os símbolos do gráfico com um clique do mouse, ao pressionar em um dos nomes dos símbolos, o evento OnChartEvent() será chamado pela função ChangeChartSymbol().

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


Se a propriedade do EA Display Trading Info on Chart for Sim, as informações de negociação serão exibidas no gráfico onde o EA está posicionado, chamando a função TradeInfo()

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


A interface do EA multimoeda é apresentada da seguinte forma.

FXSAR_MTF_MCEA_look


Como você pode ver, sob o nome do Expert Advisor FXSAR_MTF_MCEA, existem botões M, C e R.

Ao pressionar M ou C, um painel de controle manual é exibido.

MCR_Combine

Ao pressionar M, o painel de controle manual é exibido, após isso o trader pode gerenciar ordens:

1. Set SL/TP All Orders (estabelecer stop-loss/take-profit para todas as ordens)

2. Close All Orders (fechar todas as ordens)

3. Close All Profits (fechar todas as ordens lucrativas)

Ao pressionar C, um botão do painel com 30 nomes de símbolos ou pares é exibido, e os traders podem clicar em um dos nomes dos pares ou símbolos. Ao pressionar qualquer um deles, o símbolo do gráfico será imediatamente substituído pelo indicado no botão pressionado.

Ao pressionar R, o EA multimoeda FXSAR_MTF_MCEA é removido do gráfico.



Testador de estratégias

Como é conhecido, o testador de estratégias do terminal MetaTrader 5 suporta e permite testar estratégias multissímbolos ou negociação automática para todos os símbolos disponíveis e em todos os timeframes disponíveis.

Vamos testar o EA multimoeda e multiframe FXSAR_MTF_MCEA por meio do testador de estratégias do MetaTrader 5.




Considerações finais

A conclusão ao criar um EA multimoeda e multiframe usando MQL5 pode ser a seguinte:

  1. Criar um EA multimoeda no MQL5 é pouco diferente de desenvolver um de uma só moeda. Porém, para Expert Advisors multimoedas com múltiplos timeframes, o processo é um pouco mais complexo do que para os Expert Advisors com um único timeframe.
  2. Criar um EA multimoeda aumenta a eficiência e eficácia dos traders, já que eles não precisarão abrir muitos gráficos.
  3. Uma estratégia de negociação correta e sinais de indicadores de qualidade aumentam a probabilidade de lucro em comparação com o uso de um Expert Advisor de uma só moeda. As perdas em um par serão compensadas pelos lucros em outros pares.
  4. O EA multimoeda FXSAR_MTF_MCEA é apenas um exemplo para estudo e desenvolvimento de ideias próprias. 
  5. Os resultados do teste no testador de estratégias ainda são insatisfatórios. Com a implementação de uma estratégia melhor, com cálculos de sinal mais precisos e melhores timeframes, os resultados, na minha opinião, deveriam ser melhores do que os atuais.


Notas:

Se você tiver uma ideia para criar um simples EA multimoeda baseado nos sinais padrão do indicador MQL5, compartilhe-a nos comentários.

Espero que o artigo e o EA multimoeda sejam úteis para os traders no estudo e desenvolvimento de ideias. Obrigado pela atenção!

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/13470

Arquivos anexados |
FXSAR_MTF_MCEA.mq5 (80.52 KB)
Redes neurais de maneira fácil (Parte 58): transformador de decisões (Decision Transformer — DT) Redes neurais de maneira fácil (Parte 58): transformador de decisões (Decision Transformer — DT)
Continuamos a explorar os métodos de aprendizado por reforço. Neste artigo, proponho apresentar um algoritmo ligeiramente diferente que considera a política do agente sob a perspectiva de construir uma sequência de ações.
Interface Gráfico: Dicas e recomendações para criar uma biblioteca gráfica no MQL Interface Gráfico: Dicas e recomendações para criar uma biblioteca gráfica no MQL
Vamos explorar os fundamentos das bibliotecas de interface gráfica para que você possa entender como elas funcionam ou até mesmo começar a criar as suas próprias.
Indicadores alternativos de risco e rentabilidade em MQL5 Indicadores alternativos de risco e rentabilidade em MQL5
Neste artigo, apresentaremos a implementação de vários indicadores de rentabilidade e risco, considerados alternativas ao índice de Sharpe, e exploraremos curvas de patrimônio líquido hipotéticas para analisar suas características.
Teoria das Categorias em MQL5 (Parte 22): Outra Perspectiva sobre Médias Móveis Teoria das Categorias em MQL5 (Parte 22): Outra Perspectiva sobre Médias Móveis
Neste artigo, tentaremos simplificar a descrição dos conceitos discutidos nesta série, focando apenas em um indicador, o mais comum e, provavelmente, o mais fácil de entender. Estamos falando da média móvel. Também examinaremos o significado e as possíveis aplicações das transformações naturais verticais.