Moving Mini-Max: um Novo Indicador para a Análise Técnica e sua Implementação no MQL5
Introdução
Há uma ciência, chamada finança quantitativa que permite estudar os modelos de precificação de derivativos financeiros, utilizando os métodos da física teórica e matemática.
Recentemente me deparei com um artigo que descreve um novo indicador para análise técnica que combina ideias da física quântica e leva-as ao financiamento. Eu tive interesse nele e decidi que iria ensinar como implementar indicadores baseados em artigos científicos em MQL5.
O artigo Moving Mini-Max [2] original é escrito por ZK. Silagadze é um físico quântico do Instituto Budker de Física Nuclear e da Universidade do Estado de Novosibirsk. A ligação para o artigo, bem como o código fonte MQL5 estão disponíveis no final do artigo.
Indicador
Nunca esperei que eu escrevesse essa frase, mas aqui eu vou explicar o tunelamento quântico. Supondo que a maioria dos leitores não sejam profissionais quânticos, irei descrevê-lo em termos simples, espero que você não se sinta ofendido. Em primeiro vamos definir em uma frase a ideia por trás da análise técnica das séries temporais financeiras. Estamos principalmente olhando para encontrar:
- níveis de suporte e resistência dos preços;
- direção das tendências de curto e longo prazo;
- topos e bases das tendências.
A ideia original do indicador Moving Mini-Max é encontrar topos e bases no gráfico usando o análogo da partícula alfa quântica que tenta escapar de um núcleo. O problema é tomado a partir da teoria de desintegração alfa por George Gamov [1].
Uma imagem vale mais do que mil palavras, por isso, estou colando um pequeno gráfico abaixo.
Figura 1. Bola quântica imaginária no gráfico de preço forex
Imagine uma bola lançada a partir do topo da colina ou, no nosso caso, a partir de um topo recente no gráfico das séries temporais. Na mecânica clássica ela irá saltar os obstáculos e pode não ter a chance de parar na frente do obstáculo principal, uma vez que pode se prender em algum lugar no caminho.
Mas, de acordo com a mecânica quântica e a teoria da desintegração alfa, uma bola pode ter uma probabilidade muito pequena, mas diferente de zero, de tunelamento através das barreiras encontrando o seu caminho para o potencial inferior e oscilar lá.
Esta é uma analogia de encontrar um local mínimo na tabela de preços. O artigo por Z.K. Silagadze [2], propõe que, a fim de reduzir a complexidade de cálculo, em vez de resolver o verdadeiro problema de mecânica quântica ele é suficiente para imitar o comportamento quântico. Vou apresentar uma base matemática, que é apresentada no artigo original e, posteriormente, a implementação em MQL5.
Vamos ser uma série de preços para alguma janela de tempo. O Moving Mini-Max é uma transformação não linear das séries de preços:
onde e para é definido como segue:
Como você pode ver esta é uma relação recorrente, isto é, o elemento i-th é dependente do elemento i-1. As séries de moving mini-max satisfazem a condição de normalização, em que a soma de todos os elementos é igual a um
As probabilidades de tunelamento de uma bola quântica são chamadas de probabilidades de transição, porque suas probabilidades modelos de atravessar barreiras estreitas dos obstáculos pequenos imaginários da série de preços descendente:
com
O parâmetro m é uma abertura da janela de uniformização que imita a massa (inversa) da bola quântica e a sua capacidade de passar através de pequenos obstáculos. Alternativamente o moving mini-max d(si) que enfatiza máximos locais pode ser construído colocando o sinal negativo no parâmetro transmitido para a função exp():
Implementação
Depois de ler sobre a matemática por trás do indicador, podemos implementá-lo em MQL5. A fim de fazê-lo da melhor forma é preciso olhar a partir da última equação para cima. Se você prestar atenção as variáveis m e n, você vai ver que este indicador necessita da matriz elemento n+2m da série de preço para uma janela mini-max e terá tamanho lag das barras m.
Isto é por causa do indicador S i+K e S i-k no cálculo das variáveis Q. A variável i é incrementada a partir da 1 para n e k na incrementação a partir da 1 para m, portanto, vamos precisar do buffer n+2 m para começar. Isto pode ser alcançado ligando:
double S[]; ArrayResize(S,n+2*m); CopyClose(Symbol(),0,0,n+2*m,S);
Isso irá declarar matriz de duplas, redimensioná-la para n+2m e copiar valores próximos das últimos barras n+2m da tabela de símbolos atual de partida a partir da última barra.
O próximo passo é calcular valores de Q. Se você ler atentamente a definição você vai ver que para o elemento i-th da série de preços analisados precisamos somar os resultados m da função exp() com as variáveis dos valoresdos preços. Portanto, precisamos fazer um ciclo de 1 a n, que vai contar todos os valores de Q:
void calcQii() { int i,k; for(i=0; i<n; i++) { double sqiip1=0; double sqiim1=0; double dqiip1=0; double dqiim1=0; for(k=0; k<m; k++) { sqiip1 += MathExp(2*(S[m-1+i+k]-S[i])/(S[m-1+i+k]+S[i])); sqiim1 += MathExp(2*(S[m-1+i-k]-S[i])/(S[m-1+i-k]+S[i])); dqiip1 += MathExp(-2*(S[m-1+i+k]-S[i])/(S[m-1+i+k]+S[i])); dqiim1 += MathExp(-2*(S[m-1+i-k]-S[i])/(S[m-1+i-k]+S[i])); } sQiip1[i] = sqiip1; sQiim1[i] = sqiim1; dQiip1[i] = dqiip1; dQiim1[i] = dqiim1; } }
Como você pode observar a função calcQii calcula i-th Q e valores de Q ' para a janela de preço observada de tamanho n. A matriz S contém os valores de preços e sQiip1, sQiim1, dQiip1, dQiim1 são usados como variáveis de cálculos intermediários de Q e Q '.
As probabilidades são calculadas com base em variáveisQ e Q ', portanto, podemos fazer uma outra função que faz um ciclo de 1 a n através das matrizes sQii e dQii:
void calcPii() { int i; for(i=0; i<n; i++) { sPiip1[i] = sQiip1[i] / (sQiip1[i] + sQiim1[i]); sPiim1[i] = sQiim1[i] / (sQiip1[i] + sQiim1[i]); dPiip1[i] = dQiip1[i] / (dQiip1[i] + dQiim1[i]); dPiim1[i] = dQiim1[i] / (dQiip1[i] + dQiim1[i]); } }
O que resta é calcular uSi e elementos sSi posteriores e colocar os resultados nas matrizes USI e DSi
void calcui() { int i; sui[0] = 1; dui[0] = 1; for(i=1; i<n; i++) { sui[i] = (sPiim1[i]/sPiip1[i])*sui[i-1]; dui[i] = (dPiim1[i]/dPiip1[i])*dui[i-1]; } double uSum = 0; double dSum = 0; ArrayInitialize(uSi, 0.0); ArrayInitialize(dSi, 0.0); for(i=0; i<n; i++) { uSum+=sui[i]; dSum+=dui[i]; } for(i=0; i<n; i++) { uSi[n-1-i] = sui[i] / uSum; dSi[n-1-i] = dui[i] / dSum; } }
A fim de verificar se a condição de normalização é válida, pode-se adicionar as seguintes linhas:
double result=0; for(i=0; i<n; i++) { /* Print("i = "+i+" uSi = "+uSi[i]); */ result+=uSi[i]; } Print("Result = "+ DoubleToString(result));
Depois que todos os cálculos foram feitos, precisamos exibi-los dentro da janela do indicador. A fim de fazê-lo, deve-se declarar pelo menos dois buffers indicadores, um para uSi e outro para matriz dSi e definir o tipo de indicador como DRAW_LINE.
#property indicator_separate_window #property indicator_buffers 2 #property indicator_plots 2 #property indicator_type1 DRAW_LINE #property indicator_type2 DRAW_LINE #property indicator_color1 SeaGreen #property indicator_color2 BlueViolet
Então, chamando a função SetIndexBuffer() atribuímos as matrizes uSi e dSi a serem exibidas como INDICATOR_DATA:
SetIndexBuffer(0,uSi,INDICATOR_DATA); SetIndexBuffer(1,dSi,INDICATOR_DATA); PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0); PlotIndexSetInteger(0,PLOT_SHIFT,-(m-1)); PlotIndexSetInteger(1,PLOT_SHIFT,-(m-1));
Figura 2. Indicador Moving Mini-Max Implementado
Uma das possíveis aplicações do indicador descrito no artigo é identificar as linhas de suporte e resistência e a identificação de padrões gráficos por uniformização inerente do indicador. Quanto às linhas de suporte e resistência elas são formadas pelo cruzamento do moving mini-max das séries de preços e moving mini-max de sua média móvel.
Se o preço passa pelo máximo local e cruza a média móvel temos uma resistência. Depois de implementá-lo, vi que o método está sofrendo de alguns sinais falsos, mas estou colando um código fonte de referência sobre como colocar as linhas em MQL5 usando a biblioteca ChartObjectsLines.mqh:
void SR() { // if price goes through local maximum and crosses a moving average draw resistance int i, cnt=0; int rCnt=CopyClose(Symbol(),0,0,n+2*m,S); for (i=n-2; i>=0; i--) if (uSi[i]<uSi_MA[i] && uSi[i+1]>=uSi_MA[i+1]) { Print("Resistance at " + i); CChartObjectHLine *line=new CChartObjectHLine(); line.Create(0, "MiniMaxResistanceLine:"+IntegerToString(cnt), 0, S[i]); line.Color(LightSkyBlue); line.Width(1); line.Background(true); line.Selectable(false); cnt++; } // if price goes through local minimum and crosses a moving average draw support for (i=n-2; i>=0; i--) if (dSi[i]<dSi_MA[i] && dSi[i+1]>=dSi_MA[i+1]) { Print("Support at " + i); CChartObjectHLine *line=new CChartObjectHLine(); line.Create(0, "MiniMaxSupportLine:"+IntegerToString(cnt), 0, S[i]); line.Color(Tomato); line.Width(1); line.Background(true); line.Selectable(false); cnt++; } }
O fato interessante do indicador é que eu vi que ele reconhece muito bem locais mínimos de curta tendência e máximo para uma determinada janela de tempo. é o suficiente para filtrar a diferença entre as maiores e as menores leituras do moving mini-maxes e marcá-las como um início de uma subida de preços de curto prazo ou tendência.
Podemos explorar esse comportamento de acordo com outros indicadores e gestão de dinheiro para fazer um Expert Advisor rentável.
Para marcar as maiores leituras sobre a janela do tempo atual, podemos usar buffers indicadores adicionais para exibir as setas para cima e para baixo cada vez que a diferença for maior. Além disso, para tornar o indicador mais atraente eu decidi usar o novo recurso do MQL5: um histograma de cores. A baixa e alta tendências são coloridas em cores diferentes, e a mudança da tendência é sinalizada por uma barra amarela.
Para utilizar o histograma de cores entre dois buffers devemos usar dois buffers de dados e um buffer para os índices de cor. Por favor, observe como definir planos. Existem cinco buffers indicadores no total, e três cores são definidas para o histograma de cores.
//+------------------------------------------------------------------+ //| MovingMiniMax.mq5 | //| Copyright 2011, Investeo.pl | //| http://Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http://Investeo.pl" #property description "Moving Mini-Max indicator" #property description "proposed by Z.K. Silagadze" #property description "from Budker Institute of Nuclear Physics" #property description "and Novosibirsk State University" #property description "Original paper can be downloaded from:" #property description "http://arxiv.org/abs/0802.0984" #property version "0.6" #property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 3 #property indicator_type1 DRAW_COLOR_HISTOGRAM2 #property indicator_type2 DRAW_ARROW #property indicator_type3 DRAW_ARROW #property indicator_color1 Chartreuse, OrangeRed, Yellow #property indicator_color2 RoyalBlue #property indicator_color3 RoyalBlue #property indicator_width1 5 #property indicator_width2 4 #property indicator_width3 4
Por favor, note que histograma leva dois buffers do tipo INDICATOR_DATA e um INDICATOR_COLOR_INDEX. Os buffers devem ser configurados com precisão na seguinte ordem, os buffers de dados vem em primeiro lugar, depois de que um buffer do índice de cor é definido.
SetIndexBuffer(0,uSi,INDICATOR_DATA); SetIndexBuffer(1,dSi,INDICATOR_DATA); SetIndexBuffer(2,trend,INDICATOR_COLOR_INDEX); SetIndexBuffer(3,upArrows,INDICATOR_DATA); SetIndexBuffer(4,dnArrows,INDICATOR_DATA); PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0); PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0.0); PlotIndexSetInteger(1,PLOT_ARROW,234); PlotIndexSetInteger(2,PLOT_ARROW,233);
Buffers 0,1,2 são para histograma de cores, buffers 3 e 4 são para exibição seta.
O algoritmo de coloração é como se segue:
if (upind<dnind) { for (i=0; i<upind; i++) trend[i]=0; for (i=upind; i<dnind; i++) trend[i]=1; for (i=dnind; i<n; i++) trend[i]=0 ; } else { for (i=0; i<dnind; i++) trend[i]=1; for (i=dnind; i<upind; i++) trend[i]=0; for (i=upind; i<n; i++) trend[i]=1; } trend[upind] = 2; trend[dnind] = 2;
Estou colando a imagem do resultado final:
Figura 3. Versão final do indicador do Moving Mini-Max
é preciso lembrar que os valores de tendência baixa e alta são calculados para uma determinada janela de tempo cada vez que chega uma nova barra, esta é a razão para chamar o indicador moving mini-max.
Embora ele retarde as barras m dá surpreendentemente boa visão para a tendência da janela de tempo atual e interpretação de como o mercado 'respira'.
Estou convencido de que este indicador pode ser rentável.
Conclusão
Eu apresentei a matemática por trás de um novo indicador para a análise técnica e sua implementação em MQL5.
O artigo original por Z.K. Silagadze está disponível em http://arxiv.org/abs/0802.0984. O código fonte em anexo está disponível para download.
Espero apresentar indicadores técnicos mais interessantes e sua implementação MQL5 no futuro.
Referências:
1. G.Gamov, Theory of alpha decay.
2. Z.K. Silagadze, Moving Mini-Max - a new indicator for technical analysis.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/238
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Ethos Trader O código do Moving Mini-Max está funcionado sim, mas deve fazer uma correção a partir da linha 225:
//| ----- Erro: Foi substituido pelas linhas a baixo ----- |
//| double result=0;
//|**** Original: for(i=0; i<n; i++) { Print("i = "+i+" uSi = "+uSi[i]); result+=uSi[i]; }
//| ---------------------------------------------------------- |
double result=0;
for(i=0; i<n; i++) // Desliguei isso --- >> { Print("i = "+(string)i+" uSi = "+(string)uSi[i]); result+=uSi[i]; }
// Desliguei isso --- >> Print("Result = "+DoubleToString(result));
}
Estou testando o indicador e ele aparece para todos os ativos que exceto para o índice, seja cheio, mini ou do contrato corrente. Alguma sugestão sobre o que ocorre ou como devo proceder para que apareça o indicador para o índice?
Obrigado.
Meus parabéns pelo trabalho.
Estou testando o indicador e ele aparece para todos os ativos que exceto para o índice, seja cheio, mini ou do contrato corrente. Alguma sugestão sobre o que ocorre ou como devo proceder para que apareça o indicador para o índice?
Obrigado.