English Русский 中文 Español Deutsch 日本語 Türkçe
preview
Força bruta para encontrar padrões (Parte III): novos horizontes

Força bruta para encontrar padrões (Parte III): novos horizontes

MetaTrader 5Testador | 12 abril 2021, 09:49
1 404 0
Evgeniy Ilin
Evgeniy Ilin

Sumário


Introdução

O artigo anterior mostrava que criar EAs lucrativos era possível usando um mecanismo tão simples como a força bruta, em grande parte devido ao fato de que essa abordagem, como qualquer outra, não era pior do que as outras. Na verdade, este tópico é muito semelhante ao meu artigo "Abordagem ideal para desenvolver e analisar sistemas de negociação", e especialmente com a seção "Matemática de pesquisa ideal". Ao criar este software, a ênfase foi colocada nos pensamentos que foram formulados neste artigo. De uma forma geral, o artigo visa continuar a modernizar os algoritmos do meu programa de forma a obter indicadores de maior qualidade em comparação com as opções encontradas, bem como para uma pesquisa de mercado mais detalhada em diferentes dias da semana e em diferentes corredores de tempo.

Vários de meus EAs demonstram que vale a pena considerar essa abordagem. Existem diferentes padrões para diferentes pares de moedas. Existem corredores de tempo estreitos que funcionam com todos os pares, tudo o que precisamos é realizar uma análise completa, como neste artigo. Essa análise não pode ser realizada sem o uso de software adicional. Também quero dizer que não considero meu software o melhor de seu tipo e, mais ainda, não o considero o Graal.

Inicialmente, o programa era um programa de pesquisa e era adequado apenas como uma caixa de ferramentas adicional para analisar vários instrumentos, sendo que agora suas capacidades aumentaram muitas vezes. Visto que essa abordagem funciona, por que não tirar o máximo proveito dela? Acho que vale a pena tentar. Em geral, para ser honesto, considero abordagens como redes neurais, inteligência artificial e até mesmo o mesmo aumento de gradiente, muito mais progressivas, mas como se viu, ela pode competir com esses métodos de análise. Também é necessário levar em conta o fato de que a base ainda é matemática muito simples. Eu acho que isso está longe de alcançar um teto.


Novos pensamentos e ideias

O programa era um protótipo e eu queria extrair o máximo dele e ver do que mesmo um método de pesquisa simples como a enumeração aleatória de números é capaz. O principal problema era que, para uma busca confiável de padrões globais, era preciso pegar grandes parcelas de cotações. Por exemplo, ao analisar as cotações do período M5 de qualquer par de moedas ao longo de 10 anos, o programa gerava cerca de 700-2000 variantes por hora em 1 núcleo bom, e isso mesmo com configurações decentes.

Se termos um servidor com 30 núcleos, a velocidade não será muito alta, e teremos que esperar dias. A única saída é reduzir a quantidade de dados que precisam ser analisados; isso só pode ser feito cortando todo o intervalo em partes iguais e pulando periodicamente alguns deles sem realizar cálculos. Esses intervalos são dias, meses, anos, minutos, horas. Além disso, cada uma dessas áreas condicionais caracteriza certos parâmetros de negociação. Em outras palavras, além da aceleração, também temos a oportunidade de examinar detalhadamente se todos os dias da semana, horas e minutos possuem padrões. Não precisamos nos preocupar com a causa desse padrão.

Basicamente, é impossível classificar todos os padrões, porque pode haver um número infinito deles, e o cérebro humano não é capaz de compreender e descrever todos (e isso não é necessário) quando existe uma fórmula que funciona. Os matemáticos vão me entender. Você pode explorar um período fixo de tempo e dias fixos ou explorar tudo de uma vez. Isso pode ser comparado com isto: suponhamos que tivéssemos uma função de uma variável, e vemos que este é um caso especial de uma função de muitas variáveis.


Segmentação de amostra e previsibilidade de amostras derivadas

Achei que seria muito interessante analisar esta questão, porque, como se viu, os modos de busca de padrões são muito diferentes até porque que amostras completamente diferentes são analisadas em termos de duração. Além de acelerar os cálculos várias vezes, e talvez dezenas de vezes, em alguns casos, é fácil adivinhar que da amostra inicial (cotação) podemos obter, embora pequena, uma amostra mais útil. Uma que pode ser analisada usando algumas fórmulas simples ou polinômios. Mas o mercado tem uma vinculação muito rígida ao horário mundial.

A atividade comercial é formada em grande parte com base na atividade diária das pessoas. Os EAs também podem ser incluídos nesta categoria. Muitos EAs podem ser considerados jogadores previsíveis, não todos, é claro, mas a maioria. Muitos desenvolvedores criam os chamados scalpers noturnos que funcionam na hora definida. Aqui temos um pouco de assunto para refletirmos. Acontece que a natureza do movimento dos preços é determinada não apenas pelos preços anteriores, mas também por certos dias, semanas, meses, possivelmente até anos. Cada uma dessas magnitudes é quantizada, ou seja, possui determinados valores fixos.

Claro, esses valores podem ser divididos. Por exemplo, a janela de tempo pode ser medida não em horas e minutos, mas, digamos, em segundos decorridos desde o início de um novo dia. Tudo depende de quão conveniente seja para nós medirmos esses valores. De modo geral, todas essas magnitudes quantizadas podem ser subdivididas ao infinito. Em meu programa, a segmentação ocorre apenas em alguns dias e semanas. Achei que segmentar por meses e anos não é tão eficaz, embora talvez mais tarde acrescente a funcionalidade de meses, como fiz com os dias da semana. Vou descrever meus pensamentos na forma de um diagrama:

Segmenting Diagram

Descrevi duas variantes arbitrárias para segmentar a amostra original, e abaixo mostro o que aconteceria se nossa força bruta ocorresse indefinidamente. No primeiro caso, se tivéssemos implementado todos os modelos matemáticos possíveis para descrição, e no segundo caso, o que obtemos do único método de força bruta implementado (polinômio de Taylor multidimensional). Pode-se entender imediatamente que sempre existe a amostra mais previsível e a mais imprevisível. Também para cada tipo de polinômio, há uma seção segmentada otimizada ao máximo. Existem inúmeras dessas seções, mas podemos localizá-las no minuto mais próximo. Não considero segundos aqui, pois estamos analisando barras.

Com base nessas conclusões, pode-se supor que para cada combinação de parâmetros de segmentação, podemos compor uma função para cada parâmetro de negociação que seria importante para nós no robô, e que poderíamos obter na saída de todo o ciclo de desenvolvimento. Por exemplo, o valor esperado e o fator de lucro:

  • Ma=Ma(M,D,Ts,Te)
  • PrF=PrF(M,D,Ts,Te)
  • M - mês do ano
  • D - dia da semana
  • Ts - hora do início do corredor
  • Te - hora do final do corredor (pode haver uma transição até 0:00) 

De modo geral, essas são funções discretas. Ou seja, os argumentos podem assumir valores estritamente fixos. Se corrigirmos as variáveis associadas aos meses e dias da semana, você poderá imaginar como essas 2 funções ficarão. As medidas máximas que podemos visualizar são três, por isso, um gráfico mais informativo pode ser desenhado com apenas duas variáveis livres. Eu escolhi "Ts" e "Te":

3D Graph

Cada fórmula ou algoritmo com o qual tentaremos prever o futuro terá esses gráficos exclusivos para todas as características quantitativas do futuro sistema de negociação. Citei apenas dois para mostrar que, onde há um fator de lucro máximo, não haverá necessariamente um valor esperado máximo. Na maioria dos casos, termos que equilibrar entre o valor esperado e o fator de lucro, pois somos prejudicados por spreads, comissões e swaps. O número e a magnitude desses extremos são diferentes para cada fórmula. Não poderemos realizar uma busca multidimensional de extremos manualmente, mas o programa é bem capaz disso, o que já prova com sucesso.

Também gostaria de observar que, ao pesquisar o mercado usando meu software, percebi uma área muito interessante em que, na maioria dos casos, todos os pares de moedas superestimaram os indicadores de previsibilidade. Esse intervalo é aproximadamente das 23h30 às 0h30. Talvez eu não tenha escrito exatamente, mas é definitivamente relacionado ao ponto em que dia muda. Mas, como se viu, ao testar essas estratégias no MetaTrader 5 que mostraram excelentes fatores de lucro no MetaTrader 4, toda essa lucratividade aparente desapareceu. O spread é o culpado. Aconselho a todos que tenham muito medo do fato de que seu padrão ficará dentro do spread. A maioria dos padrões encontrados estará dentro do spread.


Modificações finais do algoritmo de busca

As modificações finais tiveram como objetivo agilizar o programa, bem como maximizar a variabilidade e eficiência da pesquisa. Lista de mudanças:

  1. Adicionada a capacidade de pesquisar padrões num intervalo de tempo fixo
  2. Adicionada a capacidade de negociar apenas em dias marcados
  3. Adicionada a capacidade de gerar conjuntos aleatórios de dias para cada nova opção com base nos dias marcados
  4. Adicionada a capacidade de gerar janelas de tempo do servidor aleatórias, especificando a duração mínima e máxima possível da janela em minutos
  5. É possível combinar qualquer uma dessas configurações
  6. A segunda guia de otimização agora pode funcionar no modo multi-threaded
  7. O modo de otimização foi melhorado e agora encontra tudo o que pode ser encontrado

Tudo fica assim agora:

Guia de força bruta

A segunda guia não mudou, mas vou mostrá-la mesmo assim:

Guia de otimização

A terceira guia tem a seguinte aparência:

Guia de geração do Expert Advisor

Claro que a interface ainda está longe de ser perfeita e as configurações mal cabem no formulário, mas na próxima versão, que mostrarei no próximo artigo, a interface será completamente redesenhada, ela se tornará agradável e compreensível para todos. Também pretendo gravar um vídeo de todo o processo de criação de um Expert Advisor usando meu programa. Todos verão como é fácil, rápido e divertido. Basta entender um pouco sobre as configurações da interface e ter um pouco de prática.


Otimização de modelos e do EA auxiliar

Além disso, para esta tarefa, foi necessário modificar os modelos dos Expert Advisors, bem como os robôs que geram cotações num formato de fácil leitura pelo programa. O código do Expert Advisor que gera cotações para MetaTrader 5 fica assim:

string FileNameString;
uint Handle0x;
datetime Time0=0;

double Open[];
double Close[];
double High[];
double Low[];
datetime Time[];


void WriteEnd()
   {
   FileWriteString(Handle0x,"EndBars"+"\r\n");
   MqlDateTime T;
   TimeToStruct(Time[1],T);
   FileWriteString(Handle0x,IntegerToString(int(T.year))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.mon))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.day)));
   }

void OpenAndWriteStart()
   {
   FileDelete(FileNameString);
   Handle0x=FileOpen(FileNameString,FILE_WRITE|FILE_TXT|FILE_COMMON|FILE_ANSI,'\t',CP_UTF8);
   FileSeek(Handle0x,0,SEEK_SET);
   FileWriteString(Handle0x,"DataXXX"+" "+Symbol()+" "+IntegerToString(Period())+"\r\n");
   FileWriteString(Handle0x,DoubleToString(_Point,8)+"\r\n");
   MqlDateTime T;
   TimeToStruct(Time[1],T);
   FileWriteString(Handle0x,IntegerToString(int(T.year))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.mon))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.day))+"\r\n");             
   }
      
void WriteBar()
   {
   FileWriteString(Handle0x,"\r\n");
   FileWriteString(Handle0x,DoubleToString(Close[1],8)+"\r\n");
   FileWriteString(Handle0x,DoubleToString(Open[1],8)+"\r\n");
   FileWriteString(Handle0x,DoubleToString(High[1],8)+"\r\n");
   FileWriteString(Handle0x,DoubleToString(Low[1],8)+"\r\n");         
   FileWriteString(Handle0x,IntegerToString(int(Time[1]))+"\r\n");
   MqlDateTime T;
   TimeToStruct(Time[1],T);
   FileWriteString(Handle0x,IntegerToString(int(T.hour))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.min))+"\r\n");
   FileWriteString(Handle0x,IntegerToString(int(T.day_of_week))+"\r\n");         
   //FileClose(Handle0x);
   }      

void CloseFile()
   {
   FileClose(Handle0x);
   }

bool bNewBar()
   {
   ArraySetAsSeries(Close,false);                        
   ArraySetAsSeries(Open,false);                           
   ArraySetAsSeries(High,false);                        
   ArraySetAsSeries(Low,false);                              
   CopyOpen(_Symbol,_Period,0,2,Open);
   CopyClose(_Symbol,_Period,0,2,Close);
   CopyHigh(_Symbol,_Period,0,2,High);
   CopyLow(_Symbol,_Period,0,2,Low);
   ArraySetAsSeries(Close,true);                        
   ArraySetAsSeries(Open,true);                           
   ArraySetAsSeries(High,true);                        
   ArraySetAsSeries(Low,true);                                 
   if ( Time0 < Time[1] )
      {
      if (Time0 != 0)
         {
         Time0=Time[1];
         return true;
         }
      else
         {
         Time0=Time[1];
         return false;
         }
      }
   else return false;
   }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
  ArrayResize(Close,2,0);
  ArrayResize(Open,2,0);   
  ArrayResize(Time,2,0);
  ArrayResize(High,2,0);
  ArrayResize(Low,2,0);  
  FileNameString="DataHistory"+" "+Symbol()+" "+IntegerToString(Period());
  OpenAndWriteStart();
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
  WriteEnd();
  CloseFile();
  }

void OnTick()
  {
  ArraySetAsSeries(Time,false);
  CopyTime(_Symbol,_Period,0,2,Time);
  ArraySetAsSeries(Time,true);
  if ( bNewBar()) WriteBar();
  }

Existem apenas algumas funções simples, algumas escrevem algo no início do teste, outras adicionam algumas informações sobre a cotação no final e a principal simplesmente escreve informações sobre a barra quando ela aparece. O Expert Advisor não tem configurações de entrada, basta executá-lo com base no histórico e ele irá gerar um arquivo de cotação num formato que o programa pode ler. Talvez no futuro eu trabalhe com os formatos de cotações em terminais e os leia diretamente. Mas por enquanto assim como está já é bastante conveniente. Pelo menos não me incomoda.

Em vez de usar funções temporárias que transformam o formato datatime em dias da semana, horas e minutos, apenas as escrevo na cotação como informações adicionais sobre a barra. Todos esses são valores inteiros, exceto ENUM_DAY_OF_WEEK. Tudo o que tive de fazer foi implementar essa lista numerada dentro do código C#, que é tão fácil quanto descascar peras e, é claro, presumir em meus modelos que os dados serão retornados da mesma forma. Evitar funções temporárias permite que pular cálculos desnecessários no lado do código C#. Além disso, evita inconsistências de tempo. É melhor evitar essas coisas perigosas.

Arquivo de cotações na saída pode ser aberto com qualquer editor de texto com uma estrutura tão simples e compreensível quanto esta:

History Data File


O cabeçalho do modelo, onde são registradas as variáveis, antes continha campos para autopreenchimento no momento da geração, agora sua lista foi preenchida com variáveis de horário de negociação e dias de negociação.

Modelo de configurações de entrada agora fica assim:

double C1[] = { %%%CVALUES%%% };//Brutted Values
int CNum=%%%CNUMVALUE%%%;//Bars To Equation
int DeepBruteX=%%%DEEPVALUE%%%;//Max Pow Of Polinom
int DatetimeStart=%%%DATETIMESTART%%%;//Help Datetime
input bool bInvert=%%%INVERT%%%;//Invert Trade(or sign of values as the same)
input int DaysToFuture=%%%DAYSFUTURE%%%;//Days To Future
int DaysToTrade[]={ %%%DAYS%%% };//Days To Trade
input double ValueOpenE=%%%OPTVALUE%%%;//Open Signal
input bool bUseTimeCorridorE=%%%TIMECORRIDORVALUE%%%;//Use Time Corridor
input int TradeHour=%%%HOURSTARTVALUE%%%;//Start Trading Hour
input int TradeMinute=%%%MINUTESTARTVALUE%%%;//Start Trading Minute
input int TradeHourEnd=%%%HOURENDVALUE%%%;//End Trading Hour
input int TradeMinuteEnd=%%%MINUTEENDVALUE%%%;//End Trading Minute

Aqui, todos os valores são preenchidos pelo programa no momento da criação do robô para que este funcione imediatamente com as configurações padrão e compile no momento em que o terminal é iniciado, sem ter que entrar no MetaEditor. Todas as configurações e arrays são integrados no próprio EA. Eu acho isso conveniente. Imagine que você tenha um monte desses Expert Advisors e cada um deles não deva confundir as configurações. O protótipo de força bruta para MetaTrader 4 mostrou que até eu às vezes bagunço as configurações e as confundo. Claro, perdemos em funcionalidade, uma vez que seria possível escrever as configurações num arquivo de texto simples e ler a partir dele, mas, novamente, esses arquivos podem ser confundidos e, novamente, aparece o problema.

Função principal também passou por uma série de mudanças:

bool bDay()//Day check
   {
   MqlDateTime T;
   TimeToStruct(Time[0],T);
   for ( int i=0; i<ArraySize(DaysToTrade); i++ )
      {
      if ( T.day_of_week == DaysToTrade[i] ) return true;
      }
   return false;
   }

void Trade()//Trade Function
   {
   double Value;
   Value=PolinomTrade();
   MqlTick LastTick;
   SymbolInfoTick(Symbol(),LastTick);
   MqlDateTime tm;
   TimeToStruct(LastTick.time,tm);
   int MinuteEquivalent=tm.hour*60+tm.min;
   int BorderMinuteStartTrade=HourCorrect(TradeHour)*60+MinuteCorrect(TradeMinute);
   int BorderMinuteEndTrade=HourCorrect(TradeHourEnd)*60+MinuteCorrect(TradeMinuteEnd);
   
   if ( Value > ValueCloseE)
      {
      if ( !bInvert ) CloseBuyF();
      else CloseSellF();
      }
      
   if ( Value < -ValueCloseE)
      {
      if ( !bInvert ) CloseSellF();
      else CloseBuyF();
      }   
   
   if ( !bUseTimeCorridorE )
      {
      if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value > ValueOpenE && Value <= ValueOpenEMax )
         {
         if ( !bInvert ) SellF();
         else BuyF();
         }
      
      if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value < -ValueOpenE && Value >= -ValueOpenEMax )
         {
         if ( !bInvert ) BuyF();
         else SellF();
         }      
      }
   else
      {
      if ( BorderMinuteStartTrade > BorderMinuteEndTrade && bDay() )
         {
         if ( !(MinuteEquivalent>=BorderMinuteEndTrade && MinuteEquivalent<= BorderMinuteStartTrade) )
            {
            if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value > ValueOpenE && Value <= ValueOpenEMax )
               {
               if ( !bInvert ) SellF();
               else BuyF();
               }
      
            if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value < -ValueOpenE && Value >= -ValueOpenEMax )
               {
               if ( !bInvert ) BuyF();
               else SellF();
               }
            }        
         }
      if ( BorderMinuteStartTrade <= BorderMinuteEndTrade && bDay() )
         {
         if ( MinuteEquivalent>=BorderMinuteStartTrade && MinuteEquivalent<= BorderMinuteEndTrade )
            {
            if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value > ValueOpenE && Value <= ValueOpenEMax )
               {
               if ( !bInvert ) SellF();
               else BuyF();
               }
      
            if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToFuture && Value < -ValueOpenE && Value >= -ValueOpenEMax )
               {
               if ( !bInvert ) BuyF();
               else SellF();
               }
            }        
         }      
      }

   if ( bPrintValue ) Print("Value="+DoubleToString(Value));     
   }

Aqui, apenas a lógica de controlar os dias da semana e o intervalo de tempo dentro do dia foi adicionada, todo o resto permaneceu inalterado. A propósito, o período de tempo não precisa estar na faixa de 0-24 horas. O intervalo pode começar num dia e terminar em outro. Ou seja, é possível cruzar o ponto de swap. De acordo com a ideia, as posições podem ser abertas em corredores exclusivos, mas podem ser fechadas a qualquer momento. Pode valer a pena adicionar o fechamento forçado de posições com base no tempo como uma opção separada. Até agora, parece-me que usar essa abordagem deve fornecer robôs mais estáveis, visto que estamos tornando o limite do corredor do tempo mais vago. Isso é feito para reduzir a probabilidade de um resultado acidental, obtendo a confirmação de que o corredor encontrado e sua fórmula não param de funcionar abruptamente, mas desaparecem gradualmente.


Análise de padrões globais

Todos os resultados aqui apresentados foram obtidos com base em treinamento na parcela 2010.01.01-2020.01.01, conforme artigo anterior. Isso foi feito intencionalmente para deixar o ano corrente como um período 'forward' para verificar os resultados das cotações futuras. O período 'forward' foi escolhido de 2020.01 a 2020.12.01.

Eu gostaria de observar um aumento significativo na qualidade dos resultados finais, claro, em detrimento do número de transações, mas, curiosamente, isso só teve um efeito positivo no período 'forward'. Como assumi no último artigo, um aumento na qualidade do teste inicial acarreta um aumento na duração do padrão no período 'forward'. A prova estará abaixo.

Vamos começar com o par de moedas EURCHF H1. A análise anterior mostrou boa previsibilidade deste instrumento, por isso, decidi começar com ele. Consegui criar 3 Expert Advisors com base em resultados de otimização. Mencionarei alguns testes da versão para MetaTrader 4 para mostrar como os indicadores dos padrões encontrados cresceram. Vejamos a primeira opção:

First Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 4

O lote foi fixado em 0,1 durante o teste. Com base no valor esperado obtido durante o teste, verifica-se que ele é de 54 dólares contra os 8 dólares que recebi na versão anterior do programa. O fator de lucro também aumentou significativamente, pelo menos 0,5, e talvez até mais. Lembro que no último artigo foi por volta de 1,14. Este foi o fator de lucro máximo que conseguimos obter. Espero que todos possam ver como os resultados são dramaticamente diferentes, assim que a amostra foi estruturada por dia da semana e horário de trabalho.

Eu gostaria de apontar que este está longe de ser o melhor resultado. Afinal, os testes foram realizados por um tempo muito limitado, devido às especificidades do problema. Tivemos que nos ajustar a um período muito apertado. No total, todos os testes levaram cerca de 2-3 dias de tempo. Os testes foram realizados em 2 núcleos de um processador bastante fraco para os padrões atuais, nem mesmo um processador de servidor. Cada opção levava cerca de 5 a 6 horas aproximadamente, se olharmos mais de perto o processo de localização de padrões.

Mesmo durante o processo de teste, foram encontrados erros no algoritmo do programa, que muitas vezes dava resultados falsos. Claro, já corrigi esses erros, mas isso teve um efeito muito negativo no número de padrões que encontrei. Mesmo assim, esse tempo foi suficiente para que eu encontrasse opções aceitáveis. Agora vamos ver como esse teste fica no MetaTrader 5:

First Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 5

Existem tão poucas transações porque limitei o spread durante o teste para que fosse mais ou menos estável em busca de indicadores de maior lucratividade. Mas isso não é necessário, como a prática tem mostrado. Explicarei o porquê no final do artigo. Apesar do número muito pequeno de transações que restou do teste final, ainda podemos confiar nesses dados, uma vez que há a amostra mais longa por trás deles (percebi quando apliquei a força bruta nos coeficientes da fórmula na primeira guia). Na verdade, na primeira guia, calculamos todas as barras que estão no segmento carregado, por isso, esta é uma base ideal para complemento (otimização). Quando isolamos uma parte dos resultados de uma grande amostra como uma menor, então a força desta amostra é maior, quanto mais dados contém a primeira amostra (ordens).

Agora podemos dar uma olhada no período 'forward':

Future 1 year

Apenas 2 transações em 1 ano, muito poucas, mas o resultado é positivo.

Vejamos a próxima opção, é da mesma parcela que o anterior:

Second Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 4

No MetaTrader 5 sem requisitos para spreads, esta fórmula não é lucrativa, mas se a limitarmos com base na valor esperado obtido, verifica-se que esses sinais contêm alguns bons, embora o gráfico pareça muito distorcido:

Second Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 5

Aparentemente é um gráfico extremamente feio e o que ele pode trazer no futuro? Mas, novamente, há uma grande amostra de base por trás disso, o que dá um tremendo poder a todas as subsequentes, portanto, não há necessidade de temer que a amostra final pareça tão pouco apresentável. No nosso caso, basta que dê lucro. Vamos olhar para o futuro:

Future 1 year

Curiosamente, o resultado é muito bom, embora, novamente, não haja tantas transações. Na verdade, nos últimos anos, tudo isso tem sido mais bem testado devido ao fato de que as corretoras estarem constantemente reduzindo os spreads por meio de novas tecnologias. Uma conclusão muito boa para nós já se sugere no que diz respeito às previsões e seu possível desempenho. Mas até agora há poucos dados para afirmar isso, por enquanto isso é apenas uma indireta. Para confirmar essas conclusões, fiz vários outros testes para diferentes pares de moedas, mas por enquanto vamos olhar para o terceiro robô para este par de moedas.

Também quero dizer que não haverá mais testes para o MetaTrader 4. Duas opções completas, creio eu, serão suficientes para realizar a comparação. Também não vejo sentido em empilhar o artigo com dados desnecessários. Terceira opção:

Third Bot EURCHF H1 2010.01.01-2020.01.01 MetaTrader 5

Em geral, o gráfico parece normal, pelo menos não é feio. Agora, vamos olhar para o futuro:

Future 1 year

Vemos o mesmo panorama. Até agora, todos os períodos 'forward' foram positivos. Claro, pode surgir a ideia de que, uma vez que se trata de três robôs, embora com parâmetros diferentes, do mesmo par de moedas e treinados na mesma parcela, talvez eles descrevam o mesmo padrão, apenas um pouco diferente.

Outro pensamento que pode surgir é que este par de moedas é bom e se comporta da mesma forma o tempo todo. Mesmo assim, não importa para nós 😊. Mas, mesmo assim, isso se deve a razões muito mais gerais. Para provar que o assunto não tem nada a ver nem com o par de moedas e bem com a mesma parcela, vamos agora considerar um par de moedas e um período de tempo diferentes dos do gráfico.

Usamos EURUSD H4

Como eu disse, não vou apresentar os testes com MetaTrader 4, mas os testes neste par de moedas parecem tão suaves e bons quanto no último, apenas fique sabendo isso. Neste período, encontrei 2 robôs diferentes. Vamos começar com o primeiro:

First Bot EURUSD H4 2010.01.01-2020.01.01 MetaTrader 5

O gráfico não tem uma aparência boa, mas se nossas suposições anteriores forem verdadeiras, isso não deve nos incomodar, porque também é apenas uma pequena parte de uma amostra muito grande. Vamos ver o que está por vir:

Future 1 year

A mesma história, o padrão funciona o ano todo. Mesmo se retirarmos a primeira ordem, a maior, se olharmos de perto as demais, podemos entender que mesmo assim teríamos ficado dentro da lucratividade.

Resta consolidar nossas conclusões e ver o que o segundo Expert Advisor nos mostrará:

Second Bot EURUSD H4 2010.01.01-2020.01.01 MetaTrader 5

O gráfico é o mais equilibrado de todos os que já tivemos, nesse aspecto, eu esperava isso no futuro. Vamos verificar nossas suposições:

Future 1 year

Tudo está conforme o esperado. Podemos até ver uma linha reta, embora haja uma grande montanha no início. Até agora, não vimos um único período 'forward' não lucrativo em 5 EAs testados para 2 amostras completamente diferentes. Quanto a mim, esta já é uma estatística muito boa. Mas, pessoalmente, mesmo esses dados não seriam suficientes para mim, portanto, vou mudar para um par de moedas completamente diferente e um período de tempo completamente diferente e fazer uma verificação adicional para finalmente consolidar as conclusões.

Passamos para o EURJPY M5.

EURJPY M5 2010.01.01-2020.01.01 MetaTrader 5

A seção de treinamento parece estranha, há uma reversão acentuada em 2015, mas no geral, é claro, tudo tem uma boa aparência. Vamos dar uma olhada no período 'forward':

Future 1 year

É difícil tirar conclusões disso, mas é claro que esta é a primeira das seções 'forward' que não está dentro de ser lucrativa. No entanto, não acho que este resultado deva ser visto como algo negando a estabilidade de todos os algoritmos que foram gerados usando este software. Digo isso porque tivemos uma reversão acentuada em 2015 no backtest. Não quero que ninguém pense que quero ajustar os resultados do artigo à minha visão do mercado, mas pessoalmente não posso escrever esta situação como uma refutação por causa dessa reversão pronunciada. Antes, vou concluir que está tudo correto, pois a situação se desenrolou em 2015, e isso é apenas uma continuação dessa reversão.

Para não cancelar resultados indesejáveis por algumas razões externas, será necessário fazer algumas modificações no algoritmo para encontrar padrões. A partir da próxima versão, este algoritmo será implementado e, a seguir, possíveis modificações no algoritmo serão descritas.


Tirando conclusões

Acredito que esses testes são suficientes para tirar várias conclusões importantes sobre a pesquisa e o teste de EAs de trabalho nos terminais MetaTrader 4 e MetaTrader 5. A questão é que os testadores de ambos os terminais funcionam de maneira um pouco diferente. Cotações para o MetaTrader 4 armazenam um histórico sem informações sobre spreads, permitindo assim que o usuário defina o spread "1", que é quase igual a "0". Para a esmagadora maioria dos EAs, esse spread não importa, por essa razão, torna-se possível encontrar o início de quaisquer padrões e desenvolvê-los, o que o MetaTrader 5 não fornece. No entanto, as cotações do MetaTrader 5 mantêm seu spread, o que nos permite avaliar a lucratividade real do sistema.

Como minha prática mostrou, se um sistema que foi escrito para MetaTrader 4 também não foi transferido para o quinto terminal, esse sistema tem muito pouca chance de mostrar lucro, porque a maioria dos padrões que podemos encontrar estão dentro do spread, e não têm nenhum uso prático. É verdade que em alguns casos, entre todos os sinais, é possível destacar os sinais que estavam com spreads mínimos e, por isso, pelo menos parte dos sinais permanecerá, mas a experiência mostra que nem sempre é assim.

Muitas vezes, ao diminuir o spread necessário, os sinais só pioram. Neste caso, usei os botões para ajustar os spreads no MetaTrader 5 para testes a fim de obter testes mais ou menos aceitáveis, mas isso leva muito tempo. Essas coisas podem ser feitas automaticamente modificando o programa. Tentarei descrever na figura como todo o processo de busca por um padrão fica agora, até o último estágio, e como podemos automatizar uma busca manual por um spread:

Development Cycle

O diagrama mostra todo o ciclo de desenvolvimento de um novo Expert Advisor, do início ao fim. Preto é o estado atual implementado deste loop usando meu programa. Possíveis modificações e possíveis automações são mostradas em cinza. As melhorias que pretendo introduzir se enquadram em 6 categorias:

  1. Uso de funções matemáticas simples para processar os dados da barra
  2. Adição de mecanismos de variação de lote que aumentam o fator de lucro para robôs que implementam padrões globais
  3. Adição e modificação de mecanismos de martingale e martingale reverso para trabalhar em parcelas extremamente curtas
  4. Adição de um mecanismo para combinar bons robôs com a maior frequência possível de transações
  5. Inclusão de spreads na cotação e automação total de todo o ciclo de desenvolvimento
  6. Correção de erros detectados do otimizador

Os itens numerados 1, 5 e 6 se destacam. A variabilidade das fórmulas usadas para força bruta dará tanto um aumento no número de variantes de EAs que podem ser obtidas a partir de um ciclo de otimização bruta, quanto um aumento na qualidade média dos resultados. Foi notado em artigos anteriores do ciclo por membros do fórum que é possível usar a série Fourier para descrever processos periódicos de mercado. Para ser honesto, eu também queria implementar isso no início, mas decidi que por enquanto vale a pena adiar isso devido à sua complexidade. Mas após pensar um pouco, cheguei à conclusão de que não é tão difícil. Afinal, não precisamos expandir nenhuma função numa série, em vez disso, basta buscar os coeficientes dos termos, da mesma forma que acontece na minha série de Taylor. Além disso, a variabilidade desse método será muito maior do que a da série de Taylor. Ainda uso apenas a primeira potência, porque conforme a potência graus aumenta, a qualidade diminui devido a um aumento desproporcional na complexidade do cálculo. Os spreads também são muito importantes. Por que filtrar sinais manualmente quando você pode fazer isso automaticamente?! Também havia incompatibilidades de tempo de barra, mas esses erros foram eliminados, em sua maioria associados à diferença na funcionalidade dos modelos e na funcionalidade do software.

Em última análise, o objetivo deste software é automatizar todo o processo de desenvolvimento, teste e otimização de assessores para ambas as plataformas, afastando-se da rotina habitual. As alterações que estou fazendo agora no modo manual podem ser facilmente feitas por uma máquina e, claro, muito mais rápido do que eu. Talvez minha qualidade seja superior à de uma máquina, mas no final a máquina ainda se encontrará melhor e mais rápida devido ao seu poder de computação, que nenhuma outra pessoa tem. E, para ser sincero, já sou tão preguiçoso que não quero dar voltas em torno de coisas tão elementares como o tamanho do spread. Parece ser uma ninharia, mas cada uma delas aumenta significativamente a duração do ciclo completo de desenvolvimento do sistema. O processo de desenvolvimento em si não é tão interessante quanto a quantidade e qualidade dos resultados obtidos por unidade de tempo, pois o lucro dependerá disso se quisermos utilizar esses sistemas para negociação. E o tempo sempre está correndo, embora você traga à mente um sistema, ele já pode ser irrelevante nesse momento. A maioria dos Expert Advisors trabalhará por um tempo muito limitado e, a este respeito, é importante fazer tudo com muita rapidez e eficiência. Temos de aproveitar o momento. Ou use o otimizador todo mês, o que nem eu mesmo recomendaria ao meu inimigo.

Talvez, se eu vir o potencial no desenvolvimento posterior da ideia, vou continuar nessa direção. Se a ideia for bem-sucedida, farei um programa de aumento de gradiente semelhante ou simplesmente adicionarei um novo modo na forma do terceiro estágio de análise de dados. A verdade é que o método em si é muito bom como mecanismo de busca de previsão para o problema de aumento de gradiente. Em vez de inventar preditores e testá-los, podemos usar os preditores encontrados por esse método com sucesso. Mas, claro, esta já é uma modificação muito mais séria e profunda do programa, por isso é muito cedo para falar sobre isso. Talvez o tempo me dê a razão. Mas algumas modificações que mencionei nesta lista já foram implementadas e agora estou testando-as e salvando dados para um artigo mais detalhado com os resultados das alterações e exemplos de aplicação. "TO BE CONTINUED...", como dizem.

Este e todos os artigos anteriores desta série focaram no MetaTrader 4, mas como a prática tem mostrado, em tal abordagem, a ênfase deve ser no Meta Trader 5, uma vez que a automação permite que você se afaste da busca inicial por rudimentos de padrões no MetaTrader 4. No próximo artigo, essa abordagem será totalmente implementada e o programa adquirirá uma funcionalidade sem precedentes.

Considerando que o MetaTrader 5 é uma plataforma muito mais progressiva, que passou a registrar histórico real de ticks e spreads, o que permite avaliar a rentabilidade real de qualquer sistema de negociação, é necessário focar nela, mesmo para integração com softwares semelhantes ao meu. Para o desenvolvimento manual de sistemas de negociação, é claro que continuarei a usar as duas plataformas ao mesmo tempo, mas para essa abordagem, a escolha é óbvia.

Durante o processo de teste, foi identificado um fator muito importante que reduz a qualidade dos EAs gerados e a porcentagem deles que podem resistir à seleção natural após testá-los com base em dados reais de tick no testador MetaTrader 5. Este fator é muito importante não apenas para os sistemas que usam qualquer tipo de aprendizado de máquina, mas também para qualquer outro Expert Advisors que foi originalmente criado no MetaTrader 4. É tudo sobre o spread como isso afeta a amostra final de dados para treinamento. Muitos não prestam atenção ao spread, na melhor das hipóteses levam em consideração seu tamanho na hora de negociar, mas ele contém um componente muito invisível, mas muito importante, que tem um efeito muito negativo no processo de aprendizado de máquina. Vou revelar as sutilezas disso no próximo artigo.


Fim do artigo

O mais importante é que o artigo mostra que se você deseja aumentar as chances de desempenho de seu programa, seus robôs de negociação devem ser implementados em MQL5. Afinal, isso permitirá que você realize testes o mais próximo possível da realidade. Inicialmente, embora, ao desenvolver meu software, não gostasse dessa plataforma, uma análise profunda me mostrou que, se eu não fizer testes no MetaTrader 5, irei correr o risco de o meu otimismo ser exagerado.

O artigo mostra que, mesmo com um poder de computação limitado, podemos fornecer resultados usando as fórmulas matemáticas mais simples - em particular, polinômios lineares e polinômios com potências grandes. Criamos uma seção para o uso das funções matemáticas mais simples. Os resultados mostram que uma combinação linear e de potência da função mais simples pode fornecer um excelente sinal para negociação.

Os resultados sugerem que qualquer conjunto de condições lógicas pode ser reduzido a um único indicador quantitativo na forma de uma função. Essencialmente, a fórmula gera um indicador que cria valores simétricos de mais e menos que podem ser usados como sinais de compra ou venda. A fórmula do indicador é sempre diferente e isso garante a variabilidade do método. Acho que muitos traders sonham com um indicador que dirá exatamente quando comprar ou vender. Este método gera esse recurso na medida em que podemos ser ajudados pelo mercado. O próximo artigo promete apresentar resultados muito melhores, e espero que consolide todas as conclusões que foram tiradas ao longo de todo o ciclo. Ele também revelará novas sutilezas que serão úteis tanto para a criação manual de sistemas de negociação quanto para o aprendizado de máquina.

Links

  1. Abordagem de força bruta para encontrar padrões
  2. Força bruta para encontrar padrões (Parte II): Imersão


Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/8661

Arquivos anexados |
Bots.zip (880.06 KB)
Trabalhando com preços na biblioteca DoEasy (Parte 62): atualização em tempo real da série de ticks, preparação para trabalhar com o livro de ofertas Trabalhando com preços na biblioteca DoEasy (Parte 62): atualização em tempo real da série de ticks, preparação para trabalhar com o livro de ofertas
Neste artigo, atualizaremos em tempo real da coleção de dados de ticks e prepararemos a classe do objeto-símbolo para trabalhar com o livro de ofertas, cujo funcionamento abordaremos no próximo artigo.
Redes neurais de maneira fácil (Parte 10): Atenção Multi-Cabeça Redes neurais de maneira fácil (Parte 10): Atenção Multi-Cabeça
Nós já consideramos anteriormente o mecanismo de self-attention (autoatenção) em redes neurais. Na prática, as arquiteturas de rede neural modernas usam várias threads de self-attention paralelas para encontrar várias dependências entre os elementos de uma sequência. Vamos considerar a implementação de tal abordagem e avaliar seu impacto no desempenho geral da rede.
Aplicação prática de redes neurais no trading (Parte 2). Visão computacional Aplicação prática de redes neurais no trading (Parte 2). Visão computacional
O uso da visão computacional permite treinar redes neurais, usando uma representação visual do gráfico de preços e indicadores. Este método nos permite operar mais livremente com todo o conjunto de indicadores técnicos, uma vez que não requer feed digital para a rede neural.
Trabalhando com preços na biblioteca DoEasy (Parte 61): coleção de séries de ticks para símbolos Trabalhando com preços na biblioteca DoEasy (Parte 61): coleção de séries de ticks para símbolos
Visto que diferentes símbolos podem ser usados durante a operação do programa, é necessário criar uma lista própria para cada um deles. Hoje vamos combinar essas listas numa coleção de dados de ticks. Na verdade, irá tratar-se de uma lista normal baseada numa classe de array dinâmico de ponteiros para instâncias da classe CObject e seus herdeiros da Biblioteca Padrão.