Testando Estratégias de Negociação

A ideia de negociação automática é atraente pelo fato de que o robô de negociação pode trabalhar sem parar 24 horas por dia, sete dias por semana. O robô não fica cansado, em dúvida, ou com medo, ele é totalmente livre de quaisquer problemas psicológicos. Basta formalizar de forma clara as regras de negociação e implementá-las nos algoritmos, e o robô está pronto para trabalhar incansavelmente. Mas primeiro, você deve se certificar de que as duas condição importantes seguintes estão satisfeitas:

  • O Expert Advisor realiza operações de negociação em concordância com as regras do sistema de negociação;
  • A estratégia de negociação, implementada no EA, demonstra lucro no histórico.

Para obter respostas para estas questões, nos voltamos para o Provador de Estratégia, incluído no terminal cliente MetaTrader 5.

Esta seção aborda as características do teste e otimização de programa no Provador de Estratégia:

 

Limitações de memória e de espaço em disco na MQL5 Cloud Network

Ao executar a otimização na MQL5 Cloud Network, há uma restrição: o Expert Advisor testado não pode gravar mais de 4 GB de informações no disco e usar mais de 4 GB de RAM. Se o limite for excedido, o agente de rede não conseguirá concluir o cálculo corretamente e você não receberá o resultado do teste. Além disso, você será cobrado pelo tempo já gasto nos cálculos.

Se você precisar obter informações de cada passagem da otimização, use enviar quadros sem gravar no disco. Para não usar operações de arquivo nos Expert Advisors durante os cálculos na MQL5 Cloud Network, você pode aplicar essa verificação:

   int handle=INVALID_HANDLE;
   bool file_operations_allowed=true;
   if(MQLInfoInteger(MQL_OPTIMIZATION) || MQLInfoInteger(MQL_FORWARD))
      file_operations_allowed=false;
 
   if(file_operations_allowed)
     {
      ...
      handle=FileOpen(...);
      ...
     }

 

Restrições de trabalho das funções no testador de estratégias de negociação #

Existem restrições no que diz respeito ao trabalho de algumas funções no testador de estratégias de negociação

Funções Comment(), Print() e PrintFormat() #

A fim de aumentar o desempenho na otimização de parâmetros do expert, não são executadas as funções Comment(), Print() e PrintFormat(). A exceção é o uso dessas funções dentro do manipulador Oninit(). Isto torna mais fácil procurar as causas de erros quando eles ocorrem.

Funções Alert(), MessageBox(), PlaySound(), SendFTP, SendMail(), SendNotification(), WebRequest() #

Funções de interação com o "mundo exterior" Alert(), MessageBox(), PlaySound(), SendFTP(), SendMail(), SendNotification() e WebRequest() não são executadas no testador de estratégias.

 

Modos de Geração de Tick #

Um Expert Advisor é um programa, escrito em MQL5, que é rodado a cada instante em resposta a algum evento externo. O EA tem uma função correspondente (handler de evento) para cada evento pré-definido.

O evento NewTick (mudança de preço) é o evento principal para o EA e, portanto, precisamos gerar um seqüência de ticks para testar o EA. Existem 3 modos de geração de tick implementada no Provador de Estratégia do terminal cliente MetaTrader 5:

  • Cada Tick
  • OHLC por minuto (preços OHLC, Open-High-Low-Close, com barras de minuto)
  • Somente Preços de Abertura

O básico e mais detalhado é o modo "Cada Tick", os outros dois modos são simplificações do modo básico, e serão descritos em comparação com o modo "Cada Tick". Considere todos os três modos em ordem para entender as diferenças entre eles.

"Cada Tick"

Os dados de cotação histórica para instrumentos financeiros são transferidos do servidor de negociação para o terminal cliente MetaTrader 5 na forma de barras de minuto empacotadas. Informações detalhadas sobre a ocorrência de solicitações e a construção das janelas de tempo requiridas podem ser obtidas a partir do capítulo Organizando Acesso a Dados da Referência MQL5.

O elemento mínimo do histórico de preços é a barra de minuto, a partir do qual pode-se obter informações sobre os quatro valores de preços:

  • Abertura (Open) - o preço em que a barra de minuto foi aberta;
  • Máximo (High) - o máximo que foi alcançado durante esta barra de minuto;
  • Mínimo (Low) - o mínimo que foi alcançado durante esta barra de minuto;
  • Fechamento (Close) - o preço de fechamento da barra.

A nova barra de minuto não é aberta no momento que o novo minuto começa (número de segundos se torna igual a 0), mas quando um tick ocorre - uma alteração de preço de no mínimo um ponto. A figura mostra a primeira barra de minuto da nova semana de negociação, que tem a hora de abertura de 2011.01.10 00:00. A diferença de preços entre Sexta e Segunda, que nós vemos no gráfico é comum, já que taxas de moeda flutuam mesmo em fins-de-semana em resposta ao surgimento de notícias.

A diferença de preços entre Sexta e Segunda

Para esta barra, nós sabemos apenas que a barra de minuto foi aberta em 10 de Janeiro de 2011 às 00 horas 00 minutos, mas nós não sabemos nada sobre os segundos. Ela poderia ter sido aberta às 00:00:12 ou 00:00:36 (12 ou 36 segundos após o inicio de um novo dia) ou qualquer outro instante dentro daquele minuto. Mas nós sabemos que o preço de Abertura do EURUSD foi de 1.28940 no instante de abertura da nova barra de minuto.

Nós também não sabemos, em termos de segundos, quando o tick, correspondente ao preço de fechamento da barra de minuto considerada, foi recebido. Nós só sabemos uma coisa - o último preço de Fechamento da barra de minuto. Para este minuto, o preço foi 1.28958. Os instantes de aparecimento dos preços de Máximo e Mínimo também são desconhecidos, mas nós sabemos que os preços máximo e mínimo foram nos níveis de 1.28958 e 1.28940, respectivamente.

Para testar a estratégia de negociação, nós precisamos de uma seqüência de ticks, na qual o trabalho do Expert Advisor será simulado. Assim, para toda barra de minuto, nós conhecemos os 4 pontos de controle, onde os preços definitivamente estiveram. Se uma barra tem apenas 4 ticks, então isso é informação suficiente para realizar um teste, mas geralmente o volume de tick é maior que 4.

Portanto, existe a necessidade de gerar pontos de controle adicionais para ticks, que ocorreram entre os preços de Abertura, Máximo, Mínimo, e Fechamento. O princípio do modo de geração de ticks "Cada tick" é descrito dentro do O Algoritmo de Geração de Ticks dentro da Testador de Estratégia do Terminal MetaTrader 5, um número a partir do qual é apresentado a baixo.

Algoritmo de geração de ticks

Ao testar no modo "Cada Tick", a função OnTick() do EA será chamado a cada ponto de controle. Cada ponto de controle é um tick de uma seqüência gerada. O EA receberá a hora e preço do tick simulado, assim como se estivesse trabalhando online.

Importante: o modo de teste "Cada Tick" é o mais preciso, mas ao mesmo tempo, é o que consome mais tempo. Para um teste inicial da maioria das estratégias de negociação, é geralmente suficiente usar um dos outros dois modos de teste.

"OHLC por minuto"

O modo "Cada Tick" é o mais preciso dos três modos, mas é ao mesmo tempo, o mais lento. A execução do handler OnTick() ocorre a cada tick, a mesmo tempo que o volume de tick pode ser muito grande. Para uma estratégia, na qual a seqüência de ticks da movimentação de preços em toda barra não importa, existe um modo de simulação mais rápido e grosseiro - "OHLC por minuto".

No modo "OHLC por minuto", a seqüência de ticks é construída somente pelos preços OHLC das barras de minuto, o número de pontos de controle gerados é significativamente reduzido - assim como o tempo de teste. O disparo da função OnTick() é realizada sob todos os pontos de controle, que são construídos pelos preços OHLC das barras de minuto.

A opção de não gerar ticks intermediários adicionais entre os preços de Abertura, Máximo, Mínimo e Fechamento, leva ao aparecimento de um rígido determinismo na evolução dos preços, a partir do momento que o preço de Abertura é determinado. Isso torna possível criar um "Teste Graal", que mostra um agradável gráfico ascendente do saldo do teste.

Um exemplo de tal Graal é apresentado no Código Base - Grr-al.

O Expert Advisor Grr-al, ele usa as características especiais de preços OHLC

A figura mostra um gráfico muito atrativo deste teste de EA. Como ele foi obtido? Nós conhecemos 4 preços para uma barra de minuto, e nós sabemos que o primeiro é preço de Abertura, e o último é o preço de Fechamento. Nós temos os preços Máximo e Mínimo entre eles, e a seqüência de suas ocorrências é desconhecida, mas é sabido que o preço Máximo é maior ou igual que o preço de Abertura (e o preço Mínimo é menor ou igual ao preço de Abertura).

É suficiente determinar o momento da recepção do preço de Abertura, e então analisar o próximo tick a fim de determinar que preço nós temos no momento - ou o Máximo ou o Mínimo. Se o preço for abaixo do preço de Abertura, então nós temos um preço Mínimo e comprarmos neste tick, o próximo tick corresponderá ao preço Máximo, no qual nós encerramos a compra e abrimos para venda. O próximo tick é o último, este é o preço de Fechamento, e encerramos a venda nele.

Se após o preço, nós recebermos um tick com um preço maior que o preço de Abertura, então a seqüência de operações (deals) é invertida. Processe uma barra de minuto neste modo "trapaceiro", e espere para pela próxima barra.

Ao testar tal EA no histórico, tudo vai bem, mas uma vez que lançamos ele online, a verdade começa a ser revelada - a linha de saldo permanece regular, porém em direção descendente. Para expor este truque, nós simplesmente precisamos executar o EA no modo "Cada Tick".

Observação: Se os resultados do teste do EA em modos de teste grosseiros ("OHLC por minuto" e "Somente Preços de Abertura") parecerem muito bons, certifique-se de testar-lo no modo "Cada Tick".

"Somente Preços de Abertura"

Neste modo os ticks são gerados baseados nos preços OHLC das janelas de tempo selecionados para teste. A função OnTick() do Expert Advisor roda somente no começo da barra, no preço de Abertura. Devido a este característica, níveis de stop e ordens pendentes podem disparar em um preço que difere do preço especificado (especialmente ao testar em janelas de tempo mais altas). Em contrapartida, nós temos uma oportunidade de executar rapidamente um teste de avaliação do Expert Advisor.

Os períodos W1 e MN1 são exceções no modo de geração de ticks "Somente Preços de Abertura": para estas janelas de tempo, ticks são gerados para os preços OHLC de cada dia, e não preços OHLC da semana ou mês.

Suponha que nós testemos um Expert Advisor sob EURUSD H1 no modo "Somente Preços de Abertura". Neste caso o número total de ticks (pontos de controle) não será mais que 4 * número de barras de uma-hora dentro do intervalo testado. Mas o handler OnTick() é chamado somente na abertura da barra de uma-hora. As verificações requeridas para um teste correto ocorrem no resto dos ticks (que são "escondidas" do EA).

  • O cálculo de requerimentos de margem;
  • O disparo de níveis de Stop Loss e Take Profit;
  • O disparo de ordens pendentes;
  • A remoção de ordens pendentes expiradas.

Se não existirem nenhum posição aberta ou ordens pendentes, nós não precisamos realizar destas verificações nos ticks escondidos, e o aumento da velocidade pode ser bastante substancial. Este modo "Somente Preços de Abertura" é bem adequado para testar estratégias que processam operações (deals) somente na abertura da barra e não usam ordens pendentes, bem como ordens Stop Loss e Take Profit. Para estratégias deste tipo, a necessidade de precisão do teste é preservada.

Vamos usar o Expert Advisor Moving Average (Média Móvel) do pacote padrão como exemplo de um EA, que pode ser testado em qualquer modo. A lógica deste EA é construído de tal forma que todas as decisões são feitas na abertura da barra, e operações (deals) são executadas imediatamente, sem o uso de ordens pendentes.

Executar um teste de EA no EURUSD H1 sobre um intervalo a partir de 2010.09.01 to 2010.12.31, e comparar os gráficos. A figura mostra o gráfico de saldo do relatório de teste para todos os três modos.

O gráfico de teste do EA Moving Average.mq5 do pacote padrão não depende do modo do teste

Como se pode ver, os gráficos nos diferentes modos de teste são exatamente o mesmo para o EA Moving Average do pacote padrão.

Existem algumas limitações no modo "Somente Preços de Abertura":

  • Você não pode usar o modo de execução Atraso Aleatório.
  • No Expert testado, você não pode acessar os dados do período inferior do período utilizado para o teste/otimização. Por exemplo, se você rodar um teste em M20, você não pode acessar dados de M30, mas é possível acessar H1. Além disso, os períodos superiores que são acessados ​​devem ser múltiplos do período do teste. Por exemplo, se você rodar um teste em M20, você não pode acessar dados de M30, mas é possível acessar H1. Estas limitações estão relacionadas com a impossibilidade de se obter dados de períodos inferiores ou não múltiplos de fora das barras geradas durante o teste/otimização.
  • Limitações no acesso a dados de outros períodos também se aplicam a outros ativos cujos dados são usados ​​pelo Expert Advisor. Neste caso, a limitação para cada ativo depende do primeiro período acessado durante o teste/otimização. Suponha que durante teste em EURUSD H1, um Expert Advisor acesse dados de GBPUSD M20. Neste caso, o Expert será capaz de continuar a usar os dados de EURUSD H1, H2, etc, bem como GBPUSD M20, H1, H2, etc.

Observação: O modo "Somente Preços de Abertura" tem o mais rápido tempo de teste, mas não é adequado para todas as estratégias de negociação. Selecione o modo de teste desejado baseado nas características do sistema de negociação.

Para concluir a seção sobre os modos de geração de tick, vamos considerar uma comparação visual dos diferentes modos de geração de tick para EURUSD, para duas barras de M15 no intervalo de 2011.01.11 21:00:00 - 2011.01.11 21:30:00.

Os ticks foram salvos em arquivos diferentes usando o EA WriteTicksFromTester.mq5 e o fim desses nomes de arquivos são especificados nos parâmetros de entrada filenameEveryTick, filenameOHLC e filenameOpenPrice input-parameters.

Nós podemos especificar as datas de início e fim dos ticks (as variáveis start e end) para o Expert Advisor WriteTicksFromTester

Para obter três arquivos com três seqüências de tick (para cada um dos seguintes modos: "Cada Tick", "OHLC por minuto" e "Somente Preços de Abertura"), o EA foi disparado três vezes nos modos correspondentes, em execuções individuais. Então, os dados destes três arquivos foram exibidos no gráfico usando o indicador TicksFromTester.mq5. O código do indicador está anexado neste artigo.

A seqüência de tick no Provador de Estratégia do terminal MetaTrader 5 em três diferentes modos de teste

Por padrão, todos as operações de arquivo na linguagem MQL5 são feitas dentro da "caixa de areia de arquivo" e durante um teste o EA tem acesso somente a sua própria "caixa de areia de arquivo". A fim de que o indicador e o EA trabalhem com arquivos provenientes de uma pasta comum durante o teste, nós usados o flag FILE_COMMON. Um exemplo de código do EA:

//--- abre o arquivo
   file=FileOpen(filename,FILE_WRITE|FILE_CSV|FILE_COMMON,";");
//--- verifica a handle de arquivo
   if(file==INVALID_HANDLE)
     {
      PrintFormat("Erro na abertura do arquivo %s para escrever. Erro de codigo=%d",filename,GetLastError());
      return;
     }
   else
     {
      PrintFormat("O arquivo será criado na %s pasta",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

Para ler dos dados no indicador, nós também usamos o flag FILE_COMMON. Isso nós permite evitar transferir manualmente os arquivos necessários de uma pasta para outra.

//--- abre o arquivo
   int file=FileOpen(fname,FILE_READ|FILE_CSV|FILE_COMMON,";");
//--- verifica a handle de arquivo
   if(file==INVALID_HANDLE)
     {
      PrintFormat("Erro na abertura do arquivo %s para leitura. Erro de codigo=%d",fname,GetLastError());
      return;
     }
   else
     {
      PrintFormat("Arquivo será aberto a partir %s",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

Simulação de Spread #

A diferença de preço entre os preços de Venda (Bid) e Compra (Ask) é chamado de spread. Durante um teste, o spread não é modelado mas é obtido a partir de dados históricos. If the spread is less than or equal to zero in the historical data, then the last known (at the moment of generation) spread  of is used by testing agent.

No Provador de Estratégia, o spread é sempre considerado flutuante. Isto é, a função SymbolInfoInteger(symbol, SYMBOL_SPREAD_FLOAT) sempre retorna true.

Além disso, os dados históricos contém valores de tick e volumes de negociação. Para o armazenamento e recuperação dos dados nós usamos a estrutura especial MqlRates:

struct MqlRates
  {
   datetime time;         // Hora de início do período
   double   open;         // Preço de Abertura
   double   high;         // O mais alto preço do período
   double   low;          // O mais baixo preço do período
   double   close;        // Preço de Fechamento
   long     tick_volume;  // Volume de Tick
   int      spread;       // Spread
   long     real_volume;  // Volume de Negociação
  };

Usando ticks reais durante os testes #

O teste e a otimização de acordo com ticks reais se aproximam ao máximo das condições reais. Em vez de ticks gerados com base em dados de minuto, são usados ticks reais acumulados pela corretora. Esses são ticks provindos da bolsa e dos provedores de liquidez.

Para garantir a maior precisão - durante os testes em modo de ticks reais - também são usadas as barras de minuto. Nelas são verificados e corrigidos os dados de ticks. Isto também evita a divergência de gráficos no testador e no terminal de cliente.

O testador verifica a correspondência entre os dados de tick e os parâmetros da barra de minuto, isto é: o tick não deve ultrapassar os preços High/Low da barra; o tick que a abre e fecha o minuto deve coincidir com os preços Open/Close da barra. Também é comparado o volume. Se identificada uma diferença, são descartados todos os ticks correspondentes a esta barra de minuto. Em vez deles, serão utilizados os ticks gerados (como no modo "Cada tick").

Se no histórico do símbolo existir uma barra de minuto, mas, se, nesse minuto, não houver dados de ticks, o testador gerará ticks no modo "Todos os ticks". Isto permite plotar corretamente o gráfico no testador, caso a corretora tenha os dados de tick incompletos.

Se, no histórico do símbolo, não existir uma barra de minuto, mas, se, nesse minuto, houver dados de ticks, então, esses ticks podem ser utilizados. Por exemplo, as barras de símbolos de bolsa são formados de acordo com os preços Last. Se, a partir do servidor, chegarem apenas ticks com preços Bid/Ask sem preço Last, a barra não será formada. O testador usará estes dados de ticks, uma vez que eles não contradizem as de minuto.

Os dados de ticks podem ser diferentes das barras de minuto por várias razões. Por exemplo, devido a desconexões ou outras falhas, quando dados são transferidos da fonte para o terminal de cliente. Ao testar, os dados de minuto são considerados mais confiáveis.

Ao testar ticks reais, considere as seguintes particularidades:

  • Ao executar o teste, não só são sincronizados os dados de ticks, mas também os de minuto de acordo com o instrumento.
  • Os ticks são armazenados no cache do símbolo no testador de estratégias. O tamanho do cache é inferior a 128 000 ticks. Após chegarem novos ticks, seus dados mais antigos serão empurrados para fora. No entanto, com ajuda da função CopyTicks podem ser obtidos ticks fora do cache (somente nos testes em ticks reais). Neste caso, os dados serão solicitados a partir da base de ticks do testador, ela corresponde completamente à base de dados do terminal de cliente. Nesta base não é feito nenhum ajuste de barras de minuto. Portanto, os ticks nele podem ser diferentes dos ticks no cache.

As Variáveis Globais do Terminal Cliente #

Durante um teste, as variáveis globais do terminal cliente são também emulados, mas elas não estão relacionadas como as variáveis globais correntes do terminal, que podem ser vistas no terminal usando a tecla F3. Significa que todas as operações com as variáveis globais do terminal, durante um teste, acontecem fora terminal cliente (no agente de teste).

O Cálculo de Indicadores durante um Teste #

No modo tempo-real, os valores dos indicadores são calculados a cada tick.

No testador de estratégia, os indicadores são calculados apenas quando são acessados à procura de dados, ou seja, apenas no momento em que os valores dos buffers dos indicadores são solicitados. A exceção a isto é quando indicadores personalizados são definidos como #property tester_everytick_calculate, neste caso, o recálculo é feito a cada tick.

No modo de teste visual, todos os indicadores são recalculados incondicionalmente com a chegada de um novo tick, de modo a aparecerem corretamente no gráfico de teste visual.

O cálculo do indicador a cada tick é feito uma vez e todas as subsequentes solicitações de dados do indicador antes da chegada de um novo tick não provocarão um recálculo. Por isso, se, no Expert Advisor, o timer estiver ativo com a função EventSetTimer(), antes da chamada do handler OnTimer() serão solicitados os dados do indicador desde a recepção do último tick. Se o indicador ainda não tiver sido calculado no último tick, será iniciado o cálculo dos valores do indicador. Se os dados já tiverem sido preparados, eles serão fornecidos sem um novo recálculo.

Assim, todos os cálculos do indicador são feitos da forma mais econômica possível, quer dizer, se o indicador já tiver sido calculado em um determinado tick, os dados do indicador serão fornecidos como estão, ou seja, o indicador não é será recalculado.

Carregando Histórico durante Teste #

O histórico de um ativo a ser testado é sincronizado e carregado pelo terminal a partir do servidor de negociação antes de começar o processo de teste. Durante a primeira vez, o terminal carrega todo o histórico disponível de um ativo de forma a não requerer este histórico mais tarde. Após isso, somente dados novos são carregados.

Um agente de teste recebe o histórico de um ativo a ser testado a partir do terminal cliente logo após o começo do teste. Se os dados de outros instrumentos são usados no processo de teste (por exemplo, é um Expert Advisor multi-moeda), o agente de teste solicita o histórico requerido do terminal cliente durante a primeira chamada a tais dados. Se os dados históricos estiverem disponíveis no terminal, eles são imediatamente passados para o agente de teste. Se os dados não estiverem disponíveis, o terminal solicita e os baixa do servidor, e então os passa para o agente de teste.

Dados de instrumentos adicionais também são requeridos para calcular taxas-cruzadas de operações de negociação. Por exemplo, ao testar uma estratégia em EURCHF com a moeda de depósito em USD, antes de processar a primeira operação de negociação, o agente de teste solicita os dados históricos de EURUSD e USDCHF do terminal cliente, embora a estratégia não contenha chamadas de uso direta a estes ativos.

Antes de testar um estratégia multi-moeda, é recomendável baixar todos os dados históricos necessários para o terminal cliente. Isso ajudará a evitar atrasos em um teste/otimização associado com a baixa dos dados requeridos. Você pode baixar histórico, por exemplo, via abertura dos gráficos apropriados e rolá-los para o começa do histórico. Um exemplo de carga forçada de histórico para o terminal está disponível na seção Organizando Acesso a Dados da Referência MQL5.

Agentes de teste, por sua vez, recebem o histórico do terminal no formato compactado. Durante o próximo teste, o Provador de Estratégia não carrega o histórico do terminal, porque os dados requeridos estão disponíveis desde a execução anterior do Provador de Estratégia.

  • O termianl carrega o histórico a partir de um servidor de negociação apenas uma vez, na primeira vez que o agente solicita o histórico de um ativo a ser testado do terminal. O histórico é carregado em forma de pacote para reduzir o tráfego.
  • Ticks não são enviados pela rede, eles são gerados nos agentes de teste.

Teste Multi-Moeda #

O Provador de Estratégia nos permite realizar um teste de estratégias, negociando em múltiplos ativos. Tais EAs são convencionalmente referidos como Expert Advisors multi-moedas, já que originalmente, um teste era realizado somente para um único ativo. No Provador de Estratégia do terminal MetaTrader 5, nós podemos modelar negociação para todos os ativos disponíveis.

O Provador de Estratégia carrega o histórico dos ativos usados do terminal cliente (não do servidor de negociação!) automaticamente durante a primeira chamada aos dados do ativo.

O agente de teste baixa somente o histórico faltante, com uma pequena margem para fornecer os dados necessários no histórico para o cálculo dos indicadores no período inicial do teste. Para as janelas de tempo D1 ou menor, o volume mínimo de histórico baixado é de um ano.

Assim, se nós rodarmos um teste no intervalo 2010.11.01-2010.12.01 (teste para um intervalo de um mês) com um período de M15 (cada barra e igual a 15 minutos), então será solicitado ao terminal o histórico do instrumento para o ano inteiro de 2010. Para a janela de tempo semanal, nós solicitaremos um histórico de 100 barras, que é aproximadamente dois anos (um ano tem 52 semanas). Para testar em uma janela de tempo mensal, o agente solicitará o histórico de 8 anos (12 meses x 8 anos = 96 meses).

Se não houver barras necessárias, a data de ínicio do teste será automaticamente deslocada do passado para o presente para fornecer a reserva necessária de barras antes do teste.

Durante um teste, a janela "Observação de Mercado" é também emulada, a partir do qual se pode obter informações sobre os ativos.

Por padrão, no começo de um teste, existe somente um ativo na "Observação de Mercado" do Provador de Estratégia - o ativo em que o teste está rodando. Todos os ativos necessários são conectados à janela "Observação de Mercado" do Provador de Estratégia (não ao terminal!) automaticamente quando referenciados.

Antes de começar um teste de um Expert Advisor multi-moeda, é necessário selecionar os ativos requeridos para o teste na janela "Observação de Mercado" do terminal e carregar os dados requeridos. Durante a primeira chamada de um ativo "estrangeiro", seu histórico será automaticamente sincronizado entre o agente de teste e o terminal cliente. Um ativo "estrangeiro" é o outro ativo, diferente daquele em que o teste é rodado.

Referência aos dados de um "outro" ativo ocorre nos seguintes casos:

  • Solicitação da série de tempo para um ativo/janela de tempo atráves do uso das seguintes funções:

No momento da primeira chamada a um "outro" ativo, o processo de teste é interrompido e o histórico é baixado para o ativo/período, do terminal para o agente de teste. Ao mesmo tempo, a geração da seqüência de tick para este ativo é feita.

Uma seqüência de tick individual é gerada para cada ativo, de acordo com o modo de geração de tick selecionado. Você também pode solicitar explicitamente o histórico dos ativos desejados através de chamada ao SymbolSelect() no handler OnInit() - a baixa do histórico será feita imediatamente antes do teste do Expert Advisor.

Assim, não é necessário nenhum esforço extra para realizar teste de multi-moeda no terminal cliente MetaTrader 5. Apenas abra os gráficos dos apropriados ativos no terminal cliente. O histórico será automaticamente carregado do servidor de negociação para todos os ativos requeridos, contanto que ele contenha estes dados.

Simulação de Tempo no Provador de Estratégia #

Durante um teste, a hora local TimeLocal() é sempre igual a hora do servidor TimeTradeServer(). Por sua vez, a hora do servidor é sempre igual a hora correspondente à hora GMT - TimeGMT(). Desta forma, todas estas funções mostram a mesma hora durante um teste.

A ausência de diferença entre as horas GMT, local, e do servidor no Provador de Estratégia é feita deliberadamente para o caso de não haver conexão com o servidor. Os resultados do teste devem sempre ser os mesmos, independentemente de haver ou não uma conexão. Informações sobre a hora do servidor não é armazenado localmente, e é obtido do servidor.

Objetos Gráficos no Teste #

Durante um teste/otimização objetos gráficos não são plotados. Assim, ao referenciar as propriedades de um objeto criado durante um teste/otimização, um Expert Advisor receberá valores zero.

Este limitação não se aplica ao se testar em modo visual.

A Função OnTimer() no Provador de Estratégia #

MQL5 fornece a oportunidade de tratar eventos de timer. A chamada ao handler OnTimer() é feita independentemente do modo do teste. Isso significa que se um teste é rodado no modo "Somente Preços de Abertura" para o período H4, e o EA tem um timer definido para uma chamada por segundo, então na abertura de cada barra de H4, o handler OnTick() será chamado uma vez, e o handler OnTimer() será chamado 14400 vezes (3600 segundos * 4 horas). A quantidade de tempo de teste do EA que será aumentada depende da lógica do EA.

Para verificar a dependência do tempo de teste a partir de um dada freqüência do timer, nós temos que criar um EA simples sem nenhum operação de negociação.

//--- parâmetros de entrada
input int      timer=1;              // valor do timer, segundos
input bool     timer_switch_on=true; // timer ativado
//+------------------------------------------------------------------+
//| Função de inicialização do Expert                                |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- rodar o timer se timer_switch_on==true
   if(timer_switch_on)
     {
      EventSetTimer(timer);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Função de Desinicialização do Expert                             |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- para o timer
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Função Timer                                                     |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
// nenhum ação é tomada, o corpo do handler está vazio
  }
//+------------------------------------------------------------------+

As medições de tempo de tempo são obtidas em valores diferentes do parâmetro timer (periodicidade do evento Timer). Sob os dados obtidos, nós plotamos o tempo do teste como função do período do Timer.

O tempo do teste como uma função do período do Timer

Pode-se ver claramente que quanto menor é o parâmetro do timer, durante a a inicialização da função EventSetTimer, menor é o período entre as chamadas do handler OnTimer(), e maior é o tempo de teste, sob as mesmas outras condições.

A Função Sleep() no Provador de Estratégia #

A função Sleep() permite ao EA ou script suspender a execução do programa MQL5 por um tempo, ao trabalhar no gráfico. Isso pode ser útil ao solicitar dados, que não estão prontos no momento da solicitação e você precisa esperar até eles estarem prontos. Um exemplo detalhado do uso da função Sleep() pode ser encontrado na seção Preparativo para acesso a dados.

O processo de teste não é atrasado por chamadas à função Sleep(). Quando você chama o Sleep(), os ticks gerados são "jogados" com um atraso especificado, que pode resultar no disparo de ordens pendentes, stops, etc. Após uma chamada do Sleep(), o tempo simulado no Provador de Estratégia aumenta em um intervalo, especificado no parâmetro da função Sleep.

Se como resultado da execução da função Sleep(), o tempo corrente no Provador de Estratégia passar do período de teste, então você receberá o erro "Infinite Sleep loop detected while testing". Se você receber este erro, os resultados do teste não serão rejeitados, todas as computações são realizadas em seus volumes completos (o número de operações (deals), abrandamento, etc) e os resultados deste teste são transmitidos para o terminal.

A função Sleep() não funcionará em OnDeinit(), já que após ele ser chamado, será certo que o tempo de teste ultrapassará a faixa do intervalo de teste.

O esquema de uso da função Sleep() no Provador de Estratégia do terminal MetaTrader 5

Usando o Provador de Estratégia para Problemas de Otimização em Cálculos Matemáticos #

O Provador de Estratégia no terminal MetaTrader 5 pode ser usado, não apenas para testar estratégias de negociação, mas também para cálculos matemáticos. Para usar-lo, é necessário selecionar o modo "Cálculos matemáticos"

math_calculations

Neste caso, somente três funções serão chamadas: OnInit(), OnTester(), OnDeinit(). No modo "Cálculos matemáticos" o Provador de Estratégia não gera nenhum tick e não baixa o histórico.

O Provador de Estratégia também trabalha em modo "Cálculos matemáticos" se você especificar a data inicial maior que a data final.

Ao usar o Provador de Estratégia para resolver problemas matemáticos, a carga do histórico e a geração de ticks não ocorrem.

Um problema matemático típico para ser revolvido no Provador de Estratégias do MetaTrader 5 - busca de um extremo de uma função com muitas variáveis.

Para resolvê-lo nos precisamos que:

  • O cálculo do valor da função deve estar localizado na função OnTester();
  • Os parâmetros da função devem estar definidos como variáveis de entrada do Expert Advisor;

Compilar o EA, abrir a janela "Provador de Estratégia". Na guia "Parâmetros de entrada", selecionar as requeridas variáveis de entrada, e definir o conjunto de valores de parâmetros por meio da especificação dos valores iniciar, parar, e passo de cada uma das variáveis da função.

Selecionar o tipo de otimização - "Algoritmo completo lento" (busca completa do espaço de parâmetros) ou "Rápido (algoritmo genético)". Para uma busca simples do extremo da função, é melhor escolher uma otimização rápida, mas se você quiser calcular os valores para conjunto inteiro de variáveis, então é melhor usar a otimização lenta.

Selecione o modo "Cálculo matemático" e usando o botão "Iniciar", executar a procedimento de otimização. Note que ao otimizar, o Provador de Estratégia buscará pelos valores máximos da função OnTester. Para encontrar um mínimo local, retorne o inverso do valor computado da função proveniente da função OnTester:

return(1/function_value);

É necessário verificar que o function_value não é igual a zero, já que de outra forma nós podemos obter um erro crítico de dividir por zero.

Existe uma outra forma, mais conveniente e que não distorce os resultados da otimização, ela foi sugerida pelos leitores deste artigo:

return(-function_value);

Esta opção não requer a verificação do function_value ser igual a zero, e a superfície dos resultados da otimização em uma representação em 3D tem a mesma forma, porém é espelhada da original.

Como exemplo, fornecemos a função sink():

sink_formula

O código do EA para encontrar o extremo desta função é colocada dentro do OnTester():

//+------------------------------------------------------------------+
//|                                                         Sink.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- parâmetros de entrada
input double   x=-3.0; // start=-3, step=0.05, stop=3
input double   y=-3.0; // start=-3, step=0.05, stop=3
//+------------------------------------------------------------------+
//| Tester function                                                  |
//+------------------------------------------------------------------+
double OnTester()
  {
//---
   double sink=MathSin(x*x+y*y);
//---
   return(sink);
  }
//+------------------------------------------------------------------+

Execute uma otimização e veja os resultados da otimização na forma de um gráfico 2D.

Os resultados da otimização completa da função sink (x*x+y*y) como gráfico 2D

Quanto melhor for o valor para um dado par de parâmetros (x,y), mais saturada é a cor. Como era esperado a partir da observação da forma da formula sink(), seus valores forma círculos concêntricos com centro em (0,0). Pode-se ver no gráfico 3D, que a função sink() não tem um único extremo global:

Gráfico 3D da função sink

A Sincronização de Barras no modo "Somente Preço de Abertura" #

O Provador de Estratégia no terminal cliente do Metatrader 5 permite-nos verificar os chamados EAs "multi-moedas". Uma EA multi-moeda - é um EA que negocia sobre dois ou mais ativos.

O teste de estratégias, que negociam em ativos múltiplos, impõe alguns requerimentos técnicos adicionais ao Provador de Estratégia:

  • A geração de ticks para estes ativos;
  • O cálculo de valores de indicadores para estes ativos;
  • O cálculo de requerimentos de margem para estes ativos;
  • Sincronização das seqüências de ticks geradas para todos os ativos negociados.

O Provador de Estratégia gera e joga uma seqüência de ticks para cada instrumento em concordância com o modo de negociação selecionado. Ao mesmo tempo e para cada ativo, uma nova barra é aberta, independentemente de como a barra abriu em outro ativo. Isso significa que ao testar um EA multi-moeda, uma situação pode ocorrer (e freqüentemente acontece), quando para um instrumento, uma nova barra já abriu, e para o outro instrumento, ela não abriu. Assim, em um teste, tudo acontece como na realizada.

Esta simulação autêntica do histórico no Provador de Estratégia não causa nenhum problema contanto que os modos de teste "Cada Tick" e "OHLC por minuto" sejam usados. Para estes modos, ticks suficientes são gerados para um candlestick, para ser capaz de esperar até a sincronização das barras de diferentes ativos aconteça. Mas como nós testamos estratégias multi-moeda no modo "Somente Preços de Abertura", se a sincronização das barras nos instrumentos de negociação é obrigatória? Neste modo, o EA é chamado somente em um tick, que corresponde ao momento de abertura das barras.

Nós ilustraremos isso com um exemplo: se nós estamos testando um EA no EURUSD, e um novo candlestick de hora abriu em EURUSD, então podemos reconhecer facilmente este fato - em um teste no modo "Somente Preços de Abertura", o evento NewTick corresponde ao momento da abertura da barra sobre o período do teste. Mas não exitem garantias que o novo candlestick abriu no ativo USPJPY, é que usado no EA.

Em condições normais, é suficiente completar o trabalho da função OnTick() e verificar pelo surgimento de uma nova barra em USDJPY no próximo tick. Mas ao testar em modo "Somente Preços de Abertura", não haverá um outro tick, e assim pode parecer que este modo não é adequado para testar EAs multi-moedas. Mas isso não é o caso - não se esqueça que o testador no MetraTrader 5 se comporta como se fosse no mundo real. Você pode esperar até uma nova barra ser aberta em outros ativos usando a função Sleep()!

O código do EA Synchronize_Bars_Use_Sleep.mq5, que mostra um exemplo da sincronização de barras no modo "Somente Preços de Abertura":

//+------------------------------------------------------------------+
//|                                   Synchronize_Bars_Use_Sleep.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- parâmetros de entrada
input string   other_symbol="USDJPY";
//+------------------------------------------------------------------+
//| Função de inicialização do Expert                                |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- verifica ativo
   if(_Symbol==other_symbol)
     {
      PrintFormat("Você tem de especificar outro símbolo nos parâmetros de entrada ou selecionar outro símbolo no Testador de Estratégia!");
      //--- força parar teste
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Função tick (ponto) de um Expert                                 |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- variável estática usada para armazenar a hora da última barra
   static datetime last_bar_time=0;
//--- flag de sincronização
   static bool synchonized=false;
//--- caso a variável estática não esteja inicializada
   if(last_bar_time==0)
     {
      //--- é a primeira chamada, salva hora da barra e saiu
      last_bar_time=(datetime)SeriesInfoInteger(_Symbol,Period(),SERIES_LASTBAR_DATE);
      PrintFormat("A variável last_bar_time é inicializada com valor %s",TimeToString(last_bar_time));
     }
//--- obtém hora de abertura da última barra do ativo do gráfico
   datetime curr_time=(datetime)SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE);
//--- se as horas não são iguais
   if(curr_time!=last_bar_time)
     {
      //--- salva a hora da barra aberta na variável estática
      last_bar_time=curr_time;
      //--- não sincronizado
      synchonized=false;
      //--- imprime mensagem
      PrintFormat("Uma nova barra está aparecendo no símbolo %s em %s",_Symbol,TimeToString(TimeCurrent()));
     }
//--- hora de abertura da barra de outra ativo
   datetime other_time;
//--- loop até a hora de abertura do outro ativo ser igual a curr_time
   while(!(curr_time==(other_time=(datetime)SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE)) && !synchonized))
     {
      PrintFormat("Espera 5 segundos..");
      //--- espera 5 segundos e chama SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE)
      Sleep(5000);
     }
//--- barras são sincronizadas
   synchonized=true;
   PrintFormat("Tempo de abertura da barra do símbolo %s do gráfico: é %s",_Symbol,TimeToString(last_bar_time));
   PrintFormat("Tempo de abertura da barra do símbolo %s: é %s",other_symbol,TimeToString(other_time));
//--- TimeCurrent() não é útil, usar TimeTradeServer()
   Print("As barras são sincronizadas em ",TimeToString(TimeTradeServer(),TIME_SECONDS));
  }
//+------------------------------------------------------------------+

Perceba que a última linha no EA, que exibe a hora corrente quando o sincronização de fato foi estabelecida:

   Print("As barras são sincronizadas em ",TimeToString(TimeTradeServer(),TIME_SECONDS));

Para exibir a hora corrente usamos a função TimeTradeServer() ao invés de TimeCurrent(). A função TimeCurrent() retorna o hora do último tick, que não se altera após usar Sleep(). Executa o EA no modo "Abertura de preços apenas",e você verá uma mensagem sobre a sincronização dos barras.

Synchronize_Bars_Use_Sleep_EA

Use a função TimeTradeServer() ao invés de TimeCurrent(), se você precisar obter hora corrente do servidor, e não a hora da chegado do último tick.

Existe uma outra forma para sincronizar barras - usando um timer. Um exemplo de tal EA é Synchronize_Bars_Use_OnTimer.mq5, que está anexado neste artigo.

A função IndicatorRelease() no Provador de Estratégia #

Após completar um teste individual, um gráfico do instrumento é automaticamente aberto, que exibe as operações (deals) completas e os indicadores usados no EA. Isso ajuda a verificar visualmente os pontos de entrada e saída, e comprará-los com os valores dos indicadores.  

Observação: indicadores, exibidos no gráfico, que automaticamente abrem após a conclusão do teste, são calculados novamente após a conclusão do teste. Mesmo se estes indicadores foram usados no EA testado.

Mas em alguns casos, o programador pode querer ocultar a informação sobre quais indicadores estavam envolvidos nos algoritmos de negociação. Por exemplo, o código do EA é alugado ou vendido como um arquivo executável, sem o fornecimento do código fonte. Para este propósito, a função IndicatorRelease() é apropriada.

Se o terminal define um template com o nome tester.tpl no directory/profiles/templates do terminal cliente, então ele será aplicado ao gráfico aberto. Na usa ausência, o template padrão é aplicado. (default.tpl).

A função IndicatorRelease() é originalmente destinada para liberar a porção de cálculo do indicador, caso ele mais mais seja necessário. Isso permite economizar tanto a memória quando os recursos de CPU, porque cada tick pede um cálculo do indicador. Seu segundo propósito - é proibir a exibição de um indicador no gráfico de teste, após uma execução de teste individual.

Para proibir a exibição do indicador no gráfico após um teste, chame o IndicatorRelease() com o handle do indicator no handler OnDeinit(). A função OnDeinit() é sempre chamada após a conclusão e antes da exibição do gráfico de teste.

//+------------------------------------------------------------------+
//| Função de Desinicialização do Expert                             |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   bool hidden=IndicatorRelease(handle_ind);
   if(hidden) Print("IndicatorRelease() completado com sucesso");
   else Print("IndicatorRelease() retorna false. Erro de código ",GetLastError());
  }

A fim de proibir a exibição do indicador no gráfico, após a conclusão de um teste único, use a função IndicatorRelease() no handler OnDeinit().

Tratamento de Evento no Provador de Estratégia #

A presença do handler OnTick() no EA não é obrigatória para que possa ser passível de teste em dados históricos no Provador de Estratégias do MetaTrader 5. É suficiente para o EA conter pelo menos as seguintes funções-handlers:

  • OnTick() - Handler de evento de uma nova chegada de tick;
  • OnTrade() - Handler de evento de negociação;
  • OnTimer() - Handler de evento de uma chegada de sinal do timer;
  • OnChartEvent() - um handler para eventos de cliente.

Ao testar um EA, nós pode tratar eventos customizados usando a função OnChartEvent(), mas nos indicadores, esta função não pode ser chamada no testador. Mesmo se o indicador tiver o handler de evento OnChartEvent() e este indicador for usado em um EA testado, o indicador em si não receberá nenhum evento customizado.

Durante um teste, um Indicador pode gerar eventos customizados usando a função EventChartCustom(), e o EA pode processar este evento no OnChartEvent().

Além destes eventos, eventos especiais associados com o processo de teste e otimização são gerados no Provador de Estratégia:

  • Tester - este evento é gerado após conclusão do teste do Expert Advisor sobre dados históricos. O evento Tester é tratado usando a função OnTester(). Esta função pode ser usada apenas quando testar Expert Advisor e está destinada sobretudo para o cálculo de um valor que é usado como um critério máximo personalizado para otimização de parâmetros de entrada genérica.
  • TesterInit - este evento é gerado durante o início da otimização no Provador de Estratégia e antes do primeiro passo. O evento TesterInit é tratado usando a função OnTesterInit(). Durante o início da otimização, um Expert Advisor com este handler é carregado automaticamente em um gráfico de terminal separado com o ativo e período especificados no testador, e recebe o evento TesterInit. Esta função é usada para inicializar um Expert Advisor antes de iniciar a otimização para posterior processamento dos resultados da otimização.
  • TesterPass - este evento é gerado quanto um novo data frame é recebido. O evento TesterPass é tratado usando a função OnTesterPass(). Um Expert Advsor com este handler é carregado automaticamente em um gráfico de terminal separado com o ativo/período especificados para teste, e recebe um evento TesterPass quando um frame é recebido durante otimização. A função é usado para tratamento dinâmico de resultados de otimização "in loco" sem esperar pela sua conclusão. Frames são adicionados usando a função FrameAdd(), que pode ser chamada após o fim de um passo individual no handler OnTester().
  • TesterDeinit - este evento é gerado após o fim da otimização do Expert Advisor no Provador de Estratégia. O evento TesterDeinit é tratado usando a função OnTesterDeinit(). Um Expert Advisor com este handler é carregado automaticamente em um gráfico no começo da otimização, e recebe TesterDeInit após sua conclusão. A função é usado para o processamento final de todos os resultados da otimização.

Agentes de Teste #

O teste no terminal cliente MetaTrader 5 é realizado usando agentes de teste. Agentes locais são criados e habilitados automaticamente. O número padrão de agentes locais corresponde ao número de núcleos em um computador.

Cada agente de teste tem sua própria cópia das variáveis globais, que não são relacionados com o terminal cliente. O terminal em si é o despachante, que distribui as tarefas para os agentes locais e remotos. Apos executar uma tarefa no teste de um EA, com os parâmetros dados, o agente retorna o resultado para o terminal. Para um teste individual, somente um agente é usado.

O agente armazena o histórico, recebido do terminal, em pastas separadas, pelo nome do instrumento, assim o histórico para EURUSD é armazenado em uma pasta chamada EURUSD. Além disso, o histórico dos instrumentos é separado pelas suas fontes. A estrutura para armazenar o histórico tem o seguinte forma:

tester_catalog\Agent-IPaddress-Port\bases\name_source\history\symbol_name

Por exemplo, o histórico para EURUSD proveniente do servidor MetaQuotes-Demo pode ser armazenada na pasta tester_catalog\Agent-127.0.0.1-3000\bases\MetaQuotes-Demo\EURUSD.

Um agente local, após a conclusão de um teste, entra em modo de espera, aguardando a próxima tarefa por mais 5 minutos, de modo a não perder tempo com o lançamento para a próxima chamada. Somente após o período de espera acabar, o agente local desliga e se descarrega da memória do CPU.

No caso de uma conclusão antecipada do testador, por parte do usuário (o botão "Cancelar"), bem como com o fechamento do terminal cliente, todos os agentes locais imediatamente param seu trabalhar e são descarregados da memória.

A Troca de Dados entre o Terminal e o Agente #

Ao rodar um teste, o terminal cliente prepara para enviar ao agente um número de blocos de parâmetros:

  • Parâmetros de input para o teste (modo de simulação, o intervalo do teste, instrumentos, critério de otimização, etc.)
  • A lista dos ativos selecionados na janela "Observação de Mercado"
  • A especificação do ativo do teste (o tamanho do contrato, as margens permitidas do mercado para definir um StopLoss e Takeprofit, etc)
  • O Expert Advisor (robot) para ser testado e os valores de seus parâmetros de entrada
  • Informações sobre arquivos adicionais (bibliotecas, indicadores, arquivos de dados - # property tester_ ...)

tester_indicator

string

Nome de um indicador customizado no formato de "indicator_name.ex5". Indicadores que requerem teste são definidos automaticamente a partir da chamada à função iCustom(), se o correspondente parâmetro estiver definido através de um string constante. Para todos os outros casos (use da função IndicatorCreate() ou uso de uma string não constante no parâmetro que defini o nome do indicador) esta propriedade é requerida

tester_file

string

Nome de arquivo para um testador com a indicação de extensão, entre aspas duplas (como uma string constante). O arquivo especificado será passado para o Testador de Estratégias. Arquivos de entrada para serem testados, se forem necessários, devem sempre ser especificados.

tester_library

string

Nome da biblioteca (library) com a extensão, entre aspas duplas. Uma biblioteca pode ter extensão dll ou ex5. Bibliotecas que requerem teste são definidas automaticamente. No entanto, se alguma das bibliotecas é usada por um indicador customizado, esta propriedade é requerida

Para cada bloco de parâmetros, uma impressão digital na forma de MD5-hash é criada, que é enviado para o agente. O MD5-hash é único para cada conjunto, seu volume é muito menor que a quantidade de informação na qual ele é calculado

O agente recebe um hash de blocos e os compara com aqueles que ele já tem. Se a impressão digital do bloco de parâmetros dado não está presente no agente, ou o hash recebido é diferente daquele existente, o agente solicita este bloco de parâmetros. Isso reduz o tráfego entre o terminal e o agente.

Após o teste, o agente retorna ao terminal todos os resultados da execução, que são exibidos nas guias "Resultados" e "Resultados da Otimização": o lucro recebido, o número de operações (deals), o coeficiente Sharpe, o resultdo da função OnTester(), etc.

Durante a otimização, o terminal distribui tarefas de teste para os agentes em pequenos pacotes, cada pacote contendo várias tarefas (cada tarefa significando testes individuais com um conjunto de parâmetros de entrada). Isso reduz o tempo de troca entre o terminal e o agente.

Os agentes nunca gravam no disco rígido o arquivo EX5, obtido do terminal (EA, indicadores, bibliotecas, etc.) for razões de segurança, de modo que um computador com um agente em execução não pode usar os dados enviados. Todos os outros arquivos, incluindo DLL, são gravados na caixa de areia. Em agentes remotos você não pode testar EAs usando DLL.

Os resultados do teste são adicionados pelo terminal em uma cache especial de resultados (o cache de resultado), para um acesso rápido a estes resultados quando necessário. Para cada conjunto de parâmetros, o terminal busca o cache de resultados por resultados já disponíveis a partir de execuções anteriores, a fim de evitar re-execuções. Se o resultado com tal conjunto de parâmetros não é encontrado, ao agente é dado a tarefa de conduzir o teste.

Todo tráfego entre o terminal e o agente é encripto-grafado.

Ticks não são enviados pela rede, eles são gerados nos agentes de teste.

Usando a Pasta Compartilhada para Todos os Terminais Cliente #

Todos os agentes de teste são isolados uns dos outros e do terminal cliente: cada agente tem sua própria pasta na qual seus logs são gravados. Além disso, todas as operações de arquivo durante o teste do agente ocorrem na pasta agent_name/MQL5/Files. Contudo, nós podemos implementar a interação entre os agentes locais e o terminal cliente através de uma pasta compartilhada para todos os terminais clientes, se durante a abertura do arquivo você especificar a flag FILE_COMMON:

//+------------------------------------------------------------------+
//| Função de inicialização do Expert                                |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- a pasta compartilhada para todos os terminais cliente
   common_folder=TerminalInfoString(TERMINAL_COMMONDATA_PATH);
//--- imprime o nome desta pasta
   PrintFormat("Abrir o arquivo na pasta compartilhada dos terminais de cliente %s", common_folder);
//--- abre um arquivo na pasta compartilhada (indicada pelo flag FILE_COMMON)
   handle=FileOpen(filename,FILE_WRITE|FILE_READ|FILE_COMMON);
  ... novas ações
//---
   return(INIT_SUCCEEDED);
  }

Usando DLLs #

Para acelerar a otimização nós podemos usar não somente agentes locais, mas também agentes remotos. Neste caso, existem algumas limitações para agentes remotos. Primeiramente, agentes remotos não exibem em seus logs os resultados da execução da função Print(), mensagens sobre a abertura e enceramento de posições. Um mínimo de informação é exibida no log para impedir que EAs escritos incorretamente de atolem o computador, no qual o agente remoto está trabalhando, com mensagens.

A segunda limitação - a proibição no uso de DLL ao testar EAs. Chamadas de DLL são absolutamente proibidas em agentes remotos por razões de segurança. Em agentes locais, chamadas de DLL em EAs testados são permitidas somente com a apropriada permissão "Allow import DLL".

A opção "Allow import DLL" em programas-MQL5

Observação: Ao usar os códigos recebidos dos EAs (scripts, indicadores) que requerem a permissão para fazer chamadas de DLL, você deve estar ciente dos riscos, que você assume ao permitir este opção nas configurações do terminal. Independentemente de como a EA será usada - para teste ou para execução em um gráfico.