Assista a como baixar robôs de negociação gratuitos
Encontre-nos em Telegram!
Participe de nossa página de fãs
Script interessante?
Coloque um link para ele, e permita que outras pessoas também o avaliem
Você gostou do script?
Avalie seu funcionamento no terminal MetaTrader 5
Visualizações:
13612
Avaliação:
(53)
Publicado:
2014.01.14 12:31
Atualizado:
2018.06.04 17:56
Precisa de um robô ou indicador baseado nesse código? Solicite-o no Freelance Ir para Freelance

O EA de média móvel está incluído no pacote padrão do terminal do cliente MetaTrader 5 e é um exemplo da EA que negocia com o indicador de Média Móvel.

O arquivo EA Moving Average.mq5 está localizado na pasta "terminal_data_folder\MQL5\Experts\Examples\Moving Average\". Este EA é um exemplo da utilização de indicadores técnicos, histórico de negociações e funções classes de negociação da biblioteca padrão. Além disso, o AE inclui um sistema de gestão de dinheiro que é baseado nos resultados das negociações

Vamos considerar a estrutura do Expert Advisor e como ele funciona.

1. Propriedades do EA

//+------------------------------------------------------------------+
//|                                              Moving Averages.mq5 |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2009-2013, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00

As primeiras 5 linhas contêm um comentário, as três linhas seguintes definem as propriedades do programa MQL5 (copyright, link, versão) utilizando as diretivas de pré-processamento #Property.

Quando você executa o Expert Advisor eles são exibidos na aba "Common":

Propriedades da EA Média Móvel

Figura 1. Parâmetros comuns de EA Média Móvel


1.2. Arquivos de include

Em seguida, a diretiva #Include diz ao compilador para incluir o arquivo "Trade.mqh".

Este arquivo é parte da Biblioteca Padrão, que contém a classe CTrade para facilitar o acesso as funções de negociação.

#include <Trade\Trade.mqh>

O nome do arquivo de inclusão é mostrado entre parênteses "<>;", de modo que o caminho está definido em relação ao diretório: "terminal_data_folder\Include\".

1.3 Entradas

Vai-se o tipo, nome, valores padrão e um comentário. O seu papel é mostrado na fig. 2.

input double MaximumRisk        = 0.02;    // Risco máximo em porcentagem
input double DecreaseFactor     = 3;       // Fator de rebaixamento
input int    MovingPeriod       = 12;      // Período da Média Móvel
input int    MovingShift        = 6;       // Deslocamento da Média Móvel

Os parâmetros MaximumRisk e DecreaseFactor serão utilizados para o gerenciamento de dinheiro, MovingPeriod e MovingShift definem o período e o deslocamento do indicador técnico Média Móvel que será usado ou verificará as condições de negociação.

O texto no comentário na linha de parâmetro de entrada, juntamente com os valores padrão, são exibidos na aba "Options" em vez do nome do parâmetro de entrada:

Parâmetros de entrada do Expert Advisor Média Móvel

Fig. 2. Parâmetros de entrada do EA Média Móvel

1.4. Variáveis ​​globais

Em seguida, a variável global ExtHandle é declarada. Ela será usada para armazenar o manipulador do indicador Média Móvel.

//---
int   ExtHandle=0;

Ele é seguido por seis funções. A finalidade de cada um deles está descrito no comentário antes do corpo da função:

  1. TradeSizeOptimized() - Calcula o tamanho ideal do lote;
  2. CheckForOpen() - Verifica as condições para abertura de posição;
  3. CheckForClose() - Verifica as condições de fechamento da posição;
  4. OnInit() - função de inicialização do Expert;
  5. OnTick() - Função tick do Expert;
  6. OnDeinit() - Função de desinicialização do Expert;

As três últimas funções são funções de manipulação de evento; as três primeiras funções de serviço são chamadas em seu código.


2. Funções de manipulação de eventos

2.1. A função de inicialização OnInit()

A função OnInit() é chamada uma vez durante a inicialização do Expert Advisor. Geralmente no manipulador de eventos OnInit() a EA está preparada para a operação: os parâmetros de entrada são verificados, os indicadores e parâmetros são inicializados, etc No caso de erros críticos, quando o funcionamento não faz sentido, a função é encerrada com um código de retorno INIT_FAILED.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//---
   ExtHandle=iMA(_Symbol,_Period,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE);
   if(ExtHandle==INVALID_HANDLE)
     {
      printf("Erro ao criar o indicador MA");
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }

Desde que a negociação do EA é baseada no indicador de média móvel, chama-se IMA() e o indicador de Média Móvel é criado e seu manipulador é salvo na variável global ExtHandle.

No caso de um erro, OnInit() é encerrado com um código de retorno INIT_FAILED - É uma maneira correta para completar a operação EA/indicador no caso de uma inicialização mal sucedida.


2.2. A função OnTick()

A função OnTick() é chamada cada vez que uma nova cotação é recebida para o símbolo do gráfico, em que a EA é executada.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(void)
  {
//---
   if(PositionSelect(_Symbol))
      CheckForClose();
   else
      CheckForOpen();
//---
  }

A função PositionSelect() é usada para definir se existe uma posição em aberto para o símbolo atual.

Se houver posições em aberto, a função CheckForClose() é chamada, ela analisa o estado atual do mercado e fecha a posição em aberta, caso contrário CheckForOpen() é chamado, ela verifica as condições de entrada no mercado e abre uma nova posição, se tais condições ocorrerem.


2.3. A função de desinicialização OnDeInit()

OnDeInit () é chamada quando um EA é removido a partir do gráfico. Se um programa coloca os objectos gráficos durante a operação, eles podem ser removidos a partir do gráfico.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+

Neste caso, não há a realização de nenhuma ação durante a desinicialização do Expert Advisor.


3. Funções de serviço

3.1. Função TradeSizeOptimized()

Esta função calcula e retorna o valor do tamanho do lote ideal para a posição de abertura com o nível de risco especificado e os resultados das negociações.

//+------------------------------------------------------------------+
//| Calcular o tamanho ideal do lote                                 |
//+------------------------------------------------------------------+
double TradeSizeOptimized(void)
  {
   double price=0.0;
   double margin=0.0;
//--- Calcula o tamanho do lote
   if(!SymbolInfoDouble(_Symbol,SYMBOL_ASK,price))
      return(0.0);
   if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin))
      return(0.0);
   if(margin<=0.0)
      return(0.0);

   double lot=NormalizeDouble(AccountInfoDouble(ACCOUNT_FREEMARGIN)*MaximumRisk/margin,2);
//--- Calcular o comprimento da série de operações consecutivas de perda
   if(DecreaseFactor>0)
     {
      //--- Pedido de todo o histórico de negociação
      HistorySelect(0,TimeCurrent());
      //--
      int    orders=HistoryDealsTotal();  // O número total de ofertas
      int    losses=0;                    // O número de ofertas de perda na série

      for(int i=orders-1;i>=0;i--)
        {
         ulong ticket=HistoryDealGetTicket(i);
         if(ticket==0)
           {
            Print("HistoryDealGetTicket failed, no trade history");
            break;
           }
         //--- verificando o símbolo de negociação
         if(HistoryDealGetString(ticket,DEAL_SYMBOL)!=_Symbol)
            continue;
         //--- verificando o lucro
         double profit=HistoryDealGetDouble(ticket,DEAL_PROFIT);
         if(profit>0.0)
            break;
         if(profit<0.0)
            losses++;
        }
      //---
      if(losses>1)
         lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
     }
//--- Normalizando e verificando os valores permitidos para o volume de negociações
   double stepvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   lot=stepvol*NormalizeDouble(lot/stepvol,0);

   double minvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   if(lot<minvol)
      lot=minvol;

   double maxvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   if(lot>maxvol)
      lot=maxvol;
//--- retorna o valor do volume de negociação
   return(lot);
  }

A função SymbolInfoDouble() é utilizada para verificar a disponibilidade de preços para o símbolo atual, em seguinda, a função OrderCalcMargin() é utilizada para solicitar a margem necessária para colocar uma ordem (neste caso uma ordem de compra). O tamanho inicial do lote é determinado a partir do valor da margem requerida para colocar uma ordem, a margem livre da conta (AccountInfoDouble(ACCOUNT_FREEMARGIN)) e o valor máximo permitido de risco especificadas no parâmetro de entrada MaximumRisk.

Se o valor do parâmetro de entrada DecreaseFactor é positivo, as ordens históricas são analisadas ​e o tamanho do lote é ajustado tendo em conta as informações sobre a série máxima de negócios com perda: o tamanho inicial do lote é multiplicado pelo tamanho (1-perdas/DecreaseFactor).

Em seguida, o volume de negociação é "arredondado" para o valor que é múltiplo do passo mínimo permitido do volume (stepvol) para o símbolo atual. Além disso, os valores máximos (maxvol) e mínimos (minvol) possíveis do volume de negociação são solicitados, e se o valor do lote sair dos limites desejados, ele é ajustado. Como resultado, a função retorna o valor calculado do volume de negóciação.


3.2. Função CheckForOpen()

CheckForOpen() é usado para verificar as condições das posições de abertura ela abre-a quando ocorrem as condições de negociação (neste caso, quando o preço cruza a média móvel).

//+------------------------------------------------------------------+
//| Verificar a existência das condições de abertura de posição      |
//+------------------------------------------------------------------+
void CheckForOpen(void)
  {
   MqlRates rt[2];
//--- Copia os valores do preço
   if(CopyRates(_Symbol,_Period,0,2,rt)!=2)
     {
      Print("CopyRates of ",_Symbol," failed, no history");
      return;
     }
//--- Negocia somento no primeiro tick da barra
   if(rt[1].tick_volume>1)
      return;
//--- Obtém o valor atual do indicador de média móvel 
   double   ma[1];
   if(CopyBuffer(ExtHandle,0,0,1,ma)!=1)
     {
      Print("CopyBuffer from iMA failed, no data");
      return;
     }
//--- verifica os sinais
   ENUM_ORDER_TYPE signal=WRONG_VALUE;

   if(rt[0].open>ma[0] && rt[0].close<ma[0])
      signal=ORDER_TYPE_SELL;    // condição de venda
   else
     {
      if(rt[0].open<ma[0] && rt[0].close>ma[0])
         signal=ORDER_TYPE_BUY;  // condição de compra
     }
//--- verificações adicionais
   if(signal!=WRONG_VALUE)
      if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
         if(Bars(_Symbol,_Period)>100)
           {
            CTrade trade;
            trade.PositionOpen(_Symbol,signal,TradeSizeOptimized(),
                               SymbolInfoDouble(_Symbol,signal==ORDER_TYPE_SELL ? SYMBOL_BID:SYMBOL_ASK),
                               0,0);
           }
//---
  }

Ao negociar usando o movimento, você precisa verificar se o preço cruza a média móvel. Usando a função CopyRates(), dois valores dos preços atuais são copiados no array de estruturas rt[], rt[1] corresponde à barra atual, rt[0] - barra completa.

Um nova barra é iniciada através da verificação do volume de escala da barra atual se ele for igual a 1, uma nova barra se iniciou Deve-se notar que este método de detecção de um nova barra pode falhar em alguns casos (quando as cotações vêm em pacotes), então o fato do início da formação de uma nova barra deve ser feita através do armazenamento e da comparação do tempo da cotação atual (ver IsNewBar).

O valor atual do indicador de média móvel é solicitado usando a função CopyBuffer() e ela é salva no array ma[] que contém apenas um valor. O programa verifica se o preço cruzou a média móvel e faz verificações adicionais (se a negociação com o EA é possível e se há a presença de barras no histórico). Se for bem sucedido, uma posição adequada para o símbolo é aberto chamando o método PositionOpen() do objeto de negociação (uma instância de CTrade).

O preço da abertura da posição é definida através da função SymbolInfoDouble() que retorna o preço de Bid ou Ask, dependendo do valor da variável de sinal. O volume da posição é determinada pela chamada de TradeSizeOptimized() descrito acima.


3.3. Função CheckForClose()

CheckForClose() verifica as condições para o fechamento da posição e fecha se as condições para fechamento ocorrer.

//+------------------------------------------------------------------+
//| Verifica a existência de condições de fechamento da posição      |
//+------------------------------------------------------------------+
void CheckForClose(void)
  {
   MqlRates rt[2];
//--- Copy price values
   if(CopyRates(_Symbol,_Period,0,2,rt)!=2)
     {
      Print("CopyRates of ",_Symbol," failed, no history");
      return;
     }
//--- Negocia somento no primeiro tick da nova barra
   if(rt[1].tick_volume>1)
      return;
//--- Obtêm o valor atual do indicador Média Móvel
   double   ma[1];
   if(CopyBuffer(ExtHandle,0,0,1,ma)!=1)
     {
      Print("CopyBuffer from iMA failed, no data");
      return;
     }
//--- Obter o tipo de posição selecionada anteriormente usando PositionSelect()
   bool signal=false;
   long type=PositionGetInteger(POSITION_TYPE);

   if(type==(long)POSITION_TYPE_BUY   && rt[0].open>ma[0] && rt[0].close<ma[0])
      signal=true;
   if(type==(long)POSITION_TYPE_SELL  && rt[0].open<ma[0] && rt[0].close>ma[0])
      signal=true;
//--- verificações adicionais
   if(signal)
      if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
         if(Bars(_Symbol,_Period)>100)
           {
            CTrade trade;
            trade.PositionClose(_Symbol,3);
           }
//---
  }

O algoritmo da função CheckForClose() é semelhante ao algoritmo CheckForOpen(). Dependendo da direção das posições atuais em aberto, as condições de seus fechamento são verificadas novamente (o preço cruza a MA para baixo para comprar ou para cima, para vender). Uma posição em aberto é fechada chamando o método PositionClose() do objeto de negociação (instância CTrade).


4. Backtesting

Os melhores valores dos parâmetros podem ser encontrados usando o Strategy Tester do terminal MetaTrader 5.

Por exemplo, quando se otimizar o parâmetro MovingPeriod no intervalo 2012.01.01-2013.08.01, os melhores resultados são obtidos com MovingPeriod = 45:

Resultados do Backtesting do Expert Advisor da média móvel

Resultados do Backtesting do Expert Advisor da média móvel

Conclusões:

O Expert Advisor de média móvel está incluído no pacote padrão do terminal MetaTrader 5 é um exemplo da utilização de indicadores técnicos, histórico de negociação, funções classes de negociação da biblioteca padrão. Além disso, o AE inclui um sistema de gestão de dinheiro que é baseado nos resultados das negociações


Traduzido do russo pela MetaQuotes Ltd.
Publicação original: https://www.mql5.com/ru/code/1921

Math-System Math-System

Um conjunto de alvos de níveis de suporte/resistência para o movimento de preço previsto.

DigitalF-T01 DigitalF-T01

Um filtro digital de tendência rápida, com uma linha de referência, implementado na forma de uma nuvem.

MA_3HTF MA_3HTF

Três médias móveis de três períodos de tempo diferentes em um gráfico.

ColorBlauErgodicMACD ColorBlauErgodicMACD

Oscilador MACD Ergódigo implementado na forma de histograma colorido.