English Русский Español Deutsch 日本語
preview
Criação de um Expert Advisor simples em várias moedas usando MQL5 (Parte 4): Média móvel triangular — Sinais do indicador

Criação de um Expert Advisor simples em várias moedas usando MQL5 (Parte 4): Média móvel triangular — Sinais do indicador

MetaTrader 5Negociação | 29 abril 2024, 13:34
315 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, por exemplo, do tipo 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, em particular a média móvel triangular em um ou mais timeframes, ou escalas de tempo.
    Neste artigo, ao calcular os sinais do robô investidor, você pode escolher ativar um ou mais timeframes.

    A média móvel triangular é um indicador personalizado para MetaTrader 5, criado por Mladen Rakic. Recebi permissão do autor para usar esse indicador como sinal dentro de meu robô investidor multimoeda TriangularMA_MTF_MCEA.
    Agradeço a Mladen Rakic pela oportunidade de usar seu trabalho.

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

    Bem, afinal o objetivo é atender às necessidades básicas dos traders que precisam de robôs de negociação eficazes e práticos. E é graças aos pontos fortes e as capacidades do MQL5 que podemos criar um robô investidor multimoeda simples que, neste artigo, irá utilizar sinais da média móvel triangular.

    Nota: O robô investidor multimoeda TriangularMA_MTF_MCEA foi criado a pedido dos traders.


    Características

    1. Pares de negociação.

    O robô investidor negociará com os seguintes pares:

    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 pares

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

    Total de 30 pares.

    No artigo anterior usamos uma função automática para detectar nomes de pares com prefixos e/ou sufixos.
    Neste artigo, simplificamos a tarefa adicionando propriedades de entrada especiais para o prefixo e o sufixo do nome do par.
    Então, por meio de uma função simples, processamos os nomes dos pares com prefixos e/ou sufixos em combinação com os 30 nomes de pares registrados, de modo que, se um robô investidor com tais nomes especiais para seus símbolos for usado no MetaTrader 5, tudo funcionará sem problemas.

    A desvantagem da função de detecção de nomes de símbolos que têm prefixos e sufixos é que ela funciona apenas com pares ou nomes de símbolos para forex e metais no MetaTrader 5, mas não funciona com símbolos especiais e índices.
    Além disso, outra desvantagem desse método é a necessidade de evitar erros de digitação (é necessário inserir levando em consideração o caso) no nome do prefixo e/ou sufixo do par.

    Como no artigo anterior, também adicionamos 10 opções para os pares negociados neste robô investidor.
    Um dos 10 pares de opções que serão negociados é o Trader Wishes Pairs, em cujo caso os pares negociados devem ser inseridos manualmente pelo operador nas propriedades do EA. Lembre-se de que o nome do par inserido já deve estar na lista de 30 pares.

    Como no artigo anterior, nesta versão do robô investidor também adicionamos a opção de sessão de negociação (fuso horário), portanto os pares negociados correspondem ao horário da sessão de negociação.


    2. Indicador de sinais.

    Na descrição da média móvel triangular, o autor escreve:

    "Uso:
    Pode-se utilizar a mudança de cor como sinal".

    As cores padrão do indicador de média móvel triangular são:

    • 0-DarkGray = sinal desconhecido
    • 1-DeepPink = sinal de venda
    • 2-MediumSeaGreen = sinal de compra.

    Nesta versão do robô investidor, criamos duas opções de uso de timeframes ao calcular o sinal da média móvel triangular.

    1. Cálculo de sinais baseado em multi-timeframe.
    No sistema de cálculo com vários timeframes, os traders devem escolher na lista a série de timeframes desejados.
    A série de timeframes escolhida é fornecida na faixa de M5 a D1 (11 timeframes).
    Os traders podem escolher a série de timeframes: início (por exemplo, M15) e fim (por exemplo, H4).
    Assim, o robô investidor calculará o sinal da média móvel triangular começando no timeframe M15 e terminando no H4.

    Cálculos da média móvel triangular em vários timeframes:

    • Sinal de compra, se em todos os timeframes selecionados o indicador estiver na cor MediumSeaGreen, e
    • Sinal de venda, se em todos os timeframes selecionados o indicador estiver na cor DeepPink.

    2. Cálculo de sinais baseado em um único timeframe.
    No sistema de cálculo de sinais em um único timeframe, os traders devem escolher um dos 11 timeframes, começando em M5 e terminando em D1.
    Assim, o robô investidor calculará o sinal do indicador de média móvel triangular no timeframe selecionado.

    Enquanto isso, o cálculo do sinal da média móvel triangular em um único timeframe será assim:

    • Sinal de compra, se as 2 barras anteriores forem DeepPink, a barra anterior for MediumSeaGreen e a barra atual for MediumSeaGreen.
    • Sinal de venda, se as 2 barras anteriores forem MediumSeaGreen, a barra anterior for DeepPink e a barra atual for DeepPink.

    A média móvel triangular para sinais de compra e venda pode ser vista nas figuras 1 e 2.

    H4_TriangularMA01

      H4_TriangularMA02


      3. Gerenciamento de trading e ordens.

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

      1. Ordens 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):

                  Novamente é dada uma opção: 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.

                  Quando Use Order Stop Loss (No):

                  Então, o EA verificará o estado do sinal para cada ordem aberta e avaliará

                  o potencial de lucro. Se o sinal enfraquecer, significa que a ordem deve ser fechada para preservar

                  o lucro. Ou se o sinal indicar uma mudança de direção, a ordem deve ser fechada com prejuízo.

                  Nota:
                  Antes de fechar uma operação devido a um sinal fraco, é solicitada a confirmação do usuário.


      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.

                  Quando Use Order Take Profit (Yes):

                  Novamente é dada uma 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.

                  Quando Use Trailing SL/TP (Yes):

                  Novamente é dada uma opção: Use Automatic Trailing (Yes) ou (No) - usar trailing automático: sim ou não           

                  Com Use Automatic Trailing (Yes), o trailing stop é executado pelo EA usando 

                  um buffer zero da média móvel triangular (dados do indicador) no timeframe automaticamente selecionado pelo EA, e simultaneamente

                  capturando lucros móveis com base no valor da variável TPmin (valor mínimo de 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.


      Função Trailing Stop Price:

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


      Alteração da função SL/TP:

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


      4. 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 quiser usar stop-loss ou take-profit para todas as ordens, ele só precisa pressionar o botão
      Set SL / TP All Orders para alterar todas as ordens e aplicar o stop-loss e/ou take-profit.

      2. Close All Orders
      Fechar todas as ordens.

      3. Close All Orders Profit
      Se o trader desejar fechar todas as ordens que já são lucrativas, basta um clique no botão
      Close All Orders Profit para fechar todas as ordens abertas lucrativas.


      5. Management Orders and Chart Symbols.

      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. Cabeçalho 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;
      //---


      Enumeração para uso do fuso horário

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


      Enumeração para seleção de horas

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


      Enumeração para seleção de atas

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


      Enumeração para escolha de pares de opções para negociação

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


      Enumeração YN usada para opções (Yes) ou (No) no parâmetro do robô investidor

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


      Enumeração para escolha de timeframe, que será usado em um ou vários timeframes

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


      Enumeração para uso de um ou vários timeframes

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


      Parâmetros de entrada do EA

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


      No grupo de propriedades de entrada Global Strategy EA Parameter do robô investidor, os traders devem escolher se usam o cálculo de sinais em um único timeframe ou em vários.

      Ao escolher um único timeframe (STF), ele deve ser especificado.
      No parâmetro de entrada do robô investidor, selecione Select Single Calculation timeframe (escolher um timeframe para cálculo), o valor padrão é PERIOD_H1.

      Ao escolher vários timeframes (MTF), eles devem ser especificados.
      No parâmetro de entrada do robô investidor, selecione Select Multi Timeframe calculation start (início do cálculo em vários timeframes) e Select Multi Timeframe calculation end (fim do cálculo em vários timeframes).

      Nas linhas 478-518, a função TriangularMA_MTF_MCEA_Config() explica como trabalhar com um e vários timeframes.

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


      A variável ENUM_TIMEFRAMES TFs[] deve ser atribuída à opção enum TFMTF

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


      Então, o trader deve definir o período do indicador Triangular MA. O período padrão é 14.
      Além disso, é necessário especificar o preço de cálculo do Triangular MA. O preço padrão é PRICE_CLOSE.

      No grupo de propriedades de entrada Select Pairs to Trade, é necessário escolher um par para negociar entre as 10 opções fornecidas. O valor padrão é All Forex 30 Pairs (todos os 30 pares Forex).

      Para configurar o par negociado, vamos chamar a função HandlingSymbolArrays().
      Usando a função HandlingSymbolArrays(), trataremos todos os pares negociados.

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


      Dentro da função HandlingSymbolArrays(), chamamos a função SetSymbolNamePS().
      Com isso, poderemos processar os nomes dos símbolos que têm prefixos e/ou sufixos.

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

      Nota:
      O robô investidor verificará os pares.
      Se o trader cometer um erro ao inserir o nome do par ou o nome do prefixo/sufixo
      ou se a verificação do par falhar, o robô investidor emitirá um alerta e será removido do gráfico.


      No grupo de propriedades de entrada Trade on Specific Time, o trader precisa escolher Trade on Specific Time Zone (Yes) ou (No)
      - negociar em um fuso horário específico: sim ou não Quando Yes, é necessário escolher os parâmetros de enumeração:

      • Negociação em sessão personalizada
      • Negociação na sessão da Nova Zelândia
      • Negociação na sessão de Sydney da Austrália
      • Negociação na sessão asiática de Tóquio
      • Negociação na sessão da Europa em Londres (sessão de Londres)
      • Negociação na sessão de Nova York da América (sessão de Nova York)

      Negociação em sessão personalizada: Os traders devem definir um horário ou horas e minutos para iniciar a negociação e horas e minutos para fechar a negociação.

      Assim, o Expert Advisor só executará ações durante o tempo especificado.

      Em outros casos, os horários de início e término da negociação são escolhidos pelo Expert Advisor.


      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.

      Em particular, as variáveis usadas na função para processar nomes de símbolos com prefixo e/ou sufixo, bem como cálculos de fusos horários, foram feitas na classe MCEA.

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


      A função inicial e principal no funcionamento do robô investidor multimoeda, chamada de OnInit(), é a TriangularMA_MTF_MCEA_Config().

      Na função TriangularMA_MTF_MCEA_Config(), todos os símbolos usados, todos os indicadores de handle aplicados e algumas funções importantes do arquivo de cabeçalho include são configurados.

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


      2. 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 sequência do EA dentro dessa função.

      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.

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


      Especificamente para os fusos horários de negociação, a função ExpertActionTrade() adicionou a chamada da função lógica Trade_session().
      Quando Trade_session() for true, o EA funcionará até o encerramento e, quando for false, o EA só executará as tarefas Close Trade e Save Profit devido a sinal fraco (Yes) e Trailing stop (Yes).

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


      3. Obtenção de sinais de negociação para abrir posições

      Para obter o sinal, a função ExpertActionTrade() chama a função GetOpenPosition().

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


      A função GetOpenPosition() chamará duas funções que executam o cálculo dos sinais:

      1. GetSignalMidTF(const string symbol);          //-- Obtenção de sinais por posições de timeframe médio e movimento de preço

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


      2. GetTriaMASignalMTF(const string symbol);    //-- Cálculo da fórmula da média móvel triangular.

      A função GetTriaMASignalMTF() chama a função TriaMASMTF(), que calcula o sinal da média móvel triangular de acordo com o timeframe solicitado.

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


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


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

      • 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, é chamado o handle do indicador apropriado para obter o valor do buffer da média móvel triangular desse timeframe.

      Como diz o autor do indicador:
      "Uso:
      Pode-se utilizar a mudança de cor como sinal".

      Então, como aceitamos o sinal da média móvel triangular?

      Na propriedade da média móvel triangular:

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


      Sabemos que:

      • 0-DarkGray = sinal desconhecido
      • 1-DeepPink = sinal de venda
      • 2-MediumSeaGreen = sinal de compra.

      Assim, podemos pegar o valor do buffer 1 da média móvel triangular como um sinal usando a função CopyBuffer, como na função TriaMASMTF().

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


      4. Função ChartEvent

      Para maior eficácia dos robôs investidores multimoeda, criaremos vários botões para gerenciar ordens, bem como
      mudar gráficos e 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.ValidatePairs(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()
      //---------//


      Como estamos adicionando uma sessão de negociação ou um fuso horário de negociação e parâmetros de pares negociados em um ou mais timeframes, precisamos adicionar novos dados na informação de negociação exibida no gráfico. Para isso, fizemos alterações na função TradeInfo().

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


      Também adicionamos uma função para descrever o tempo de acordo com as condições do fuso horário de negociação como parte da função TradeInfo().

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


      A interface do robô investidor multimoeda TriangularMA_MTF_MCEA é a seguinte.

      TradeInfo


      Como você pode ver, sob o nome do EA TriangularMA_MTF_MCEA há os botões M, C e R

      Expert_manual_button

      Ao pressionar M, o painel de controle manual será exibido

      Expert_manual_button_01

      O operador pode então gerenciar as ordens conforme descrito na seção "Gerenciamento manual de ordens".

      • 1. Set SL/TP All Orders (definir 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.

      Expert_manual_button_02


      Quando R é pressionado, o Expert Advisor TriangularMA_MTF_MCEA multimoeda é removido do gráfico, de modo que os traders não precisam desativar os EAs manualmente.



      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 multi-timeframe FXSAR_MTF_MCEA por meio do testador de estratégias do MetaTrader 5.

      1. Teste do triangularMA_MTF_MCEA em vários timeframes.

      st-mtf


      st-mtf-result


      2. Teste triangularMA_MTF_MCEA em um timeframe.

      st-stf


      st-stf-result



      Considerações finais

      Os resultados da criação de um robô multimoeda e multi-timeframe para trabalhar com um e várias escalas de tempo usando MQL5 podem ser concluídos da seguinte forma:

      • 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.
      • Criar um EA multimoeda aumenta a eficiência e eficácia dos traders, já que eles não precisarão abrir muitos gráficos.
      • A estratégia de negociação correta aumenta a probabilidade de lucro em comparação com o uso de um Expert Advisor de moeda única. As perdas em um par serão compensadas pelos lucros em outros pares.
      • O EA multimoeda FXSAR_MTF_MCEA é apenas um exemplo para estudo e desenvolvimento de ideias próprias. 
      • 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.
      • Os resultados do teste da TriangularMA_MTF_MCEA no testador de estratégias demonstram que os resultados em um timeframe são melhores do que em vários timeframes.

      Nota:
      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/13770

      Algoritmos de otimização populacionais: otimização de dinâmica espiral (Spiral Dynamics Optimization, SDO) Algoritmos de otimização populacionais: otimização de dinâmica espiral (Spiral Dynamics Optimization, SDO)
      Neste artigo examinaremos a otimização de dinâmica espiral (SDO), um algoritmo de otimização baseado nos padrões de trajetórias espirais presentes na natureza, como nas conchas de moluscos. O algoritmo proposto pelos autores foi completamente repensado e modificado por mim, e o artigo discutirá por que essas mudanças foram necessárias.
      Padrões de projeto no MQL5 (Parte 2): Padrões estruturais Padrões de projeto no MQL5 (Parte 2): Padrões estruturais
      Neste artigo, continuaremos a estudar os padrões de projeto que permitem aos desenvolvedores criar aplicativos expansíveis e confiáveis não apenas no MQL5, mas também em outras linguagens de programação. Desta vez, falaremos sobre outro tipo: modelos estruturais. Aprenderemos a projetar sistemas usando as classes disponíveis para formar estruturas maiores.
      Redes neurais de maneira fácil (Parte 65): aprendizado supervisionado ponderado por distância (DWSL) Redes neurais de maneira fácil (Parte 65): aprendizado supervisionado ponderado por distância (DWSL)
      Neste artigo, convido você a conhecer um algoritmo interessante que se situa na interseção entre os métodos de aprendizado supervisionado e de reforço.
      Validação cruzada combinatoriamente simétrica no MQL5 Validação cruzada combinatoriamente simétrica no MQL5
      Neste artigo veremos como implementar a verificação cruzada combinatoriamente simétrica no MQL5 puro para medir o grau de ajuste após a otimização de uma estratégia usando o algoritmo completo e lento do testador de estratégias.