Diferenças entre ticks salvos em Tempo Real, em Backtest (Cada tick é baseado em um tick real) e exportados de Exibir >> Ativos >> Ticks

 

Estou escrevendo este tópico para compartilhar meu conhecimento e entendimento a respeito do que ocorre com os ticks em Tempo Real e em Backtest pois gostaria de saber se o entendimento de outros membros do fórum é o mesmo.

Na verdade busquei em todos os lugares possíveis e não encontrei uma resposta, sendo assim, resolvi suar a camisa e achar uma explicação razoável para o fato do meu EA apresentar resutados diferentes em Tempo Real e no Backtest. Espero que se interessem pelo assunto para que analisem esses dados em suas corretoras e contribuam com o processo de aprendizado de todos.

Se o seu EA toma decisões baseadas em dados de ticks tenho a certeza de que enfrenta o mesmo problema que eu neste momento, e acredito que assim como eu, você ouviu algumas explicações para a diferença nos resultados do seu EA que no meu ponto de vista, pelo fato da minha lógica depender de uma informação idêntica entre Tempo Real e Backtest em termos de atributos e número de ticks, não são a verdadeira causa das diferenças de resultado pelo menos no meu caso.

Observem os 3 conjuntos de ticks a seguir:

Ticks exportados de Exibir >> Ativos >> Ticks

# <DATE> <TIME> <BID> <ASK> <LAST> <FLAGS>
1 2023.07.05 08:54:59.981 121350 84
2 2023.07.05 08:54:59.993 120780 84
3 2023.07.05 08:54:59.993 118625 50
4 2023.07.05 08:54:59.993 0 0 0 0
5 2023.07.05 08:54:59.994 120000 50
6 2023.07.05 08:54:59.994 118625 2
7 2023.07.05 08:54:59.994 120000 2
8 2023.07.05 08:54:59.994 120300 50
9 2023.07.05 08:54:59.994 120000 2
10 2023.07.05 08:54:59.994 120300 2


Ticks salvos durante Backtest

# <DATE> <TIME> <BID> <ASK> <LAST> <FLAGS>
1 20230705 08:54:59 0 121350 0 86
2 20230705 08:54:59 0 120780 0 84
3 20230705 08:54:59 118625 120780 0 50
4 20230705 08:54:59 118625 120780 0 2
5 20230705 08:54:59 120000 120780 0 50
6 20230705 08:54:59 118625 120780 0 2
7 20230705 08:54:59 120000 120780 0 2
8 20230705 08:54:59 120300 120780 0 50
9 20230705 08:54:59 120000 120780 0 2
10 20230705 08:54:59 120300 120780 0 2


Ticks salvos em Tempo Real

# <DATE> <TIME> <BID> <ASK> <LAST> <FLAGS>
1 20230705 08:54:59 0 121350 120895 86
2 20230705 08:54:59 118625 120780 120895 0
3 20230705 08:54:59 118625 120780 120895 0
4 20230705 08:54:59 120300 120780 120895 50
5 20230705 08:54:59 120300 120780 120895 2


Dá um pouco de trabalho observar os dados e chegar às conclusões abaixo, mas garanto que vale a pena pois pode ser a causa de diferenças nos resultados, análises e otimizações feitas em Backtest:


1 - Os Ticks exportados de Exibir >> Ativos >> Ticks provavelmente são as informações sem tratamento dos ticks enviados pela B3 e salvos pela corretora.

2 - O Metatrader provavelmente faz tratamentos nestes dados quando realizamos o Backtest (Cada tick é baseado em um tick real), perceba que o número de ticks é o mesmo neste caso, porém, atributos dos ticks são alterados de um para o outro, vide diferença entre o tick #3 dos exportados x Backtest.

3 - Provavelmente com o intuito de reduzir o número de ticks a se enviar demandando menos banda de comunicação e melhoria de performance, no conjunto 3, Ticks salvos em Tempo Real, temos a metade do número de ticks com alterações mais significativas nos atributos dos ticks tornando a relação entre eles ainda mais complexa e possivelmente alterando os resultados do seu EA se ele de certa forma se baseia no número de ticks enviados.

Algumas questões:

- A sua corretora fornece alguma documentação que explique o que está sendo feito com os ticks originais antes de nos enviar em Tempo Real?

- Alguém aí tem conhecimento profundo do que o Metatrader faz com os ticks originais durante o Backtest e em Tempo Real?

Minha análise por enquanto se resumiu aos primeiros ticks do dia pois quanto mais o dia avança mais trabalho dá entender a relação entre os ticks originais e os salvos durante o Backtest (Cada tick é baseado em um tick real).


Estou anexando o código do EA que salva em .csv os ticks, pode ser rodado tanto em Tempo Real quanto no Backtest para analisar as diferenças entre eles. Os arquivos são salvos em um diretório parecido com:
C:\Users\Usuário\AppData\Roaming\MetaQuotes\Tester\xxxxxxxxxxxxx\Agent-127.0.0.1-3000\MQL5\Files (No caso do Backtest)

C:\Users\ Usuário \AppData\Roaming\MetaQuotes\Terminal\ xxxxxxxxxxxxx \MQL5\Files (No caso de Tempo Real)

#property strict

int      fileHandle = INVALID_HANDLE;
int      giCount;
string   gsDate;
string   gsAux, gsTime;

void ResetMqlTick(MqlTick& tick)
{
    tick.time = 0;
    tick.bid = 0.0;
    tick.ask = 0.0;
    tick.last = 0.0;
    tick.volume = 0.0;
    tick.time_msc = 0;
    tick.flags = 0;
}

void SaveTicks()
{
   
   // Obtém os dados do tick
   MqlTick tick;
   
   ResetMqlTick(tick);
   
   if (!SymbolInfoTick(_Symbol, tick))
   {
     Print("Erro ao obter os dados do tick.");
     return;
   }
   
   if ( TimeToString(tick.time, TIME_MINUTES) != gsTime )
   {
      
      // Fecha o arquivo do minuto anterior se estiver aberto
      if (fileHandle != INVALID_HANDLE)
      {
         FileClose(fileHandle);
         
         fileHandle = INVALID_HANDLE;
      }

      giCount = 0;
      
   }
   
   // Verifica se o arquivo foi aberto
   if (fileHandle == INVALID_HANDLE)
   {
      gsDate = TimeToString(tick.time, TIME_DATE);
      gsTime = TimeToString(tick.time, TIME_MINUTES);
      
      gsAux = gsTime;
      
      StringReplace(gsDate, ".", "");
      StringReplace(gsAux, ":", "");
      
      // Cria ou abre o arquivo para escrever
      fileHandle = FileOpen("WINQ23_ticks " + gsDate + " " + gsAux +".csv", FILE_WRITE|FILE_CSV, ';');
      
      if (fileHandle == INVALID_HANDLE)
      {
         Print("Erro ao abrir o arquivo.");
         return;
      }
   }
   
   giCount++;
   
   // Formata e escreve os dados no arquivo CSV
   string line = IntegerToString(giCount) + ";" + gsDate + ";" + TimeToString(tick.time, TIME_SECONDS) + ";" + DoubleToString(tick.bid, 0) + ";" + DoubleToString(tick.ask, 0) + ";" + DoubleToString(tick.last, 0) + ";" + IntegerToString(tick.flags);
   
   FileWrite(fileHandle, line);
   
}

void OnInit()
{
    // Verifica se o símbolo atual é WINQ23
    if (Symbol() != "WINQ23")
    {
        Print("Este EA é específico para o símbolo WINQ23.");
        return;
    }
}

void OnDeinit(const int reason)
{
   // Fecha o arquivo antes de encerrar
   if (fileHandle != INVALID_HANDLE)
   {
      // Obtém os dados do tick
      MqlTick tick;
      
      if (!SymbolInfoTick(_Symbol, tick))
      {
        Print("Erro ao obter os dados do tick.");
        return;
      }
      
      giCount++;
      
      // Formata e escreve os dados no arquivo CSV
      string line = IntegerToString(giCount) + ";" + gsDate + ";" + TimeToString(tick.time, TIME_SECONDS) + ";" + DoubleToString(tick.bid, 0) + ";" + DoubleToString(tick.ask, 0) + ";" + DoubleToString(tick.last, 0) + ";" + IntegerToString(tick.flags);
      
      FileWrite(fileHandle, line);
      
      FileClose(fileHandle);
      
   }
}

void OnTick()
{
    // Salva os ticks no arquivo
    SaveTicks();
}
 

Por favor EDITE o seu comentário e utilize o botão do CÓDIGO (Alt -S) ao inserir o seu código.

Botão de código no editor

 
Fernando Carreiro #:

Por favor EDITE o seu comentário e utilize o botão do CÓDIGO (Alt -S) ao inserir o seu código.

Obrigado pela orientação @Fernando Carreiro, espero ter feito corretamente desta vez!