Como desenvolver e testar uma estratégia para Opções Binárias com o Testador de Estratégia do MetaTrader 4

Martin Amiri | 17 janeiro, 2017


Índice

1. Introdução
2. Instalação
3. Exemplo de uma estratégia para Opções Binárias
3.1. Definição de uma estratégia para Opções Binárias
3.2. Criação de uma estratégia para Opções Binárias
3.2.1. Parâmetros de entrada
3.2.2. Inclusão da Binary-Options-Strategy-Library
3.2.3. Adicionar a CallStrategy()
3.2.4. Implementação da CheckMyRules() e da função auxiliar
3.2.5.Impressão dos valores de depuração
3.2.6. O uso de indicadores externos (arquivos ex4)
3.3. O código completo
4. Execução do backtest (vídeo)
5. Execução do forward test
6. FAQ
7. Diversos


1. Introdução

Este artigo mostra como desenvolver uma estratégia para Opções Binárias e testa-la no Testador de Estratégia do MetaTrader 4 com a biblioteca Binary-Options-Strategy-Tester. Por padrão o Testador de Estratégia do MetaTrader 4 pode realizar backtests de Expert Advisors e Indicadores com os dados históricos, mas não pode lidar com Opções Binárias que expiram por horário. Como eu preciso de uma possibilidade para testar as estratégias automatizadas para Opções Binárias no Testador de Estratégia do MetaTrader 4, o Binary-Options-Strategy-Tester foi construído como um utilitário para atender a essas necessidades.

O conceito inclui os seguintes componentes:

Conceito do Binary Options Strategy Tester

Este é um exemplo passo a passo de como desenvolver uma estratégia para Opções Binárias armazenado em um indicador (marcado em vermelho na imagem acima) para se comunicar através do Binary-Options-Strategy-Library (marcado em verde na imagem acima) com o Binary-Options-Strategy-Tester (marcado em azul na imagem acima), para colocar as ordens virtuais e mostrar seus resultados com os backtests e forward tests.

Por favor tenha em mente: A realização dos Backtests com os dados históricos nunca representará o futuro de forma real, mas pode lhe fornecer um valor aproximado para a obtenção de uma estratégia mais estável.
A qualidade do seu backtest irá depender de seus dados históricos. Por isso é altamente recomendado o uso de um conjunto de dados de altíssima qualidade!


2. Instalação

Baixe e compre o utilitário Binary-Options-Strategy-Tester do Mercado:
Framework de Testes para testar as estratégias de Opções Binárias no Testador de Estratégia do MetaTrader 4.

Por que é necessário uma versão comprada do utilitário Binary-Options-Strategy-Tester?
A estratégia para Opções Binárias deve chamar uma função da Binary-Options-Strategy-Tester (através da Binary-Options-Strategy-Library) para colocar os negócios virtuais. Relacionado ao conceito de licença do MQL4, isso irá funcionar somente se o produto possui uma licença válida. Portanto, você precisa comprar o produto para testar as estratégias para Opções Binárias deste exemplo.

Baixe grátis a biblioteca BinaryOptionsStrategyLibrary.mqh e coloque dentro da pasta \Include ([caminho do seu MetaTrader 4]\MQL4\Include):
A biblioteca grátis irá fornecer várias funções para desenvolver com facilidade sua estratégia para Opções Binárias e se comunicar com o Binary-Options-Strategy-Tester. Veja Binary-Options-Strategy-Library para mais detalhes sobre a biblioteca.

Baixe grátis o indicador KVO.mq4 e coloque-o (e o arquivo compilado KVO.ex4) na pasta \Indicators\Downloads ([caminho do seu MetaTrader 4]\MQL4\Indicators\Downloads):
O indicador KVO é usado como um exemplo para mostrar o acesso aos indicadores externos e seus arquivos em ex4 na seção "3.2.6 Uso de indicadores externos (arquivos ex4)". Veja https://www.mql5.com/pt/code/8677 para mais detalhes do indicador.

Agora você pode ir mais longe com a seção "3. Exemplo de uma estratégia para Opções Binárias" e desenvolver o código de exemplo sozinho ou apenas baixa-lo abaixo.

Baixe o arquivo (opcional) BinaryOptionsStrategyExample.mq4 e coloque-o (e o arquivo compilado BinaryOptionsStrategyExample.ex4) na pasta \Indicators ([caminho do seu MetaTrader 4]\MQL4\Indicators):
Baixe o código de exemplo desta estratégia para Opções Binárias para roda-lo sem construí-lo sozinho.

Para compilar os arquivos necessários em .ex4, abra os arquivos em .mq4 (KVO.mq4 e BinaryOptionsStrategyExample.mq4 - NÃO o Binary-Options-Strategy-Library.mqh) no MetaEditor e clique no botão "Compilar" ou simplesmente reinicie o seu MetaTrader 4, após isso, esses arquivos estarão armazenados nas pastas descritas e o MetaTrader 4 fará isso automaticamente para você.


3. Exemplo de uma estratégia para Opções Binárias

Os passos seguintes irão guiá-lo para um exemplo de como desenvolver uma estratégia para Opções Binárias, armazenada em um indicador que se comunicará com a Binary-Options-Strategy-Tester. Você pode construí-lo sozinho ou apenas baixar o código do BinaryOptionsStrategyExample.mq4.

Observação: Esta estratégia não é uma estratégia lucrativa para Opções Binárias! Ela é apenas um exemplo de como desenvolver uma estratégia dentro de um indicador para se comunicar com o utilitário Binary-Options-Strategy-Tester. Claro que você deve criar uma estratégia rentável por si próprio. Você verá que este utilitário irá ajudá-lo a testar e melhorar sua estratégia para Opções Binárias.


3.1 Definição de uma estratégia para Opções Binárias

Primeiramente, nós temos de definir a estratégia e seus valores que podem ser alterados (parâmetros de entrada). A documentação MQL4 mostra todos os indicadores técnicos, que podem ser tratados pela interface iCustom: https://docs.mql4.com/indicators.

Suponha que eu gostaria de criar uma estratégia de cruzamento de Média Móvel simples com uma MA "rápida" e outra "lenta" para negociar na próxima vela após o cruzamento delas. A documentação diz, como nós podemos obter o valor de uma única Média Móvel: https://docs.mql4.com/indicators/ima.

Complementando, nós gostamos de escolher os valores para o "período médio de MA" (rápido e lento) e para o "preço aplicado", bem como para o "método da média". Outros valores (como símbolo, período e deslocamento) dependem do caso de teste (por exemplo, o símbolo que está rodando no testador) e devem ser definidos automaticamente. Por isso, nós precisamos basicamente das seguintes variáveis ​​para a Média Móvel:

int ma_period
int ma_method
int applied_price

Como nós precisamos de duas Médias Móveis para verificar os seus cruzamentos, nós precisamos dos seguintes parâmetros de entrada com alguns valores padrão para a estratégia de exemplo:

int period_fast        =  5;
int period_slow        = 10;
int method_both        =  0; 
int applied_price_both =  0; 


3.2 Criação de uma estratégia para Opções Binárias

Você precisa criar um indicador que armazena a sua estratégia para Opções Binárias para arrastá-lo no gráfico onde o Binary-Options-Strategy-Tester está sendo executado.

Abra o MetaEditor (no MetaTrader 4 clique em "Ferramentas" -> "Editor da Linguagem MetaQuotes" ou simplesmente pressione F4) e clique em "Novo":

"Novo" no MetaEditor

O Assistente MQL irá aparecer. Selecione o "Indicador personalizado" para criar um indicador vazio e clique em "Avançar":

Indicador Personalizado do Editor de Linguagem

Digite o nome, direitos autorais e o link da estratégia, bem como os parâmetros de entrada com seus tipos e valores padrão (valores iniciais), clicando no botão "Adicionar" e pressione "Avançar":

Valores do Indicador Personalizado do Editor de Linguagem

Na guia dos manipuladores de eventos, selecione a caixa de seleção "OnCalculate" já que nós precisamos deste evento para verificar a nossa estratégia a cada tick. Pressione "Avançar":

Eventos do Indicador Personalizado do Editor de Linguagem

Na guia das propriedades de desenho, selecione a caixa de seleção "Indicador em janela separada", já que nós precisamos de uma janela separada para imprimir os valores de depuração. Pressione "Concluir":

Propriedades de Desenho do Indicador Personalizado do Editor de Linguagem

O código inicial de seu indicador será parecido como este:

//+------------------------------------------------------------------+
//|                              BinaryOptionsStrategyExample.mq4 |
//|                                           Copyright 2016, __martin__ |
//|                  https://www.mql5.com/en/users/__martin__ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, __martin__"
#property link      "https://www.mql5.com/en/users/__martin__"
#property version   "1.00"
#property strict
#property indicator_separate_window
//--- Parâmetros de entrada
input int      period_fast=5;
input int      period_slow=10;
input int      method_both=0;
input int      applied_price_both=0;
//+------------------------------------------------------------------+
//| Função de inicialização do indicador personalizado       |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- mapeamento dos buffers do indicador
  
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Função de inicialização do indicador personalizado       |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
  
//--- retorna o valor de prev_calculated para a próxima chamada
   return(rates_total);
  }
//+------------------------------------------------------------------+


3.2.1 Os parâmetros de entrada

Os parâmetros de entrada iniciais são criados com o Assistente MQL (ver 3.2 Criação de uma estratégia para Opções Binárias) e nós vamos melhorá-los com os seguintes passos.

Para evitar ter que digitar os valores de int para ao preço aplicado e o método da média das Médias Móveis nos parâmetros de entrada, o tipo de method_both e applied_price_both é alterado de int para uma enumeração com um valor padrão.

ENUM_MA_METHOD: https://docs.mql4.com/constants/indicatorconstants/enum_ma_method
ENUM_APPLIED_PRICE: https://docs.mql4.com/constants/indicatorconstants/prices#enum_applied_price_enum

Além disso, são adicionados comentários aos parâmetros de entrada para mostrar os comentários como rótulos em vez de nomes de variáveis:

...

//--- parâmetros de entrada
input int                period_fast        =  5;           //Valor de MA rápido
input int                period_slow        = 10;           //Valor de MA lento
input ENUM_MA_METHOD     method_both        = MODE_SMA;     //Método da MA
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  //Preço aplicado a MA

...

Com estas alterações nos parâmetros de entrada, nos é fornecido uma lista suspensa com os valores disponíveis para selecionar, bem como os "rótulos" para os parâmetros de entrada:

Parâmetros de Entrada da Estratégia para Opções Binárias


3.2.2 Inclusão da Binary-Options-Strategy-Library

Se você tiver baixado e armazenado a biblioteca (ver 2. Instalação) dentro da pasta \Include ([caminho do seu MetaTrader 4]\MQL4\Include), você será capaz de incluir a biblioteca como esta:

//+------------------------------------------------------------------+
//|                              BinaryOptionsStrategyExample.mq4 |
//|                                           Copyright 2016, __martin__ |
//|                  https://www.mql5.com/en/users/__martin__ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, __martin__"
#property link      "https://www.mql5.com/en/users/__martin__"
#property version   "1.00"
#property strict
#property indicator_separate_window

#include <BinaryOptionsStrategyLibrary.mqh>

//--- parâmetros de entrada

...
A biblioteca estará disponível apenas como está descrito no exemplo acima, se você colocá-la na pasta \Include de seu MetaTrader 4.
Não é necessário alterar o conteúdo da biblioteca!

A Binary-Options-Strategy-Library irá melhorar os parâmetros de entrada com mais dois novos parâmetros:

  • Coloque apenas uma ordem de VENDA ou COMPRA por vela
  • Verifique a estratégia apenas no início de uma nova vela

Melhoramento dos Parâmetros de Entrada da Estratégia para Opções Binárias


3.2.3 Adicionar a CallStrategy()

Adicione uma chamada para a função CallStrategy() no OnCalculate() ao seu indicador de estratégia para chamar a estratégia a cada novo tick. CallStrategy() é fornecido pela Binary-Options-Strategy-Library que você incluiu como descrito acima:

...

//+------------------------------------------------------------------+
//| Função de iteração do indicador personalizado              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---

   CallStrategy(); //Chama a estratégia, a função está localizada em BinaryOptionsStrategyLibrary.mqh (incluído acima)

//--- retorna o valor de prev_calculated para a próxima chamada
 
   return
(rates_total);
  }
//+------------------------------------------------------------------+

A função CallStrategy() em Binary-Options-Strategy-Library irá chamar uma função chamada CheckMyRules() em seu indicador, onde você pode colocar suas regras para a estratégia para Opções Binárias.
Portanto, você tem que implementar a função CheckMyRules() no seu indicador da estratégia para Opções Binárias.


3.2.4 Implementação da CheckMyRules() e da função auxiliar

Na função CheckMyRules(), que é chamada através da Binary-Options-Strategy-Library, as condições para a estratégia são implementadas e as ordens são colocadas através da função PlaceTrade() que se encontra na biblioteca. Os valores de ambas as Médias Móveis são temporariamente armazenadas nas variáveis ​​para compará-los dentro das condição "se" (if), enquanto que os valores das Médias Móveis são retirados da-função auxiliar GetValuesForMA():


...

//--- parâmetros de entrada
input int                period_fast        =  5;           //Valor da MA rápida
input int                period_slow        = 10;           //Valor da MA lenta
input ENUM_MA_METHOD     method_both        = MODE_SMA;     //Método da MA
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  //Preço aplicado da MA

...

//+------------------------------------------------------------------+
//| Coloque as regras de negociação aqui - veja o exemplo abaixo. |
//| O StrategyTester irá chamar esta função para colocar as negociações. |
//| NÃO FAÇA:                                                                    |
//| - Renomeie a função                                                        |
//| - Adicione os parâmetros da função, por exemplo, CheckMyRules(int a) |
//| - Altere o tipo da função de retorno, por exemplo int CheckMyRules() |
//+------------------------------------------------------------------+
void CheckMyRules()
  {
  
   //Armazena os valores da MA com deslocamento = 0 (vela atual) -> vela atual,
//Chama a função auxiliar GetValueForMA() para obter o valor - ver as funções auxiliares abaixo
   double emaSlow_Current = GetValueForMA(period_slow, 0);
   double emaFast_Current = GetValueForMA(period_fast, 0);

   Armazena os valores de MA com deslocamento = 1 (vela passada) -> última vela,
// Chama a função auxiliar GetValueForMA() para obter o valor - ver as funções auxiliares abaixo
   double emaSlow_Past = GetValueForMA(period_slow, 1);
   double emaFast_Past = GetValueForMA(period_fast, 1);

   if(emaFast_Past > emaSlow_Past
   && emaFast_Current < emaSlow_Past) //Verifica se a MA lenta e a MA rápida se cruzam
     {
      PlaceTrade(OP_SELL); //Coloca uma ordem de VENDA no Testador de Estratégia, a função está localizada na BinaryOptionsStrategyFunctions.mqh
     }
  
   if(emaFast_Past < emaSlow_Past
   && emaFast_Current > emaSlow_Past) //Verifiqua se a MA lenta cruza a MA rápida
     {
      PlaceTrade(OP_BUY); //Coloca uma ordem de COMPRA no Testador de Estratégia, a função está localizada em BinaryOptionsStrategyFunctions.mqh
     }
  
  }

//+------------------------------------------------------------------+
//| Coloque suas funções auxiliares aqui, veja o exemplo abaixo |
//+------------------------------------------------------------------+
//----
//+------------------------------------------------------------------+
//| Obtenha os valores de MA para o período, método, preço aplicado e deslocamento. |
//| Para mais detalhes de iMA() veja https://docs.mql4.com/indicators/ima |
//+------------------------------------------------------------------+
double GetValueForMA(int _period,int _shift)
  {
   return iMA(NULL,0,_period,0,method_both,applied_price_both,_shift);
  }
 


3.2.5 Impressão dos valores de depuração

A função PrintDebugValue() fornece a possibilidade de imprimir os valores de depuração, enquanto o testador estiver em execução. No exemplo abaixo, os valores das Médias Móveis são impressos com o nome de sua variável ​​como rótulos:


...

//--- parâmetros de entrada
input int                period_fast        =  5;           //Valor da MA rápida
input int                period_slow        = 10;           //Valor da MA lenta
input ENUM_MA_METHOD     method_both        = MODE_SMA;     //Método da MA
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  //Preço aplicado da MA

...

//+------------------------------------------------------------------+
//| Coloque as regras de negociação aqui - veja o exemplo abaixo. |
//| O StrategyTester irá chamar esta função para colocar as negociações. |
//| NÃO FAÇA:                                                                    |
//| - Renomeie a função                                                        |
//| - Adicione os parâmetros da função, por exemplo, CheckMyRules(int a) |
//| - Altere o tipo da função de retorno, por exemplo int CheckMyRules() |
//+------------------------------------------------------------------+
void CheckMyRules()
  {
  
   //Armazena os valores de MA com shift=0 (vela atual) -> vela atual,
   //chama a função auxiliar GetValueForMA() para obter os valores - veja as funções auxiliares abaixo
   double emaSlow_Current = GetValueForMA(period_slow, 0);
   double emaFast_Current = GetValueForMA(period_fast, 0);

   //Armazena os valores de MA com shift=1 (vela passada) -> última vela,
   //chama a função auxiliar GetValueForMA() para obter o valor - veja as funções auxiliares abaixo
   double emaSlow_Past = GetValueForMA(period_slow, 1);
   double emaFast_Past = GetValueForMA(period_fast, 1);

   PrintDebugValue("emaSlow_Current: ",(string)emaSlow_Current,0); //Valor e rótulo na linha 0
   PrintDebugValue("emaFast_Current: ",(string)emaFast_Current,1); //Valor e rótulo na linha 1
   PrintDebugValue("emaSlow_Past: ",(string)emaSlow_Past,2);       //Valor e rótulo na linha 2
   PrintDebugValue("emaFast_Past: ",(string)emaFast_Past,3);       //Valor e rótulo na linha 3

   if(emaFast_Past > emaSlow_Past
   && emaFast_Current < emaSlow_Past) //Verifica se a MA lenta cruzou a MA rápida
     {
      PlaceTrade(OP_SELL); //Coloca uma ordem de VENDA no Testador de Estratégia, a função está localizada na BinaryOptionsStrategyFunctions.mqh
     }
  
   if(emaFast_Past < emaSlow_Past
   && emaFast_Current > emaSlow_Past) //Verifica se a MA lenta cruzou a MA rápida
     {
      PlaceTrade(OP_BUY); //Coloca uma ordem de COMPRA no Testador de Estratégia, a função está localizada em BinaryOptionsStrategyFunctions.mqh
     }
  
  }

//+------------------------------------------------------------------+
//| Coloque as suas funções auxiliares aqui, veja o exemplo abaixo |
//+------------------------------------------------------------------+
//----

//+------------------------------------------------------------------+
//| Obtenha os valores de MA para o período, método, preço aplicado e deslocamento. |
//| Para mais detalhes de iMA() veja https://docs.mql4.com/indicators/ima |
//+------------------------------------------------------------------+
double GetValueForMA(int _period,int _shift)
  {
   return iMA(NULL,0,_period,0,method_both,applied_price_both,_shift);
  }
 


3.2.6 O uso de indicadores externos (arquivos ex4)

Além disso, a estratégia para Opções Binárias pode acessar um indicador externo que armazena seus valores em buffers, mesmo que este seja apenas uma arquivo EX4 -compilado.

Suponha que nós gostaríamos de incluir a linha de sinal do indicador KVO https://www.mql5.com/pt/code/8677 para colocar ordens somente se a linha de sinal for maior que 0 para uma COMPRA e abaixo de 0 VENDA. Baixe o indicador  KVO.mq4 e coloque-o compilado (arquivo ex4) na pasta \Indicators\Downloads ([caminho do seu MetaTrader 4]\MQL4\Indicators\Downloads).

Para compilar o arquivo .ex4 que nós precisamos, abra o arquivo KVO.mq4 no MetaEditor e clique no botão "Compilar" ou simplesmente reinicie o MetaTrader 4 após o arquivo ser armazenado na pasta descrita e o MetaTrader 4 fará isso automaticamente para você.

Primeiro, nós temos que identificar os buffers relevantes que armazenam os correspondentes valores para o acesso. Para isso, pressione o botão "Janela de dados" no MetaTrader 4 para mostrar todos os buffers disponíveis dos indicadores utilizados e arraste o indicador KVO para um gráfico. Ao passar a cruz (crosshair) sobre o gráfico (pressione o botão de rolagem do mouse no gráfico para abri-la), será exibido na janela de dados os valores dos buffers do indicador correspondente ao horário e período que ela estiver:

Buffers de Indicadores Externos e seus Valores

Os rótulos da janela de dados nos diz que o segundo valor do buffer do indicador armazena a linha de sinal. Se os buffers dos indicadores não tiverem rótulos, nós podemos encontrar o caminho certo comparando os valores do buffer com o valor apresentado sob a cruz no gráfico e no indicador. Os Buffers de um indicador começam com 0, por isso nós temos o valor do buffer 1 = buffer 0, o valor do buffer 2 = buffer 1 e assim por diante, sendo que nós temos que acessar o buffer 1 para obter o valor do sinal.

Em seguida, nós temos que saber todos os parâmetros de entrada do indicador externo que nós gostaríamos de acessar. Ao arrastar o indicador em um gráfico, nós vemos todos os parâmetros de entrada:

Parâmetros de entrada do KVO

Suponha que nós gostaríamos de acessar o indicador com os valores (padrão): 34, 55 e 13. Nós usamos uma função auxiliar (com base na iCustom), que nos fornece a possibilidade de obter os valores do indicador com os parâmetros para o buffer e o deslocamento (shift), enquanto que o deslocamento 0 será o valor da vela atual, o deslocamento 1 o valor da última vela, o deslocamento 2 o valor da segunda para a última vela e assim por diante. Além disso, nós armazenamos temporariamente os valores do buffer do indicador e melhoramos a condição "se" da estratégia:


...

//--- parâmetros de entrada
input int                period_fast        =  5;           //Valor da MA rápida
input int                period_slow        = 10;           //Valor da MA lenta
input ENUM_MA_METHOD     method_both        = MODE_SMA;     //Método da MA
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  //Preço aplicado da MA

...

//+------------------------------------------------------------------+
//| Coloque as regras de negociação aqui - veja o exemplo abaixo. |
//| O StrategyTester irá chamar esta função para colocar as negociações. |
//| NÃO FAÇA:                                                                    |
//| - Renomeie a função                                                        |
//| - Adicione os parâmetros da função, por exemplo, CheckMyRules(int a) |
//| - Altere o tipo da função de retorno, por exemplo int CheckMyRules() |
//+------------------------------------------------------------------+
void CheckMyRules()
  {
  
   //Armazena os valores de MA com shift=0 (vela atual) -> vela atual,
   //chama a função auxiliar GetValueForMA() para obter os valores - veja as funções auxiliares abaixo
   double emaSlow_Current = GetValueForMA(period_slow, 0);
   double emaFast_Current = GetValueForMA(period_fast, 0);

   //Armazena os valores de MA com shift=1 (vela passada) -> última vela,
   //chama a função auxiliar GetValueForMA() para obter o valor - veja as funções auxiliares abaixo
   double emaSlow_Past = GetValueForMA(period_slow, 1);
   double emaFast_Past = GetValueForMA(period_fast, 1);

   //Armazena o valor do sinal (buffer 1) do indicador KVO da vela atual (shift 0)
   double kvoSignal = GetValuesFromIndicator__KVO__(1,0);

   PrintDebugValue("emaSlow_Current: ",(string)emaSlow_Current,0); //Rótulo e valor da linha 0
   PrintDebugValue("emaFast_Current: ",(string)emaFast_Current,1); //Rótulo e valor da linha 0 1
   PrintDebugValue("emaSlow_Past: ",(string)emaSlow_Past,2);       //Rótulo e valor da linha 2
   PrintDebugValue("emaFast_Past: ",(string)emaFast_Past,3);       //Rótulo e valor da linha 3

   if(emaFast_Past > emaSlow_Past
   && emaFast_Current < emaSlow_Past //Verifica se a MA lenta cruzou a MA rápida
   && kvoSignal < 0) //Verifica se o valor do sinal de KVO está abaixo de 0
     {
      PlaceTrade(OP_SELL); //Coloca uma ordem de VENDA no Testador de Estratégia, a função está localizada na BinaryOptionsStrategyFunctions.mqh
     }
  
   if(emaFast_Past < emaSlow_Past
   && emaFast_Current > emaSlow_Past //Verifica se a MA lenta cruzou a MA rápida
   && kvoSignal > 0) //Verifica se o valor do sinal de KVO está acima de 0
     {
      PlaceTrade(OP_BUY); //Coloca uma ordem de COMPRA no Testador de Estratégia, a função está localizada em BinaryOptionsStrategyFunctions.mqh
     }
  
  }

//+------------------------------------------------------------------+
//| Coloque sua função auxiliar aqui, veja o exemplo abaixo |
//+------------------------------------------------------------------+
//----

//+------------------------------------------------------------------+
//| Obtém os valores de MA para o período, método, preço aplicado e deslocamento. |
//| Para mais detalhes de iMA() veja https://docs.mql4.com/indicators/ima |
//+------------------------------------------------------------------+
double GetValueForMA(int _period,int _shift)
  {
   return iMA(NULL,0,_period,0,method_both,applied_price_both,_shift);
  }

//+------------------------------------------------------------------+
//| Exemplo de como obter os valores dos indicadores externos |
//| veja https://docs.mql4.com/indicators/icustom               |
//| Parâmetros:                                                                      |
//| int _buffer - indicator-buffer (começa em 0)                   |
//| int _shift - valor do shift; 0 = vela atual, 1 = vela anterior |
//+------------------------------------------------------------------+
double GetValuesFromIndicator__KVO__(int _buffer, int _shift=0) //Altera o "__KVO__" para o nome do indicador
  {

   return (
            iCustom (
                      NULL,                      //NULL para o período de tempo atual selecionado no testador - NENHUMA ALTERAÇÃO É NECESSÁRIA
                      0,                         //0 para o símbolo atual selecionado no testador - NENHUMA ALTERAÇÃO É NECESSÁRIA

                      //INÍCIO DA EDIÇÃO
                      "\\Downloads\\KVO.ex4",    //Caminho e nome do arquivo do indicador (*.ex4 file)
                      //INÍCIO DAS ENTRADAS DO INDICADOR
                      34,
                      55,
                      13,
                      //FIM DAS ENTRADAS
                      //FIM DA EDIÇÃO

                      _buffer,                   //Índice do buffer (começa em 0), _buffer é endereçado acima do parâmetro da função - NENHUMA ALTERAÇÃO É NECESSÁRIA
                      _shift                     //Deslocamento (0 para a vela atual), _shift é endereçado acima do parâmetro da função - NENHUMA ALTERAÇÃO É NECESSÁRIA
                    )
          );

  }
 

Também é possível melhorar os parâmetros de entrada do nosso indicador, que contém a estratégia, com os valores do indicador KVO utilizado e definir os valores através das variáveis na função auxiliar. Como este tutorial deve ser apenas de exemplo e "o mais simples possível", esta variante não é exibida.


3.3 O código completo

Abaixo, você encontrará o código completo do Binary-Options-Strategy-Example de todos os passos acima, pronto para ser arrastado no Binary-Options-Strategy-Tester para testar e ver os resultados no gráfico:

//+------------------------------------------------------------------+
//|                              BinaryOptionsStrategyExample.mq4 |
//|                                           Copyright 2016, __martin__ |
//|                  https://www.mql5.com/en/users/__martin__ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, __martin__"
#property link      "https://www.mql5.com/en/users/__martin__"
#property version   "1.00"
#property strict
#property indicator_separate_window

#include <BinaryOptionsStrategyLibrary.mqh>

//+------------------------------------------------------------------+
//| Coloque as regras de negociação aqui - veja o exemplo abaixo. |
//+------------------------------------------------------------------+
//--- Parâmetros de entrada
input int                period_fast        =  5;           //Valor da MA rápida
input int                period_slow        = 10;           //Valor da MA lenta
input ENUM_MA_METHOD     method_both        = MODE_SMA;     //Método da MA
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  //Preço aplicado da MA

//+------------------------------------------------------------------+
//| Função de inicialização do indicador personalizado       |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- mapeamento do buffers do indicador

//---
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Função de inicialização do indicador personalizado       |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---

   CallStrategy(); //Chama a estratégia, a função está localizada em BinaryOptionsStrategyLibrary.mqh (incluído acima)

//--- retorna o valor de prev_calculated para a próxima chamada
   return(rates_total);
  }

//+------------------------------------------------------------------+
//| Coloque as regras de negociação aqui - veja o exemplo abaixo. |
//| O StrategyTester irá chamar esta função para colocar as negociações. |
//|NÃO FAÇA:                                                                     |
//| - Renomeie a função                                                        |
//| - Adicione os parâmetros da função, por exemplo, CheckMyRules(int a) |
//| - Altere o tipo da função de retorno, por exemplo int CheckMyRules() |
//+------------------------------------------------------------------+
void CheckMyRules()
  {
  
   //Armazena os valores de MA com shift=0 (vela atual) -> vela atual,
   //Chama a função auxiliar GetValueForMA() para obter o valor - veja as funções auxiliares abaixo
   double emaSlow_Current = GetValueForMA(period_slow, 0);
   double emaFast_Current = GetValueForMA(period_fast, 0);

   //Armazena os valores de MA com deslocamento = 1 (vela passada) -> última vela,
   //Chama a função auxiliar GetValueForMA() para obter o valor - veja as funções auxiliares abaixo
   double emaSlow_Past = GetValueForMA(period_slow, 1);
   double emaFast_Past = GetValueForMA(period_fast, 1);
  
   //Armazena o valor do sinal (buffer 1) do indicador KVO da vela atual (shift 0)
   double kvoSignal = GetValuesFromIndicator__KVO__(1,0);
  
   PrintDebugValue("emaSlow_Current: ",(string)emaSlow_Current,0); //Rótulo e valor da linha 0
   PrintDebugValue("emaFast_Current: ",(string)emaFast_Current,1); //Rótulo e valor da linha 1
   PrintDebugValue("emaSlow_Past: ",(string)emaSlow_Past,2);       //Rótulo e valor da linha 2
   PrintDebugValue("emaFast_Past: ",(string)emaFast_Past,3);       //Rótulo e valor da linha 3

   if(emaFast_Past > emaSlow_Past
   && emaFast_Current < emaSlow_Past    //Verifica se a MA lenta cruzou a MA rápida
   && kvoSignal < 0)                    //Verifica se o valor do sinal de KVO está abaixo de 0  
     {
      PlaceTrade(OP_SELL);              //Coloca uma ordem de VENDA no Testador de Estratégia, a função está localizada na BinaryOptionsStrategyFunctions.mqh
     }
  
   if(emaFast_Past < emaSlow_Past
   && emaFast_Current > emaSlow_Past    //Verifica se a MA lenta cruzou a MA rápida
   && kvoSignal > 0)                    //Verifica se o valor do sinal de KVO está acima de 0
     {
      PlaceTrade(OP_BUY);               //Coloca uma ordem de COMPRA no Testador de Estratégia, a função está localizada em BinaryOptionsStrategyFunctions.mqh
     }
  
  }

//+------------------------------------------------------------------+
//| Coloque suas funções auxiliares aqui, veja o exemplo abaixo |
//+------------------------------------------------------------------+
//----

//+------------------------------------------------------------------+
//| Obtém os valores de MA para o período, método, preço aplicado e deslocamento. |
//| Para mais detalhes de iMA() veja https://docs.mql4.com/indicators/ima |
//+------------------------------------------------------------------+
double GetValueForMA(int _period,int _shift)
  {
   return iMA(NULL,0,_period,0,method_both,applied_price_both,_shift);
  }

//+------------------------------------------------------------------+
//| Exemplo de como obter os valores dos indicadores externos,|
//| veja https://docs.mql4.com/indicators/icustom               |
//| Parâmetros:                                                                      |
//| int _buffer - indicator-buffer (começa em 0)                   |
//| int _shift - valor do shift; 0 = vela atual, 1 = vela anterior |
//+------------------------------------------------------------------+
double GetValuesFromIndicator__KVO__(int _buffer, int _shift=0) //Altera o "__KVO__" para o nome do indicador
  {
   return (
            iCustom (
                      NULL,                      //NULL para o período de tempo atual selecionado no testador - NENHUMA ALTERAÇÃO É NECESSÁRIA
                      0,                         //0 para o símbolo atual selecionado no testador - NENHUMA ALTERAÇÃO É NECESSÁRIA
                  
                      //INÍCIO DA EDIÇÃO
                      "\\Downloads\\KVO.ex4",    //Caminho e nome do arquivo do indicador (*.ex4 file)                  
                      //INÍCIO DAS ENTRADAS DO INDICADOR
                      34,
                      55,
                      13,
                      //FIM DAS ENTRADAS
                      //FIM DA EDIÇÃO
                  
                      _buffer,                   //Índice do buffer (começa em 0), _buffer é endereçado acima do parâmetro da função - NENHUMA ALTERAÇÃO É NECESSÁRIA
                      _shift                     //Deslocamento (0 para a vela atual), _shift é endereçado acima do parâmetro da função - NENHUMA ALTERAÇÃO É NECESSÁRIA
                    )
          );
  }
//+-----------------------------------------------------------------+


4. Execução do backtest (vídeo)

O vídeo a seguir mostra como executar um backtest de sua estratégia para Opções Binárias no Testador de Estratégia do MetaTrader 4:

  • Inicie o Binary-Options-Strategy-Tester no Testador de Estratégia do MetaTrader 4 e defina os parâmetros de entrada
  • Arraste o indicador de estratégia para as Opções Binárias no gráfico, defina os parâmetros de entrada e marque "Permitir importar de experts externos" na aba "Comum"
  • Arraste os indicadores utilizados com os seus parâmetros de entrada no gráfico para ver seus valores enquanto o testador está em execução (opcional)
  • Salve todas as configurações em um template (modelo) para executar o teste com todas as configurações novamente - usando o botão de pausa do Testador de Estratégia(opcional)
  • Veja os resultados de sua estratégia para Opções Binárias no gráfico do Testador de Estratégia 


5. Execução do forward test

Para realizar um forward test, arraste o utilitário Binary-Options-Strategy-Tester e o seu indicador de estratégia sobre o gráfico de sua conta demo ou real, em vez de usá-lo Testador de Estratégia:

  • Arraste o utilitário Binary-Options-Strategy-Tester no gráfico de sua conta demo ou real e defina os parâmetros de entrada
  • Arraste o indicador de estratégia para as Opções Binárias no gráfico, defina os parâmetros de entrada e marque "Permitir importar de experts externos" na aba "Comum"
  • Arraste os indicadores utilizados com os seus parâmetros de entrada no gráfico para ver seus valores enquanto o forward test está em execução (opcional)
  • Salve todas as configurações em um template (modelo) para executar o teste novamente com todas as configurações (opcional)
  • Veja os resultados de sua estratégia para Opções Binárias no gráfico de sua conta demo ou real


6. FAQ

Pergunta: Por que você mostrou um exemplo de uma estratégia não lucrativa para Opções Binárias?
Resposta: Este é apenas um exemplo de como desenvolver uma estratégia em um indicador para se comunicar com o utilitário Binary-Options-Strategy-Tester no mercado para testar e melhorar a sua estratégia.

Pergunta: Binary-Options-Strategy-Tester encerra com erro após uma quantidade exata de perdas "Array out of range". Por quê?
Resposta: Binary-Options-Strategy-Tester pode apresentar um erro após x perdas para parar o Testador e analisar a situação no gráfico. Se você não quiser, basta desligar a opção nas configurações.

Pergunta: As setas não aparecem no gráfico depois que eu arrastei o meu indicador com uma estratégia sobre ele. O que aconteceu?
Answere: Você tem que habilitar "Permitir importar de experts externos" na aba "Comum" enquanto você arrasta seu indicador com a estratégia no gráfico (aparecerá um erro na mensagem de log, neste caso).

Pergunta: As setas não aparecem no gráfico depois que eu arrastei o meu indicador com uma estratégia sobre ele com "Permitir importar de experts externos" habilitado. Por quê?
Answere: A estratégia tem de chamar uma função da Binary-Options-Strategy-Tester para colocar as ordens virtuais. Relacionada com o conceito de licença MQL4, isso só irá funcionar se o produto tiver uma licença válida. Portanto, você tem que adquirir o produto.

Pergunta: As setas não aparecem no gráfico depois que eu arrastei o meu indicador com uma estratégia sobre ele e eu obtenho erros como "Cannot call..." ou "Cannot load..." no log do MetaTrader 4. O que eu posso fazer?
Resposta: Use a versão mais recente (maior que v1.00) da BinaryOptionsStrategyLibrary.mqh. Verifique a tag da versão no código de sua BinaryOptionsStrategyLibrary.mqh e veja changelog v1.01 da BinaryOptionsStrategyLibrary.

Pergunta: Eu não vejo nenhum resultado nas guias do Testador de Estratégia "Resultados", "Gráfico", "Relatório". Onde eu posso ver os resultados?
Resposta: O Testador de Estratégias do MetaTrader 4 não tem suporte para Opções Binárias, assim, essas guias não são usadas. Portanto, este utilitário calcula todos ganhos e perdas, imprimindo os resultados no gráfico.


7. Diversos

Este utilitário foi criado devido a minha necessidade de testar estratégias para Opções Binárias automatizadas no Testador de Estratégia do MetaTrader 4 para longos períodos de tempo em um curto espaço de tempo e para fazer forward test no gráfico da corretora. Eu gastei muito tempo para a definição e implementação do conceito do Binary-Options-Strategy-Tester, bem como na sua documentação. Talvez haja uma maneira melhor de fazer isso e talvez algumas melhorias irão aproximá-lo à suas necessidades. Por favor, sinta-se livre em entrar em contato para ideias de melhoria!