ja_mageia

 

Nossas notícias estão intercaladas com os artigos, ambas na seção de artigos. A maioria das notícias está acessível exclusivamente a cotistas e/ou visitantes registrados. Por favor, dirija-se à seção: Artigos

Início Artigos Só 9,2 quintilhões não é suficiente
Só 9,2 quintilhões não é suficiente Versão para impressão Enviar por E-mail
Artigos - Investimentos
Escrito por Melao   
Segunda, 24 Maio 2010 16:46

O algoritmo genético do Meta Trader 4 possibilita otimizar, de cada vez, até 9,22335 quintilhões de diferentes combinações de valores para os parâmetros. Embora possa parecer um número grande, na verdade é relativamente pequeno. Basta usar 7 parâmetros discretos ou discretizados com 100 valores cada, além de stop loss e take profit, com mais um parâmetro com 10 valores, para exceder esse número.

Há diversas maneiras de se tentar contornar essa limitação, algumas das quais já descrevemos em artigos anteriores. Para testar todos os valores relevantes de um parâmetro entre 1 e 1000, não é preciso testar em passos de 1 em 1. Pode-se testar de 1 em 1 para os valores menores e 20 em 20 quando estiver perto de 1000, já que entre 980 e 1000 a diferença é relativamente pequena, ao passo que entre 1 e 21 seria grande, então se pode logaritmizar os parâmetros antes da otimização, entre outras possibilidades, reduzindo de 1000 para cerca de 20 ou 30 etapas e sem perda sensível na qualidade. Também se pode colocar um parâmetro em função de outro, como nos casos de médias móveis, em que MA1 > MA2, pois em tal caso não faz sentido testar MA1 entre 1 e 30 e MA2 entre 7 e 100, porque nos casos em que MA2 for menor que MA1 a estratégia perde o sentido. Então é mais econômico representar MA2 como k x MA1, em que k pode assumir valores entre 1,2 e 8, por exemplo, variando de 0,2 em 0,2, e com isso se consegue reduzir o número de possibilidades a serem testadas, sem perda sensível de qualidade no resultado. Porém depois de se aplicar vários métodos para conseguir otimizar maior quantidade de informações, vai se tornando cada vez mais difícil não ultrapassar esse limite de 9 quintilhões sem que isso implique perda de qualidade no final. Nos casos descritos acima, ainda se poderia melhorar alguns detalhes, porque quando MA1=1, tanto faz o MA2 ser gerado por k = 1,6, 1,8, 2, 2,2 ou 2,4, pois em todos esses casos o valor de MA2 vai resultar em 2, já que o número de médias não pode assumir valores que não sejam inteiros, portanto há um desperdício com esses vários possíveis inputs repetidos gerando mesmo output, de modo que se pode usar algum tipo de função que evite esse problema, ou uma tabela de valores para k correspondentes quando MA1 é pequeno, porém tanto no uso de uma função menos simples quanto no uso da tabela, se consome recursos de processamento e isso pode causar uma perda de performance na otimização maior do que se deixasse repetir os valores de MA2 para uso de k dentro de alguns intervalos, pois as repetições só ocorreriam para poucos valores muito pequenos de MA1, e acima de MA1=5 já não haveria repetições. Também seria possível, se necessário, mudar o time frame e assim tornar possível usar os valores decimais para períodos das médias móveis, e em vez de 7,5 períodos de MA1 no time frame de 1 hora se poderia usar 15 períodos de 30 minutos, que não é a mesma coisa, mas fica semelhante para alguns propósitos e em alguns casos. Porém entre 1,2 períodos de 1 hora ou 72 períodos de 1 minuto, embora cubra o mesmo intervalo de tempo, a diferença no comportamento desse indicador seria imensa e não faria sentido usar algo assim numa substituição. Muitos detalhes precisam ser levados em conta para “otimizar a otimização”, e nem sempre é fácil perceber se a mudança no método para poupar tempo ou reduzir a quantidade de dados atingirá o objetivo desejado, aliás, algumas vezes é muito difícil e só depois de testar e comparar é que se verifica se realmente houve ganho de performance e nenhuma perda sensível no resultado.

As versões 3.x, 4.x e 5.x operam perto do limite de 9 quintilhões do Meta Trader 4, e no processo de otimização de novas versões, uma das etapas preliminares consiste em verificar os intervalos mais estreitos dentro dos quais cada parâmetro deve ser otimizado sem reduzir significativamente as probabilidades de que os valores ótimos estejam dentro do tal intervalo, e, ao mesmo tempo, usar os passos tão largos quanto possível sem que entre dois passos consecutivos possa haver valores de otimização sensivelmente melhores do que aqueles nos pontos de discretização. Isso costuma envolver várias etapas sucessivas de estreitamentos de intervalos e alargamentos de passos, antes de iniciar a otimização propriamente dita. E muitas vezes é preciso deixar alguns parâmetros para serem otimizados separadamente. Essa escolha dos parâmetros a serem otimizados não-simultaneamente com o grupo principal precisa ser muito criteriosa, caso contrário o valor ótimo obtido isoladamente não será nem sequer próximo ao valor ótimo que seria obtido se todos os parâmetros tivessem sido otimizados em conjunto. Um procedimento básico costuma ser mais ou menos o seguinte: dados os parâmetros A, B, C, D, E, F, G, H, I, J, K que não podem ser otimizados todos juntos por exceder o limite de 9 quintilhões de valores, mas no máximo 7 parâmetros de cada vez, então em lugar de se fazer as otimizações de A, B, C, D, E, F, G numa etapa (depois de avaliar que A, B, C, D, E, F, G são mais significativamente otimizáveis em conjunto do que outro grupo outros 7 parâmetros) e em seguida otimizar os 4 restantes a partir dos valores ótimos para os 7 primeiros, em vez disso se coloca novamente 7 parâmetros na segunda etapa, repetindo 3 da primeira etapa que sejam considerados potencialmente mais inter-relacionados aos 4 restantes. Isso pode ser repetido mais algumas vezes, voltando a usar alguns ou todos os 4 parâmetros que foram usados na primeira etapa e não reutilizados na segunda. Há muito mais detalhes a serem considerados nesse processo, mas resumidamente é isso.

Muito bem, neste domingo colocamos em teste duas novas versões: 4.6 e 3.14159265358979 ou 3.(14), sendo que “.(14)” indica o número de decimais, também representado por 3’14.

A versão 3’14 usa a idéia geral das versões 3.x de operar em tendências, e incorpora algumas idéias das versões 4.x e 5.x para definir com mais precisão os pontos de entrada. Quase poderia ser chamada de versão 6.0, porque é muito diferente das 3.x, porém o esqueleto é muito semelhante ao das versões 3.x. Além disso, não usa alguns dos diferenciais da 5.0, que provavelmente serão mantidos quando futuramente começarmos a trabalhar na 6.0.

A versão 4.6 usa uma mistura das versões 4.07b2, 4.3 e 4.02, que na verdade já são misturas de versões anteriores. Não usa algumas idéias que caracterizam a 5.0, portanto não parece apropriado chamar de 5.1.

As duas novas versões acabaram com uma quantidade de parâmetros que cria dificuldades no processo de otimização, o que levou a formular uma maneira diferente de otimizar para lidar com essa situação. Na essência, é o mesmo método de otimizar por partes, porém a maneira de determinar quais parâmetros serão otimizados em cada etapa muda em alguns aspectos extremamente importantes e fazem muita diferença nesse caso específico, em que pelos métodos usados anteriormente seria necessário um tempo absurdo ou ficaria grande margem para dúvida se os resultados encontrados ficaram próximos aos valores ótimos. Na verdade, com 10^4 soluções entre 10^20 possibilidades sempre é difícil assegurar que os melhores resultados destas 10^4 soluções tenham muito mais que 1% de probabilidade de conter uma das 100 melhores soluções possíveis entre as 10^20 consideradas, porém se pode ter boa segurança de que entre as melhores soluções encontradas, a relação risco/recompensa em comparação ao risco/recompensa da suposta melhor solução possível seja algo entre 1:1 e 2:1, portanto muito razoável. A função dos algoritmos genéticos não é encontrar uma solução exata, nem mesmo encontrar a melhor solução possível. A idéia é explorar um conjunto gigantesco de dados (9.223.350.000.000.000.000 nesse caso) em busca de uma boa solução sem ter que analisar o conjunto inteiro, mas apenas analisando uma amostra selecionada desse conjunto e comparando os resultados dos elementos analisados para decidir quais os próximos elementos que convém analisar em seguida, bem como quais alterações convém buscar ou introduzir nos próximos elementos a serem analisados para que se tenha mais probabilidades de encontrar resultados melhores que os anteriores. Geralmente se analisa apenas 10.496 desse grupo de 9.223.350.000.000.000.000 genótipos, o que representa uma economia de tempo de 99,999999999999886% ou seja, gasta-se “apenas” cerca de 350 horas em vez de 35.000.000.000.000 de anos, que seria 2500 vezes a idade estimada para o Universo com base no modelo do Big-Bang. Mesmo com essa economia imensa de tempo, de 878.750.000.000.000 : 1, a perda de qualidade no processo é de apenas 2 : 1 ou menos, portanto a relação entre economia de tempo e perda de qualidade compensa folgadamente e justifica plenamente o uso de algoritmos genéticos, inclusive porque normalmente as pessoas não estão interessadas em aguardar 2500 vezes o tempo de existência do Universo até que o resultado seja alcançado. Mas ainda é muito 350 horas para uma única otimização. Há meios de se fazer isso em prazos mais curtos, porém com perdas na qualidade do resultado. Desde que as perdas sejam pequenas em comparação à economia de tempo, pode ser um procedimento aceitável.

Se por um lado as duas novas versões apresentam algumas dificuldades para serem otimizadas, por outro elas apresentam importantes pontos positivos:

1) A possibilidade de negociar grandes volumes, realizando operações mais longas e não se mostrando sensíveis a variações no tamanho dos spreads.

2) Possibilidade de operar em time-frame D1, permitindo otimizações desde 1971 em alguns pares e, nesse caso específico, com possibilidade de otimizar mesmo em dados que não contenham informações intraday. A fidedignidade fica baixa quando não se tem dados intradiários, porém não chega a ser alarmante. Vejamos a seguir os resultados comparativos de uma otimização em USDDKK desde 1971 até 2010, comparado década a década:


Podemos constatar que no período de 1971 a 1980 e 1980 a 1990 os resultados são bastante semelhantes, assim como entre 1990 e 2000 se comparados ao período entre 2000 e 2010. A quantidade de operações em cada período é uma das diferenças mais marcantes e não se deve tanto ao fato de não haver dados intradiários, mas sim ao fato de a qualidade dos dados anteriores a 1989 ser bem inferior, dificultando a determinação dos pontos de entrada e perdendo sinais que seriam gerados se os dados estivessem mais completos. É interessante que entre 1990 e 2000, período em que não dispomos de muitos dados intradiários, os resultados sejam semelhantes aos do período de 2000 a 2010, corroborando o que acabamos de dizer.

A performance não é tão extraordinária, mas se considerar que usa mesma configuração entre 1971 e 2010, com cenários muitíssimo diferentes do atual nas décadas passadas, com dados escassos e incompletos, e ainda assim consegue manter excelente estabilidade, isso é muito positivo. O fato de não afundar em 2007 e 2008, com um cenário bastante diferente e com dados precisos, também é muito significativo. Porém a versão 4.6 não consegue resultados tão animadores em dados históricos tão antigos, em parte porque depende de características do Mercado sobre as quais nem sequer temos informações precisas nos dados mais antigos, tornando difícil não apenas otimizar como também avaliar se o resultado da otimização é representativo da performance que teria se tivesse operado em tempo real naquela época. Em contrapartida, a versão 3’14, por operar em tendência, explora uma característica que sempre está presente no Mercado, e já na década de 1970 era explorada com sucesso por Ed. Seykota. No caso da 3’14, até onde podemos avaliar, tudo indica que teria performances semelhantes às observadas no back test, caso tivesse atuado em tempo real entre 1971 e 2010, porém não temos como saber se, exclusivamente com os dados disponíveis naquela época, poderíamos encontrar para os parâmetros os valores que encontramos usando os dados atuais. Usando os dados de 1971 a 1980 não conseguimos encontrar, para os parâmetros, valores que funcionem depois de 1990, mas conseguimos valores que funcionam de 1980 e 1989. Com dados de 1999 a 2001 conseguimos valores para os parâmetros que funcionam bem de 2002 em diante, porém não são valores tão apropriados quanto se a otimização for feita entre 2008 e 2010 e depois rodada em dados antigos. Com otimização entre 2006 e 2010 se consegue valores bons para operar em todo o histórico desde 1971 até 2010. Essa informação é extremamente interessante por diversos motivos, não apenas para essa versão em particular ou essa otimização em particular, mas também pode revelar que para versões que operam em tendências longas, se algumas condições forem atendidas, uma otimização feita entre 2006 e 2010 pode ser quase tão boa quanto uma otimização que incluísse dados desde 1971, pois a variedade de cenários que ocorreu entre 2006 e 2010 cobre a maioria das situações ocorridas entre 1971 e 2010. Isso não se aplica a estratégias que não sejam baseadas em tendências longas, e mesmo para estratégias baseadas em seguir tendência, só são aplicáveis quando determinadas exigências são devidamente preenchidas.

Operar seguindo tendências parece ser mais aplicável a diferentes épocas e a séries históricas com diferentes padrões de qualidade, inclusive com dados incompletos, porque como as operações são mais longas, pequenos erros, distorções e ruídos não afetam tanto o resultado. Mas isso é ilusório em diversos casos. A versão 3.03, por exemplo, apresentou comportamentos muito diferentes da 3’14, não sendo possível ser otimizada em USDDKK entre 1971 e 1999, e mesmo entre 2000 e 2010 não ficou com desempenho similar ao obtido em EURUSD, como no caso da 3’14. Portanto não se trata de propriedades que estejam igualmente presentes em todas as estratégias baseadas em tendências longas.

Por vários motivos, a versão 3’14, em nossa avaliação, supera com certa folga a 3.03 como melhor versão para gestão de grandes volumes e a longo prazo. A 3.03 foi rodada em 30 anos de back test com resultados próximos a 20% ao ano, com 6 anos negativos nesse período e máximo drawdown 38%. A 3’14 foi rodada em quase 40 anos de back test com resultados próximos a 37% ao ano, com 5 anos negativos nesse período (nenhum ano negativo desde 1989) e máximo drawdown 35% (sendo este máximo drawdown anterior a 1989).

A otimização da 3’14 num par relativamente exótico, como USDDKK não é por acaso. A Olsendata usa históricos de Coroa Dinamarquesa para completar cotações de EURUSD anteriores à época em que ainda não existia euro, portanto um bom funcionamento em USDDKK equivale a prolongar o histórico de EURUSD. A versão 3’14 também foi otimizada (preliminarmente, ainda) em EURUSD com média anual de 42% desde 1999.

A 4.6 é bastante semelhante à 4.07b2, reforçando principalmente os fatores relevantes para realizar operações mais longas, menos sensíveis ao tamanho do spread e viabilizando gestão de maiores volumes. Por enquanto, tem se mostrado superior à 4.07b2 quando otimizadas em time frame de 1 dia, porém ainda não é tão boa quanto à 4.07b2 em time frame de 1 hora. Uma das vantagens importantes de usar time frame de 1 dia é que permite, em alguns casos, ser testada num histórico mais longo. Outra vantagem é que permite otimização mais rápida para operações longas, já que uma média móvel de 40 dias precisaria de 960 horas e envolveria cálculos 24 vezes mais lentos. Uma desvantagem é que como a maioria das divisas (aliás, a maioria de todos os instrumentos financeiros) não tem todas as principais propriedades de fractais, em particular a auto-similaridade, por isso a mudança de time frame pode implicar mudança nas propriedades gerais da cotação da divisa, ativo, derivativo, índice etc., assim um método que pode funcionar bem com time frame de 1 hora, algumas vezes deixa de funcionar em time frames mais curtos, como de 1 ou 5 minutos, bem como em time frames mais longos, como de 1 dia. Sempre que se muda de tim frame é importante ter em mente que o Mercado é pseudofractal, não é um fractal genuíno. Nesse caso, tanto as versões 4.02, 4.07b2, 4.3 e 4.6 parecem se sair bem melhor em time frame de 1 hora ou mesmo de 15 minutos, do que em time frame de 1 dia, isso desde não ocorram anomalias com candles gigantes. Quando essas anomalias acontecem, em alguns casos o uso de time frame de 1 dia se torna mais apropriado. A 4.6 é, por enquanto, a que se mostra mais eficiente para operar com time frame de 1 dia, e se por um lado isso implica redução na performance, por outro implica mais robustez a candles gigantes, já que todos os parâmetros associados aos tamanhos dos movimentos assumem valores maiores.

Ainda não temos dados suficientes para saber se a 4.6 oferecerá alguma vantagem em comparação às melhores versões 4.x já testadas, mas a 3’14 parece ser claramente melhor que a 3.03 para gestão de grandes volumes, e talvez melhor também que a 3.1415926c. Após otimizar melhor a 3’14, colocaremos duas contas comparativas para testar 3’14 e 3.1415926c. Na verdade, esse tipo de comparação é mais um “jogo”, um entretenimento, já que as comparações mais informativas e úteis são feitas em back tests, com maior quantidade de dados, com controle sobre diversas variáveis que podem ser alteradas para conferir diferentes propriedades de cada uma ao longo do teste, períodos mais longos etc. A utilidade dos testes em tempo real é comparar a similaridade entre back test e tempo real para uma determinada versão e configuração. Serve para conferir se os pontos de entrada e saída estão semelhantes, se as diferenças de spread no mercado real em relação aos do back test estão gerando disparidades, se os eventuais atrasos e interrupções na conexão, adulterações de brokers (se houver) entre outros fatores, se chegam a afetar ou não os resultados, em comparação ao que foi testado. Os testes em tempo real não servem para validar uma versão, porque são muito curtos e sem nenhum controle sobre as variáveis. Os testes em tempo real servem para validar os back tests, e são os back tests que servem para validar as versões.