Gap - estratégia rentável ou 50/50?

Vladimir Karputov | 27 dezembro, 2018

Introdução

Esse artigo, além de mostrar como verificar gaps no timeframe D1 no mercado de ações, vai tentar esclarecer certas questões, como com que frequência o mercado continua se movendo na direção de um gap ou o quão factível é uma reversão do mercado após um gap. Aqui, para visualização de resultados, serão usados gráficos personalizados CGraphic. Além disso, a seleção de arquivos com símbolos será realizada usando a função DLL GetOpenFileName do sistema.


Qual mercado escolher?

Fica desde já dito que o gap me interessa exclusivamente no timeframe D1.

É óbvio que o maior número de gaps não está nos símbolos do Forex, mas, sim, nos mercado de ações, uma vez que os valores mobiliários são negociados de manhã à noite e não as 24 horas do dia. Estou especificamente interessado em ações, pois elas possuem um histórico relativamente profundo. Por outro lado, os futuros não são muito adequados, já que muitas vezes têm uma vida útil de 3 ou 6 meses, o que não é suficiente para estudar seu histórico no período gráfico D1.

Com a ajuda do script "TestLoadHistory.mq5" que está na seção do manual "Organização do acesso a dados", podemos verificar o número de barras no símbolo atual e no timeframe D1 no servidor. Eis um exemplo de verificação do número de barras D1 no símbolo "ABBV":

Symbol ABBV

Fig. 1. Símbolo ABBV

Procedimento:

  1. Primeiro, salvamos o script descrito na documentação, criando um novo script no MetaEditor 5 ("Criando um script") com o nome "TestLoadHistory.mq5". Agora, precisamos copiar o texto do script da documentação e colá-lo no script TestLoadHistory.mq5 (o texto colado deve substituir o texto inteiro no script).
  2. Compilamos o script resultante (após a compilação, o script fica visível no terminal na janela Navegador).
  3. Iniciamos o script no MetaTrader 5. Como a verificação é iniciada para o símbolo ABBV, precisamos preparar o gráfico, abrindo a tabela de símbolos ABBV e substituindo o período gráfico por D1. Pegamos o script na janela Navegador e iniciamo-lo no gráfico do ABBV. Nos parâmetros do script, definimos ABBV como nome para o símbolo, selecionamos o período gráfico D1 e especificamos a data 1970:

Running the script

Fig. 2. Executando o script "TestLoadHistory.mq5"

Resultado de operação do script:

TestLoadHistory (ABBV,D1)       Start loadABBV,Dailyfrom1970.03.16 00:00:00
TestLoadHistory (ABBV,D1)       Loaded OK 
TestLoadHistory (ABBV,D1)       First date 2015.09.18 00:00:00 - 758 bars

O histórico começa em 2015 e nele existem 758 barras de D1. Isso é suficiente para análise.

Trabalhando com um grupo de símbolos

Para analisar e calcular qualquer critério, precisamos comparar símbolos de um grupo de símbolos. Normalmente, os símbolos no terminal MetaTrader 5 já estão divididos em grupos (clique com o botão direito na janela Observação do mercado e selecione Símbolos ou pressione Ctrl + U):

Symbols NASDAQ group (SnP100)

Fig. 3. Símbolos do grupo NASDAQ (SnP100)

Na imagem é selecionado o grupo NASDAQ (SnP100). Ele inclui o símbolo ABBV. A maneira mais conveniente de trabalhar com um grupo de símbolos é garantir que o script seja iniciado num símbolo desse grupo. Para fazer uma iteração sobre cada grupo, precisamos abrir manualmente o gráfico de um símbolo de cada grupo e iniciar o script Symbols on symbol tree.mq5 (esse script coleta todos os símbolos do grupo num arquivo separado).

O script Symbols on tree tree.mq5 funciona de acordo com o seguinte algoritmo: obtém-se o caminho na árvore de símbolos SYMBOL_PATH; recupera-se o grupo final de símbolos do caminho obtido (aqui é o grupo NASDAQ(SnP100)); selecionam-se todos os símbolos desse grupo e salvam-se os símbolos selecionados no arquivo. O nome do arquivo é um caminho numa árvore de símbolos em que todos os caracteres "/" e "\" são substituídos por "_" (a substituição é executada automaticamente pelo script, o nome do arquivo também é gerado automaticamente). Após a substituição de símbolos, para o grupo de símbolos NASDAQ(SnP100) é gerado o nome "Stock Markets_USA_NYSE_NASDAQ(SnP100)_.txt".

Por que precisamos colocar cada grupo num arquivo separado? Pois, porque, posteriormente, será possível simplesmente ler os nomes de símbolos dos arquivos de grupos sem enumerar todos os símbolos e analisar a direção dos gaps. Na verdade, o script Symbols on symbol tree.mq5 faz com que evitemos a rotina de selecionar símbolos manualmente de um grupo de símbolos específico.


Script "Symbols on symbol tree.mq5"

Nesse ponto, vamos nos debruçar sobre a operação do script.

ATENÇÃO: apenas o texto Everything is fine. There are no errors na guia Experts garante que o trabalho do script foi bem-sucedido e o arquivo obtido com símbolos pode ser usado para trabalhos futuros!

Para encurtar o código de operações de arquivo, é incluída a classe CFileTxt, enquanto o trabalho com o arquivo de texto é executado pelo objeto de classe m_file_txt — CFileTxt. O script executa seu trabalho em sete passos:

//+------------------------------------------------------------------+
//|                                       Symbols on symbol tree.mq5 |
//|                              Copyright © 2018, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2018, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.000"
//---
#include <Files\FileTxt.mqh>
CFileTxt       m_file_txt;       // file txt object
//---
string   m_file_name="";         // File name
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- STEP 1
   string current_path="";
   if(!SymbolInfoString(Symbol(),SYMBOL_PATH,current_path))
     {
      Print("ERROR: SYMBOL_PATH");
      return;
     }
//--- STEP 2
   string sep_="\\";                 // A separator as a character 
   ushort u_sep_;                    // The code of the separator character 
   string result_[];                 // An array to get strings 
//--- Get the separator code 
   u_sep_=StringGetCharacter(sep_,0);
//--- Split the string to substrings 
   int k_=StringSplit(current_path,u_sep_,result_);
//--- STEP 3
//--- Now output all obtained strings 
   if(k_>0)
     {
      current_path="";
      for(int i=0;i<k_-1;i++)
         current_path=current_path+result_[i]+sep_;
     }
//--- STEP 4
   string symbols_array[];
   int symbols_total=SymbolsTotal(false);
   for(int i=0;i<symbols_total;i++)
     {
      string symbol_name=SymbolName(i,false);
      string symbol_path="";
      if(!SymbolInfoString(symbol_name,SYMBOL_PATH,symbol_path))
         continue;
      if(StringFind(symbol_path,current_path,0)==-1)
         continue;

      int size=ArraySize(symbols_array);
      ArrayResize(symbols_array,size+1,10);
      symbols_array[size]=symbol_name;
     }
//--- STEP 5
   int size=ArraySize(symbols_array);
   if(size==0)
     {
      PrintFormat("ERROR: On path \"%s\" %d symbols",current_path,size);
      return;
     }
   PrintFormat("On path \"%s\" %d symbols",current_path,size);
//--- STEP 6
   m_file_name=current_path;
   StringReplace(m_file_name,"\\","_");
   StringReplace(m_file_name,"/","_");
   if(m_file_txt.Open("5220\\"+m_file_name+".txt",FILE_WRITE|FILE_COMMON)==INVALID_HANDLE)
     {
      PrintFormat("ERROR: \"%s\" file in the Data Folder Common folder is not created",m_file_name);
      return;
     }
//--- STEP 7
   for(int i=0;i<size;i++)
      m_file_txt.WriteString(symbols_array[i]+"\r\n");
   m_file_txt.Close();
   Print("Everything is fine. There are no errors");
//---
  }
//+------------------------------------------------------------------+

Algoritmo do EA:

Repare que, no PASSO 6, o arquivo é criado na pasta 5220 dentro do diretório de arquivos comuns (é usado o sinalizador FILE_COMMON).

Além disso, precisamos nos certificar de que a operação do script seja concluída sem erros, portanto, na guia Experts deve aparecer a mensagem "Everything is fine. There are no errors. Create file:". O nome do arquivo é exibido na próxima linha — copiamos e colamos no script "Getting gap statistics ...". Abaixo está um exemplo de criação bem-sucedida do arquivo:

On path "Stock Markets\USA\NYSE/NASDAQ(SnP100)\" 100 symbols
Everything is fine. There are no errors. Create file:
Stock Markets_USA_NYSE_NASDAQ(SnP100)_

Como resultado, obtemos um arquivo (nesse exemplo, Stock Markets_USA_NYSE_NASDAQ(SnP100)_) em que cada nova linha há um caractere As primeiras cinco linhas desse arquivo são:

AAPL
ABBV
ABT
ACN
AGN

Coletando dados

A obtenção de dados históricos de OHLC por símbolos e cálculo de estatísticas são realizados pelo script "Getting gap statistics.mq5". A estrutura SGapStatistics é preenchida para cada símbolo:

   struct SGapStatistics
     {
      string            name;                // symbol name
      int               d1_total;            // total number of D1 bars
      int               gap_total;           // total number of gaps
      int               gap_confirmed;       // gap was confirmed
     };

name — nome do símbolo
d1_total — número de barras do símbolo em D1
gap_total — número de gaps detectado
gap_confirmed — número de gaps confirmados (por exemplo, o dia abriu como um gap altista e o dia fechou com uma barra de alta)

Para obter os preços OHLC para cada símbolo, a função mais apropriada é "CopyRates". Será usada a terceira forma — de acordo com as datas inicial e final do intervalo de tempo requerido. A hora de início é a hora atual estimada do servidor de negociação TimeTradeServer mais um dia, e a data final é 1º de janeiro de 1970.

Resta decidir como lidar com o erro (como resultado da consulta, é retornado "-1") ou como determinar que nem todos os dados foram retornados como resultado da consulta (por exemplo, nem todos os dados foram baixados do servidor ainda). Podemos proceder de uma maneira simples (consulta — pausa N — segundos — nova consulta) ou de uma maneira correta. A maneira correta é baseada na alteração do script "TestLoadHistory.mq5" - "Organização do acesso aos dados".

Os resultados da consulta do script estão listados abaixo:

   switch(res) 
     { 
      case -1 : Print("Símbolo desconhecido",InpLoadedSymbol);                        break; 
      case -2 : Print("Número de barras maior do que pode ser exibido no gráfico"); break; 
      case -3 : Print("Execução interrompida pelo usuário");                    break; 
      case -4 : Print("O indicador não deve carregar dados próprios");          break; 
      case -5 : Print("Falha de carregamento");                              break; 
      case  0 : Print("Todos os dados carregados");                                      break; 
      case  1 : Print("Os dados disponíveis na série temporal já são suficientes");               break; 
      case  2 : Print("Série temporal construída a partir dos dados disponíveis no terminal");         break; 
      default : Print("O resultado da execução não está definido"); 
     }

Isto é, um resultado de execução menor que zero é um erro. Nesse caso, o esquema de trabalho será abrir o arquivo com os símbolo e realizar uma consulta para cada símbolo. Totalizamos os resultados negativos. Se houver pelo menos um resultado negativo, exibiremos uma mensagem sobre a presença de problemas com as consultas. O usuário, nesse caso, precisa executar o script novamente (provavelmente, o histórico já está sendo carregado ou construído nesse momento). Se não houver erros, obtemos os dados de OHLC e calculamos o número de gaps.


Script "Getting gap statistics.mq5"

Esse script exibe as estatísticas de gaps na guia "Experts" do terminal. A seguir, consideraremos a confirmação do gap. Um gap é confirmado quando a barra diária está fechada na direção do gap, enquanto um gap não é confirmado — quando a barra diária é fechada na direção oposta ao gap:


Gaps

Fig. 4. Gaps confirmados e não confirmados

Ele tem um parâmetro de entrada, isto é, "File name", que, por sua vez, é o nome do arquivo que foi gerado pelo script auxiliar "Symbols on symbol tree.mq5" (se você ainda se lembra, esse arquivo é criado na pasta compartilhada no diretório 5220). O nome do arquivo é exibido sem especificação do diretório e da extensão:

Getting gap statistics Inputs

Fig. 5. Parâmetro de entrada do script "Getting gap statistics"

Assim, para obter estatísticas, devemos realizar certos passos:

  1. Selecionamos um grupo de símbolos para o qual serão estimados gaps.
  2. Desse grupo, escolhemos qualquer símbolo e abrimos seu gráfico.
  3. No gráfico aberto, colocamos o script "Symbols on symbol tree.mq5" — como resultado, será criado um arquivo com todos os símbolos desse grupo. É necessário certificar-se de que não há erros enquanto o script está sendo executado: na guia "Experts", deve aparecer a mensagem "Everything is fine. There are no errors".
  4. Colocamos no gráfico o script "Getting gap statistics.mq5"

Como resultado, na guia "Experts", veremos as estatísticas sobre o número de gaps, abaixo observamos os cinco primeiros símbolos:

      [name] [d1_total] [gap_total] [gap_confirmed]
[ 0] "AAPL"        7238        3948            1640
[ 1] "ABBV"         759         744             364
[ 2] "ABT"          762         734             374
[ 3] "ACN"          759         746             388
[ 4] "AGN"          761         754             385

Agora com CGraphic

A exibição de todas as informações na guia "Experts" não ajuda muito, portanto, o script "Getting gap statistics CGraphic.mq5" para exibir gráficos usará gráficos personalizados CGraphic. O script tem os parâmetros de entrada:

O resultado é um gráfico com o número de gaps confirmados (como uma porcentagem):

Getting gap statistics CGraphic

Fig. 6. O resultado do script "Getting gap statistics CGraphic.mq5"

Na figura são marcados com números:

O gráfico deixa claro que, embora haja três picos abaixo de 42%, os valores dos gaps flutuam em torno de 50% mais/menos 6%. Esses três picos com gaps confirmados é inferior a 42%, o que significam que uma barra diária se moverá contra o gap em três símbolos com probabilidade de 58%.

Agora, podemos verificar outro grupo de símbolos — Stock Markets\RussiaMICEX20. Resultado do script "Getting gap statistics CGraphic.mq5" para o grupo Stock Markets\RussiaMICEX20:

Stock Markets_Russia_MICEX20_

Fig. 7. Estatísticas de gap para o grupo Stock Markets\RussiaMICEX20

Aqui há dois pontos anômalos. No entanto, não podemos vincular a imagem e o símbolo na versão atual. É por isso que precisamos melhorar um pouco o script.


Script "Getting gap statistics CGraphic 2.mq5

Alterações: na versão 2.0, na guia "Expert" são exibidas as estatísticas dos gaps confirmados como uma porcentagem. Graças a isso, quando a configuração é "Log Statistics" para o grupo Stock Markets\RussiaMICEX20 é fácil encontrar dois símbolos anormais:

          [name] [d1_total] [gap_total] [gap_confirmed] [confirmed_per]
***
[14] "NVTK.MM"          757         737             347           47.08
[15] "PIKK.MM"          886         822             282           34.31
[16] "ROSN.MM"          763         746             360           48.26
[17] "RSTI.MM"          775         753             357           47.41
[18] "RTKM.MM"          753         723             324           44.81
[19] "SBER.MM"          762         754             400           53.05
[20] "SBER_p.MM"        762         748             366           48.93
[21] "SNGS.MM"          762         733             360           49.11
[22] "TATN.MM"          765         754             370           49.07
[23] "SNGS_p.MM"        751         708             305           43.08
[24] "URKA.MM"          765         706             269           38.10
[25] "VTBR.MM"          763         743             351           47.24
[26] "RASP.MM"          778         756             354           46.83

Para os símbolos "PIKK.MM" 34% e "URKA.MM" 38% com gaps confirmados, existe 66% e 62% de probabilidade de a barra diária fechar contra o gap.


Limitando o número de símbolos num arquivo

Ao analisar diferentes grupos de símbolos, encontrei alguns que contêm mais de mil símbolos. Trabalhar assim é muito inconveniente, já que tantos símbolos tardam muito tempo a ser carregados na "Observação do mercado", fazendo, ao mesmo tempo, com que o gráfico resultante seja impossível de interpretar por causa da quantidade de dados amontoados.

Por essa razão, decidi atualizar o script "Symbols on symbol tree.mq5", escrevendo a versão "Symbols on symbol tree 2.mq5". Na versão 2, o número máximo de símbolo num arquivo não é maior que 200, além disso, o número da parte é adicionado ao nome do arquivo. Por exemplo, no grupo de símbolos "Stock Markets\USA\NYSE/NASDAQ(SnP100)\" há 100 símbolos, o que significa que vai haver apenas uma parte, portanto, o nome do arquivo será: "Stock Markets_USA_NYSE_NASDAQ(SnP100)_part_0.txt".


Selecionando arquivos usando a caixa de diálogo do sistema "Abrir arquivo"

Depois de ter trabalhado por vários dias com scripts desse arquivo, comecei entender que incluir o nome do artigo nos parâmetros de entrada do script "Getting gap statistics CGraphic 2.mq5" não é era melhor escolha. Temos que fazer várias coisas, como abir a pasta compartilhada de todos os terminais, copiar o nome do arquivo e, em seguida, inserir o nome de arquivo copiado no script.

Portanto, o arquivo é escolhido usando a função DLL GetOpenFileName do sistema. Para isso, insiro o arquivo "GetOpenFileNameW.mqh". A partir desse arquivo, a função "OpenFileName" retorna o caminho completo do arquivo *.txt selecionado, por exemplo: "C:\Users\barab\AppData\Roaming\MetaQuotes\Terminal\Common\Files\5220\Stock Markets_USA_NYSE_NASDAQ(SnP100)_part_0.txt". Agora precisamos selecionar o nome do arquivo desse caminho.

O script "Getting gap statistics CGraphic 3.mq5" usa a função DLL GetOpenFileName:

Allow DLL

Fig. 8. Consulta de permissão de DLL ao iniciar o script "Getting gap statistics CGraphic 3.mq5"

Aqui está como é selecionado o arquivo usando a caixa de diálogo do sistema "Abrir arquivo":

File select

Fig. 9. Seleção de arquivo


Estatísticas sobre outras ações

Agora é possível coletar estatísticas de gaps para outros grupos de símbolos.


Grupo Stock Markets\USA\NYSE\NASDAQ(ETFs)

Os símbolos do grupo são divididos em sete arquivos:

Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_0

Fig. 10. Grupo Stock Markets\USA\NYSE\NASDAQ(ETFs), parte 0


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_1

Fig. 11. Grupo Stock Markets\USA\NYSE\NASDAQ(ETFs), parte 1


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_2

Fig. 12. Grupo Stock Markets\USA\NYSE\NASDAQ(ETFs), parte 2


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_3

Fig. 13. Grupo Stock Markets\USA\NYSE\NASDAQ(ETFs), parte 3


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_4

Fig. 14. Grupo Stock Markets\USA\NYSE\NASDAQ(ETFs), parte 4


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_5

Fig. 15. Grupo Stock Markets\USA\NYSE\NASDAQ(ETFs), parte 5


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_6

Fig. 16. Grupo Stock Markets\USA\NYSE\NASDAQ(ETFs), parte 6


Grupo "Stock Markets\United Kngdom\LSE Int. (ADR/GDR)\"

Stock Markets_United Kngdom_LSE Int. (ADR_GDR)_

Fig. 17. Grupo "Stock Markets\United Kngdom\LSE Int. (ADR/GDR)\"


Grupo "Stock Markets\United Kngdom\LSE (FTSE350)\"

Esse grupo tem 350 símbolo, daí que o símbolo é dividido em dois arquivos.

Stock Markets_United Kngdom_LSE (FTSE350)_part_0

Fig. 18. Grupo "Stock Markets\United Kngdom\LSE (FTSE350)\", parte 0


Stock Markets_United Kngdom_LSE (FTSE350)_part_1

Fig. 19. Grupo "Stock Markets\United Kngdom\LSE (FTSE350)\", parte 1


Grupo "Stock Markets\Germany\XETRA (IBIS)\Dax100\"

Stock Markets_Germany_XETRA (IBIS)_Dax100_part_0

Fig. 20. Grupo "Stock Markets\Germany\XETRA (IBIS)\Dax100\"


Grupo "Stock Markets\France\Eurnext (CAC40)\"

Stock Markets_France_Eurnext (CAC40)_part_0

Fig. 21. Grupo "Stock Markets\France\Eurnext (CAC40)\"

Fim do artigo

Ao examinar vários mercados de ações, vi que, após um gap, a probabilidade de movimento contínuo e a probabilidade de reversão para muitos é próxima de 50%, isto é, tentar pegar um gap tem a taxa de sucesso de 50/50. Ao mesmo tempo, existem títulos com probabilidades (de continuação e reversão) consideravelmente superiores a 65%. Esses títulos podem ser usados para negociar com base em gaps.

Ao artigo foram anexados os scripts descritos no artigo:

Nome do scriptDescrição
 Symbols on symbol tree.mq5 Script auxiliar. Define um grupo de símbolos na árvore e salva todos os símbolo desse grupo num arquivo, numa pasta compartilhada, no diretório 5220.
 Symbols on symbol tree 2.mq5  Script auxiliar. Define um grupo de símbolos na árvore e salva todos os símbolo desse grupo num arquivo, numa pasta compartilhada, no diretório 5220. Divide um grupo de símbolos em arquivos de 200 símbolos.
 Getting gap statistics.mq5 O script carrega os símbolos do arquivo criado pelo script auxiliar e exibe as estatísticas de gaps na guia "Experts"
 Getting gap statistics CGraphic.mq5 O script carrega os símbolos do arquivo criado pelo script auxiliar e exibe as estatísticas de gaps como um gráfico, usando os gráficos personalizados CGraphic
  Getting gap statistics CGraphic 2.mq5 O script carrega os símbolos do arquivo criado pelo script auxiliar e exibe as estatísticas de gaps como um gráfico, usando os gráficos personalizados CGraphic. As estatísticas na guia "Experts" também são exibidas em porcentagem.
  Getting gap statistics CGraphic 3.mq5 O script carrega os símbolos do arquivo criado pelo script auxiliar e exibe as estatísticas de gaps como um gráfico, usando os gráficos personalizados CGraphic. As estatísticas na guia "Experts" também são exibidas em porcentagem. Para selecionar um arquivo com símbolos, é usada a caixa de diálogo do sistema "Abrir arquivo" 
  GetOpenFileNameW.mqh Arquivo incluído para operação da caixa de diálogo do sistema "Abrir arquivo"