English Русский Español Deutsch 日本語
preview
Técnicas do MQL5 Wizard que você deve conhecer (Parte 17): Negociação Multimoedas

Técnicas do MQL5 Wizard que você deve conhecer (Parte 17): Negociação Multimoedas

MetaTrader 5Exemplos | 17 setembro 2024, 08:53
16 0
Stephen Njuki
Stephen Njuki

Prefácio

Este artigo continua a série sobre como o MQL5 wizard é ideal para testes rápidos e prototipagem de ideias para traders. Para muitas pessoas que desenvolvem expert advisors e sistemas de negociação, a necessidade de continuar aprendendo e estar atualizado com as tendências não apenas em machine learning, mas também em gestão de riscos e negociações em geral, é importante. Portanto, consideramos dentro desta série como o IDE MQL5 é útil nesse sentido, não apenas economizando tempo, mas também minimizando erros de codificação.

Eu pretendia analisar neural architecture search (NAS) para este artigo, mas percebi que há alguns preceitos básicos que ainda não abordei e que valem a pena ser considerados, sendo o principal deles a negociação de múltiplos ativos em um expert advisor montado pelo assistente. Então, vamos nos desviar um pouco da análise de novas configurações de negociação e considerar alguns conceitos básicos para este artigo. O NAS será considerado no próximo artigo.


Introdução

A negociação multimoedas, ao contrário da negociação de uma única moeda, reduz a concentração de risco. Como cada conta tem um nível de alavancagem definido e, portanto, uma quantidade definitiva de margem livre, quando você se depara com uma situação em que precisa negociar mais de um símbolo, a quantidade de margem livre a ser alocada deve ser dividida entre todas as moedas disponíveis. Se essas moedas não têm correlação ou são correlacionadas inversamente, o risco de dependência excessiva de apenas uma delas pode ser muito mitigado.

Além disso, se um sistema de negociação em que a abertura de posições em várias moedas não for feita em paralelo para minimizar o risco, mas de forma sequencial, onde cada par de moedas é considerado em um momento distinto, então as oportunidades entre mercados podem ser aproveitadas. Isso envolveria a abertura sequencial ou continuada de posições cujos pares de moedas se correlacionam inversamente com as posições já abertas se as mesmas estiverem em prejuízo, ou fazer o oposto se as posições abertas já estiverem com lucro. O pareamento de moedas como margem ou lucro em qualquer par torna este processo particularmente interessante ao selecionar uma oportunidade entre mercados, além de considerar apenas correlações.

O pareamento margem-lucro em cada par de moedas também apresenta uma vantagem da negociação multimoedas, que é a proteção (hedge). Próximo da arbitragem, uma prática não apenas desaprovada pela maioria dos corretores, mas também muito difícil de implementar na prática, a proteção com múltiplos pares de moedas com base em suas moedas de margem ou lucro pode ser realizada com ordens pendentes, especialmente em situações em que o trader pretende manter posições durante eventos de notícias de alto impacto ou até mesmo no final de semana.

Mais do que essas estratégias, a negociação multimoedas permite que o trader ou expert advisor visualize e capitalize sobre tendências específicas de moedas em vários pares negociáveis na observação de mercado. Assim, por exemplo, se uma moeda específica estiver ganhando juros favoráveis, você poderia comprar e manter um número de pares em que ela tenha uma taxa superior sob uncovered interest arbitrage e ganhar não apenas com eventuais mudanças de preço, mas também com os juros. A capacidade de fazer uma análise em vários pares de moedas e colocar negociações que aproveitem essas configurações entre moedas só é viável se o expert advisor for construído para negociação multimoedas, algo que os expert advisors montados pelo assistente que analisamos não conseguem fazer.

Então, para este artigo, vamos buscar construir templates que modifiquem as classes usadas no MQL5 wizard para montar um expert advisor em dois cenários amplos. Primeiro, buscaremos ter um expert montado pelo assistente que simplesmente analise e abra posições paralelas em múltiplos pares de moedas com o objetivo de mitigar a exposição ao risco. Essa abordagem provavelmente exigirá a maior customização, pois modificaremos um arquivo importante usado na montagem do assistente. Por fim, na segunda abordagem, consideraremos experts montados pelo assistente que levem em consideração correlações relativas de pares de moedas e possam abrir posições em sequência com base em análise independente.


Template para o MQL5 Wizard (Opção-1):

Os expert advisors montados pelo assistente têm 3 classes principais, cada uma em um arquivo separado. Essas são ‘ExpertBase’, ‘ExpertTrade’ e ‘Expert’. Além dessas 3 classes principais, há 3 outras classes auxiliares, a saber, ‘ExpertSignal’, ‘ExpertMoney’ e ‘ExpertTrailling’, que são herdadas respectivamente ao construir as classes de sinal, gestão de dinheiro ou trailing de um expert. Em todas essas classes, é a classe ‘ExpertBase’ que define o objeto de classe de símbolo que é usado para acessar as informações de mercado do símbolo negociado por padrão (‘m_symbol’). Como mencionado acima, por padrão, todos os expert advisors montados pelo assistente negociam apenas um símbolo, portanto, a classe de símbolo inicializada dentro de ‘ExpertBase’ é destinada a lidar com apenas um símbolo.

Para torná-lo multissímbolos, uma solução possível poderia ser converter essa instância de classe em um array. Embora isso seja possível, as classes que acessam essa instância de classe de símbolo usam muitas funções para fazê-lo e essa conectividade sempre espera um não array, o que significa que muitas mudanças inviáveis teriam que ser feitas no código. Portanto, essa não é uma boa solução para tornar os expert advisors montados pelo assistente multimoedas.

Uma abordagem mais viável e semelhante que consideraremos é fazer com que a instância da classe geral ‘Expert’ seja um array cujo tamanho corresponda ao número de símbolos de negociação que estaríamos testando. Uma instância dessa classe é sempre declarada no arquivo ‘*.mq5’ do expert advisor montado pelo assistente, e simplesmente converter isso em um array, essencialmente marca toda a personalização a jusante que precisamos fazer.

//+------------------------------------------------------------------+
//| Global expert object                                             |
//+------------------------------------------------------------------+
CExpert ExtExpert[__FOLIO];
CExpertSignal *signals[__FOLIO];

Converter a instância da classe expert em um array exigirá que tenhamos predefinido um array de pares de moedas para negociar. Fazemos isso no código abaixo:

//+------------------------------------------------------------------+
//| 'Commodity' Currency folio                                       |
//+------------------------------------------------------------------+
#define                          __FOLIO 9
string                           __F[__FOLIO] 

                                 = 
         
                                 {
                                 "AUDNZD","AUDUSD","AUDCAD","AUDJPY",
                                 "NZDUSD","NZDCAD","NZDJPY",
                                 "USDCAD",
                                 "CADJPY"
                                 };
input string                     __prefix="";
input string                     __suffix="";


O código acima é alterado para uma versão customizada da classe Expert. Como estamos modificando essa classe, precisamos salvar uma instância dela com um novo nome para manter as configurações padrão para montagens típicas. O nome que usamos é 'ExpertFolio.mqh', a partir do nome original 'Expert.mqh'. Além da mudança de nome e do código modificado no cabeçalho, também precisamos alterar a listagem da função 'Init' para ser mais flexível em relação a símbolos que não correspondem ao símbolo do gráfico ao qual o expert está anexado. Fazemos isso no código abaixo:

//+------------------------------------------------------------------+
//| Initialization and checking for input parameters                 |
//+------------------------------------------------------------------+
bool CExpert::Init(string symbol,ENUM_TIMEFRAMES period,bool every_tick,ulong magic)
  {
//--- returns false if the EA is initialized on a timeframe different from the current one
   if(period!=::Period())
     {
      PrintFormat(__FUNCTION__+": wrong timeframe (must be: %s)",EnumToString(period));
      return(false);
     }
     
   if(m_on_timer_process && !EventSetTimer(PeriodSeconds(period)))
      {
      PrintFormat(__FUNCTION__+": cannot set timer at: ",EnumToString(period));
      return(false);
      }
//--- initialize common information
   if(m_symbol==NULL)
     {
      if((m_symbol=new CSymbolInfo)==NULL)
         return(false);
     }
   if(!m_symbol.Name(symbol))
      return(false);
   
....
....


//--- ok
   return(true);
  }

As mudanças acima podem ser feitas em uma réplica do arquivo de classe expert, que depois renomeamos como indicado acima, ou podemos criar uma nova classe que herde da classe expert em 'Expert.mqh' e, em seguida, adicionar uma função 'override' 'Init' nesta nova classe. Essa nova classe e arquivo serão referenciados no arquivo principal do expert. Abaixo está uma listagem disso:

#include "Expert.mqh"
//+------------------------------------------------------------------+
//| Class CExfolio.                                                  |
//| Purpose: Base class expert advisor.                              |
//| Derives from class CExpertBase.                                  |
//+------------------------------------------------------------------+
class CExfolio : public CExpert
  {
protected:

   
public:

                     CExfolio(void);
                    ~CExfolio(void);
                    
   //--- initialization
   virtual bool      Init(string symbol,ENUM_TIMEFRAMES period,bool every_tick,ulong magic=0) override;
   
   //...

  };

Como pode ser visto no código acima, o comando de substituição (override) foi adicionado no final da declaração de interface, mas como a função Init não é 'virtual' por padrão, a função Init na classe expert original precisa ser modificada para incluir isso. Assim, essa linha ficaria assim:

//+------------------------------------------------------------------+
//| Initialization and checking for input parameters                 |
//+------------------------------------------------------------------+
bool CExfolio::Init(string symbol,ENUM_TIMEFRAMES period,bool every_tick,ulong magic)
  {
//--- returns false if the EA is initialized on a symbol/timeframe different from the current one
      
      bool _init=true;
      
      if(!CExpert::Init(symbol,period,every_tick,magic))
      {
         _init=false;
         //
         if(symbol!=_Symbol)
         {
            if(Reinit(symbol,period,every_tick,magic)){ _init=true; }
         }
      }
      
      CExpert::OnTimerProcess(true);
      
      if(CExpert::m_on_timer_process && !EventSetTimer(PeriodSeconds(_Period)))
      {
         printf(__FUNCTION__+": cannot set timer at: ",EnumToString(period));
         _init=false;
      }
      
//--- ok
      return(_init);
  }

As principais mudanças aqui garantem que a inicialização não falhe se o símbolo do gráfico não corresponder ao símbolo do portfólio. Certamente, essa seria uma opção mais "limpa", já que nosso arquivo de classe criado é consideravelmente menor, o que significa que temos menos duplicidade do que no primeiro caso. No entanto, precisaríamos modificar o arquivo expert embutido, e isso significa que, para cada atualização do terminal, teríamos que adicionar o especificador de função virtual à função Init.

Além dessas mudanças na classe expert, o arquivo do expert advisor gerado pelo assistente também precisaria ter cada uma das funções OnInit, OnTick, OnTimer, OnDeInit e Trade modificadas. O que seria adicionado é um loop que itera por todas as moedas predefinidas na classe expert customizada. Sua declaração é acompanhada por parâmetros de entrada de string de prefixo e sufixo que garantem que seus nomes sejam bem formados e estejam na observação de mercado. Em vez de nomear explicitamente os símbolos e gerenciar nomes com prefixos/sufixos, a abordagem adequada para acessar símbolos disponíveis é destacada aqui, mas mesmo assim você precisaria ter uma lista predefinida dos símbolos de seu interesse, para filtrar corretamente a lista frequentemente muito longa de símbolos disponíveis na observação de mercado.

Os símbolos selecionados na classe expert customizada são o que costumava ser chamado de "commodities", especialmente na era da Guerra Fria, já que seu momentum era excessivamente influenciado pelo preço das commodities. Portanto, nossa lista usa as moedas AUD, NZD e CAD como as principais commodities. A adição do USD e JPY é para exposição à volatilidade, mas eles não eram membros do grupo de "commodities".

A classe de sinal usada para o expert advisor no assistente pode ser qualquer uma das classes embutidas. Isso porque, para a primeira implementação, os símbolos são executados em paralelo para minimizar a exposição ao risco. As decisões de negociação em qualquer símbolo não são influenciadas pelo que está acontecendo com outro símbolo, então as configurações para o sinal selecionado serão aplicadas a todos os símbolos. A partir dos testes, isso implica que nossas execuções de teste terão melhores chances de ter bom desempenho em caminhadas futuras ou validação cruzada, já que diferentes símbolos compartilham as mesmas configurações e, portanto, há menos ajuste de curva. Usamos a classe de sinal RSI, que requer relativamente poucos parâmetros de entrada, a saber: período do indicador e preço aplicado.


Template para o MQL5 Wizard (Opção-2):

Para a segunda implementação de negociação multimoedas, buscaremos modificar o arquivo do expert advisor montado pelo assistente, adicionando a ele uma função 'Select'. Essa função, baseando-se nas correlações dos símbolos dentro do portfólio de negociação, busca capitalizar oportunidades entre mercados, negociando mais de um símbolo apenas se essas oportunidades existirem. Ela funciona essencialmente como um filtro da abordagem que consideramos na primeira opção acima.

Para conseguir isso, primeiro devemos habilitar a negociação com temporizador, o que, surpreendentemente, não está ativado por padrão. Fazemos isso com uma linha na função 'OnInit', conforme indicado abaixo:

//
ExtExpert[f].OnTimerProcess(true);

Com isso definido, podemos então nos concentrar na função 'Select', que apresenta essencialmente duas seções principais. A primeira lida com situações em que nenhuma posição está aberta e um sinal de confirmação de correlação precisa ser selecionado entre todos os símbolos de negociação no portfólio. Esse sinal é de confirmação porque, lembre-se, ainda dependemos da classe de sinal RSI como a principal para todos os símbolos. Então, a confirmação, em nosso caso, será obtida via auto-correlação do buffer de preços de fechamento para cada um dos símbolos. O símbolo com o maior valor positivo do portfólio será selecionado.

Usamos o maior valor positivo e não apenas a magnitude porque estamos visando símbolos em tendência ou o símbolo com a tendência mais forte do portfólio. Uma vez que temos isso, determinamos sua direção de tendência observando a mudança no preço de fechamento entre o valor mais recente e o último valor. Uma mudança positiva seria de alta, enquanto uma mudança negativa seria de baixa. Isso é processado na listagem abaixo:

//+------------------------------------------------------------------+
//| Symbol Selector via Correlation                                  |
//+------------------------------------------------------------------+
bool  Select(double Direction, int &Index, ENUM_POSITION_TYPE &Type)
{  if(PositionsTotal() == 0)
   {  double _max = 0.0;
      int _index = -1;
      Type = INVALID_HANDLE;
      for(int f = 0; f < __FOLIO; f++)
      {  vector _v_0, _v_1;
         _v_0.CopyRates(__F[f], Period(), 8, 0, 30);
         _v_1.CopyRates(__F[f], Period(), 8, 30, 30);
         double _corr = _v_0.CorrCoef(_v_1);
         if(_max < _corr && ((Direction > 0.0 && _v_0[0] > _v_0[29]) || (Direction < 0.0 && _v_0[0] < _v_0[29])))
         {  _max = _corr;
            _index = f;
            if(_v_0[0] > _v_0[29])
            {  Type = POSITION_TYPE_BUY;
            }
            else if(_v_0[0] < _v_0[29])
            {  Type = POSITION_TYPE_SELL;
            }
         }
      }
      Index = _index;
      return(true);
   }
   else if(PositionsTotal() == 1)
   {  

//...
//...

   }
   return(false);
}


Assim, a listagem acima é a parte 'padrão' da função 'Select', e lida com situações em que ainda nenhuma posição foi aberta. Uma vez que uma posição foi aberta, então procederíamos a procurar por oportunidades entre mercados, dependendo do desempenho da posição aberta. Se a posição inicialmente aberta estiver em prejuízo, então filtramos os símbolos restantes do portfólio e tentamos encontrar um com uma correlação efetiva 'inversa'. 'Inversa' no sentido de que estamos interessados apenas na magnitude, e seguiremos a tendência desse símbolo, desde que a magnitude de sua correlação com o símbolo aberto atual seja a maior em comparação com a posição já aberta. O código que lida com isso está abaixo:

//+------------------------------------------------------------------+
//| Symbol Selector via Correlation                                  |
//+------------------------------------------------------------------+
bool  Select(double Direction, int &Index, ENUM_POSITION_TYPE &Type)
{  if(PositionsTotal() == 0)
   {  
//...
//...

   }
   else if(PositionsTotal() == 1)
   {  ulong _ticket = PositionGetTicket(0);
      if(PositionSelectByTicket(_ticket))
      {  double _float = PositionGetDouble(POSITION_PROFIT);
         ENUM_POSITION_TYPE _type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
         int _index = ArrayBsearch(__F, PositionGetString(POSITION_SYMBOL));
         double _max = 0.0;
         Type = INVALID_HANDLE;
         for(int f = 0; f < __FOLIO; f++)
         {  if(f == _index)
            {  continue;
            }
            else
            {  vector _v_0, _v_1;
               _v_0.CopyRates(__F[_index], Period(), 8, 0, 30);
               _v_1.CopyRates(__F[f], Period(), 8, 0, 30);
               double _corr = fabs(_v_0.CorrCoef(_v_1));
               if(_float < 0.0 && _max < _corr)
               {  _max = _corr;
                  Index = f;
                  if(_v_1[0] > _v_1[29])
                  {  Type = POSITION_TYPE_BUY;
                  }
                  else  if(_v_1[0] < _v_1[29])
                  {  Type = POSITION_TYPE_SELL;
                  }
               }
            }
         }
      }
      return(true);
   }
   return(false);
}

Para usar essa função 'Select' no ambiente de um expert advisor montado pelo assistente, temos que fazer mais algumas mudanças na classe expert. Por isso, criar uma instância duplicada da classe expert e renomeá-la, por mais volumoso que pareça, seria mais pragmático. A primeira alteração que precisamos fazer é tornar a função 'Refresh' acessível publicamente. Isso significa movê-la da seção 'Protected' da interface da classe para a parte 'Public'. Da mesma forma, a função 'Process' também deve ser tornada pública. Essa mudança apareceria conforme indicado abaixo:

//+------------------------------------------------------------------+
//| Class CExpert.                                                   |
//| Purpose: Base class expert advisor.                              |
//| Derives from class CExpertBase.                                  |
//+------------------------------------------------------------------+
class CExpert : public CExpertBase
  {
protected:
   
   //...
   //...

public:
                     CExpert(void);
                    ~CExpert(void);
   
   //...

   //--- refreshing 
   virtual bool      Refresh(void);
   //--- processing (main method)
   virtual bool      Processing(void);
   
protected:
   
   //...
   //...

  };


Essas duas funções principais precisam ser movidas para a parte pública porque temos que chamá-las manualmente dentro do nosso expert advisor alterado. Normalmente, elas são chamadas internamente pelas funções 'OnTick' ou 'OnTimer', dependendo de qual das duas está ativada. E, quando são chamadas, fazem um processamento completo de sinal, trailing e gerenciamento de dinheiro do símbolo em que são chamadas. No nosso caso, queremos processar apenas certos símbolos, dependendo de a) suas correlações relativas e b) se já temos uma posição aberta. Isso claramente exigiria que 'assumíssemos o comando' de como e quando elas são chamadas. Fazemos isso na função 'OnTimer', conforme indicado abaixo:

//+------------------------------------------------------------------+
//| "Timer" event handler function                                   |
//+------------------------------------------------------------------+
void OnTimer()
{  for(int f = 0; f < __FOLIO; f++)
   {  ExtExpert[f].Refresh();
   }
   for(int f = 0; f < __FOLIO; f++)
   {  int _index = -1;
      ENUM_POSITION_TYPE _type = INVALID_HANDLE;
      ExtExpert[f].Magic(f);
      if(Select(signals[f].Direction(), _index, _type))
      {  ExtExpert[f].OnTimer();
         ExtExpert[f].Processing();
      }
   }
}


Na seleção do símbolo para negociar, o rastreamos atribuindo seu índice dentro do array de portfólio de origem como seu número mágico. Isso significa que em cada loop nas funções de processamento padrão ‘OnTick’, ‘OnTrade’ e ‘OnTimer’, precisaríamos atualizar o número mágico usado pela classe de negociação antes do processamento. Além disso, como símbolos personalizados foram usados para este teste, por razões de qualidade dos dados, o nome dos símbolos no array do portfólio precisava ser incluído com seu sufixo (ou prefixo, se aplicável). Por algum motivo, o testador de estratégias não consegue sincronizar símbolos personalizados, mesmo que todos os dados estejam presentes no computador de teste se você estiver adicionando o prefixo e sufixo ao inicializar.

Além disso, queremos negociar usando ‘OnTimer’ e não no padrão ‘OnTick’, o que, em teoria, pode ser ajustado facilmente configurando os parâmetros ‘OnProcessTimer’ e ‘OnProcessTick’. No entanto, alterá-los resulta em nenhum trade ou negociação no tick. Isso significa que mudanças mais invasivas nas funções OnTick e OnTimer da classe expert foram necessárias, de modo que a função ‘OnProcess’ foi desativada dentro de ‘OnTick’, e a função ‘OnProcess’, que foi tornada pública acima, agora é chamada independentemente na função ‘OnTimer’ do expert advisor, conforme mostrado no código de ‘OnTimer’ acima. Isso é necessário novamente porque, por uma razão desconhecida, no momento desta escrita, a função ‘Process’ dentro de ‘OnTimer’ na classe ‘ExpertFolio’ não é executada. Conseguimos atualizar preços e valores de indicadores em todos os símbolos, mas a função ‘Process’ precisa ser chamada independentemente. Além disso, o temporizador precisa ser declarado e encerrado manualmente, como em expert advisors comuns.


Testes e Otimização

Realizamos testes no cruzamento de commodities AUDJPY no período de 4 horas, de 2023 a 2024. Nossos expert advisors de teste não usam stop loss, pois na segunda opção, conforme descrito acima, as posições perdedoras são gerenciadas por oportunidades entre mercados. Otimizamos apenas o período do RSI, já que é o indicador da classe de sinal, e os limiares de abertura e fechamento, expiração de ordens limite e o gap de entrada para as ordens limite. O gerenciamento de dinheiro utilizado foi para lotes fixos no tamanho mínimo. Os relatórios e as curvas de equidade de ambas as opções são apresentados abaixo:

r1

c1


r2

c2

Como pode ser visto nos relatórios acima, muitas mais negociações foram feitas do que no caso de uma configuração de moeda única, como seria de esperar. Curiosamente, as configurações usadas para realizar essas múltiplas negociações, enquanto gerenciam os rebaixamentos (drawdowns) a limites razoáveis, apontam para uma aplicação e potencial prolongados. Além disso, como esperado, a segunda opção fez menos negociações que a primeira porque a) não havia um filtro secundário para o sinal de entrada e b) as regras de proteção entre mercados (hedging) são usadas na segunda opção para minimizar os rebaixamentos e gerenciar o risco.

Além das oportunidades entre mercados, também podem ser exploradas oportunidades de arbitragem de juros descobertos, conforme mencionado na introdução. Nesse caso, os dados de notícias econômicas precisariam ser extraídos do calendário econômico do MQL5. Os testes de estratégia com esses valores ainda são limitados, mas recentemente foi postado um artigo interessante sobre armazenar dados de notícias econômicas em um banco de dados, enquanto usa o IDE MQL5. Esse artigo pode ser encontrado aqui, e vale a pena ler se esse for um caminho que você deseja explorar.


Conclusão

Concluindo, exploramos como a negociação multimoedas pode ser introduzida em expert advisors montados via o MQL5 wizard. Esses podem ser facilmente codificados sem o assistente, no entanto, o assistente MQL5 não apenas permite o desenvolvimento rápido de experts com menos repetição, como também permite que mais de uma ideia seja testada simultaneamente por meio de um sistema de ponderação. Como sempre, novos leitores podem se referir aos guias aqui e aqui sobre como usar o assistente.

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

Arquivos anexados |
ExpertFolio_1.mqh (121.5 KB)
ExpertFolio_2.mqh (121.49 KB)
opt_17_1.mq5 (7.04 KB)
opt_17_2.mq5 (10.18 KB)
Caminhe em novos trilhos: Personalize indicadores no MQL5 Caminhe em novos trilhos: Personalize indicadores no MQL5
Vou agora listar todas as possibilidades novas e recursos do novo terminal e linguagem. Elas são várias, e algumas novidades valem a discussão em um artigo separado. Além disso, não há códigos aqui escritos com programação orientada ao objeto, é um tópico muito importante para ser simplesmente mencionado em um contexto como vantagens adicionais para os desenvolvedores. Neste artigo vamos considerar os indicadores, sua estrutura, desenho, tipos e seus detalhes de programação em comparação com o MQL4. Espero que este artigo seja útil tanto para desenvolvedores iniciantes quanto para experientes, talvez alguns deles encontrem algo novo.
O Método de Agrupamento de Manipulação de Dados: Implementando o Algoritmo Combinatório em MQL5 O Método de Agrupamento de Manipulação de Dados: Implementando o Algoritmo Combinatório em MQL5
Neste artigo, continuamos nossa exploração da família de algoritmos do Método de Agrupamento de Manipulação de Dados, com a implementação do Algoritmo Combinatório, juntamente com sua versão refinada, o Algoritmo Combinatório Seletivo em MQL5.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Como construir e otimizar um sistema de negociação baseado em volatilidade (Chaikin Volatility - CHV) Como construir e otimizar um sistema de negociação baseado em volatilidade (Chaikin Volatility - CHV)
Neste artigo, vamos apresentar outro indicador baseado em volatilidade, chamado Chaikin Volatility. Vamos entender como construir um indicador personalizado, após identificar como ele pode ser usado e construído. Vamos compartilhar algumas estratégias simples que podem ser usadas e, em seguida, testá-las para entender qual delas pode ser melhor.