![Examinemos na prática o método adaptativo de acompanhamento do mercado](https://c.mql5.com/i/articles/overlay.png)
Examinemos na prática o método adaptativo de acompanhamento do mercado
Introdução
Este artigo apresenta uma estratégia de negociação que foi descrita pela primeira vez por Vladimir Kravchuk na revista rusa Especulador de moedas [Валютный спекулянт] em 2001 e 2002. O sistema é baseado no uso de filtros digitais e na avaliação espectral de séries temporais (cronológicas) discretas.
O gráfico real contendo as mudanças nas cotações pode ter uma forma arbitrária. Em matemática, tais funções são chamadas de não-analíticas. No entanto, o famoso teorema de Fourier diz que qualquer função num intervalo de tempo finito pode ser representada pela soma infinita de funções senoidais. Portanto, quaisquer sinais temporais podem ser representados exclusivamente por funções de frequência, que são chamadas seus espectros de frequência.
Para os sinais de não-aleatórios, a transição a partir da descrição temporal para a de frequência (isto é, o cálculo do espectro de frequências) é realizada por meio de uma transformada de Fourier. Os processos aleatórios são apresentados pela densidade espectral do processo, que é a transformada de Fourier da sua função de autocorrelação.
1. Aspectos teóricos da estratégia
A filtragem é a mudança no espectro de frequencia do sinal para a direção certa. Tal transformação pode aumentar ou diminuir as componentes frequenciais num intervalo específico, suprimir ou isolar qualquer uma delas. O filtro digital é um sistema digital para transformar sinais, definidos apenas em momentos discretos.
Há certos aspectos importantes ao trabalhar com filtros digitais e séries temporais discretas.
Em primeiro lugar, a maioria das ferramentas técnicas mais populares (MA, RSI, Momentum, Stochastic, etc.) são baseadas nas alterações no espectro de frequência do sinal e, portanto, são filtros digitais. O ganho de sua função de transferência depende da frequência. Porém poucas pessoas refletem sobre essa função de transferência. É por isso que a maioria dos usuários não sabem em qual direção muda o espectro de frequência do sinal e, portanto, não entendem a natureza do impacto do indicador sobre o sinal. isso complica a configuração do indicador e o modo de tratar os sinais.
Em segundo lugar, o movimento das cotações sempre aparece como um sinal discreto, cujas propriedades gerais devem ser levadas em conta no desenvolvimento de indicadores técnicos. Assim, por exemplo, o espectro do sinal discreto é sempre uma função periódica. Se essa propriedade é ignorada, você pode obter uma distorção da série temporal de entrada .
Em terceiro lugar, a densidade espectral dos movimentos de preços é bem desigual entre os mercados. Neste caso, o melhor para o usuário é configurar os parâmetros dos indicadores, ou seja, ele deve selecionar parâmetros arbitrários e testar sua viabilidade na prática.
Às vezes acontece que um indicador já otimizado (ou EA) que vem tendo boa reputação mostra resultados pobres hoje. Isto tem a ver com a série temporal não-estacionária. Na prática, quando se comparam as duas estimativas, calculadas em diferentes timeframes para um só mercado, muda a forma da amplitude dos picos espectrais. Isto pode ser interpretado como uma manifestação do efeito Doppler, quando a fonte de uma onda harmônica se move em relação a um receptor, ela muda seu comprimento. Isso mais uma vez prova a existência do movimento de tendência no mercado.
O objetivo do método adaptativo de acompanhamento do mercado consiste em encontrar as ferramentas técnicas mínimas que criem um algoritmo de negociação com um rendimento máximo, mas com o mínimo risco. Para isso, são realizadas várias etapas.
- Estuda-se a composição espectral das flutuações de preços para um mercado particular.
- De maneira adaptativa são configurados os filtros digitais não-recursivos. O resultado deste procedimento é um conjunto de respostas ao impulso otimizadas.
- Filtra-se a série temporal de entrada, e é definido o conjunto de indicadores discutidos mais adiante neste artigo.
- Desenvolve-se o algoritmo de negociação.
1.1. Selecionando o método de análise espectral
O desenvolvimento de um sistema de negociação de acordo com o método adaptativo de acompanhamento do mercado começa com o estudo do espectro do movimento do preço de um certo instrumento. É óbvio que a eficiência final de todo o sistema depende dos resultados desta fase.
Pareceria que a solução se consegue por si só, isto é, é necessário realizar uma análise espectral ou harmônica. Mas qual o método a escolher? Hoje, existem duas classes de métodos de análise espectral principais, isto é, paramétricos e não paramétricos.
Métodos de análise espectral paramétricos são práticas, em que é definido um certo modelo de densidade espectral e são avaliados seus parâmetros com base nos resultados da observação do processo correspondente num período limitado. Além disso, o modelo original pode ter o mais diverso aspecto.
Em particular, o modelo inicial pode ser a densidade espectral da série temporal como uma função racional. Em tal caso, é possível distinguir o modelo autorregressivo, o modelo de média móvel e o modelo autorregressivo de média móvel. Consequentemente, na avaliação dos parâmetros do modelo, serão utilizados diferentes abordagens metodológicas.
Além disso, para resolver este problema, podemos usar o princípio variacional e o correspondente recurso de avaliação da qualidade. Aqui, os multiplicadores de Lagrange realizarão o papel de parâmetros avaliados. Tal método é utilizado na avaliação da densidade espectral de acordo com o método da máxima entropia, onde é necessário maximizar a entropia do processo segundo os valores individuais conhecidos da função de correlação.
Métodos não paramétricos de análise espectral, ao contrário dos paramétricos, não conta com modelos pré-definidos. Entre eles, o método mais popular é aquele em que na fase inicial do processo é determinada a periodicidade do processo, isto é, o módulo quadrado da transformada de Fourier. Depois disso, o problema se resume à escolha da janela adequada que satisfará certos requisitos.
O método de Blackman-Tukey também é amplamente utilizado, nele, para a série temporal examinada, encontra-se a transformada de Fourier da estimativa ponderada da sequência de correlação.
Outra abordagem consiste em reduzir a avaliação da densidade espectral da série temporal à solução de uma equação integral fundamental, que descreve a transformada de Fourier da série temporal estudada por meio de um processo aleatório com incrementos ortogonais.
O autor do sistema de negociação proposto acredita que é impossível avaliar qualitativamente a densidade espectral das flutuações nas cotações usando métodos clássicos não paramétricos de estimação espectral baseados no cálculo da transformada discreta de Fourier das séries temporais. A única solução é utilizar métodos paramétricos de análise espectral, que são capazes de obter uma avaliação consistente da densidade espectral em relação à amostra de tempo discreta, em que o processo já é estacionário (ele também se pode tornar estacionário excluindo a tendência linear). Entre a variedade de métodos paramétricos de estimação espectral, talvez, aquele que merece mais atenção é o método de máxima entropia.
1.2. Ferramentas de análise técnica usadas
A principal diferença da estratégia apresenta está na linha de tendência adaptativa. Sua direção é o indicador de direção da tendência atual.
Linha de tendência adaptativa é uma componente de baixa frequência da série temporal de entrada. Ela é obtida graças ao filtro passa-baixo. Quanto menor a frequência de corte fc do filtro passa-baixo, mais ajustada é a linha de tendência.
Entre os pontos da linha de tendência adaptativa existe uma ligação interna, cuja força é inversamente proporcional à distância entre eles. Não há ligação apenas entre os valores dos pontos, cuja distância entre eles é igual ou superior ao assim chamado intervalo de Nyquist TN=1/(2 fc). Por conseguinte, com a diminuição da frequência de corte do filtro esta ligação aumenta e o ponto de inversão de tendência se afasta.
Para determinar a tendência do sistema de negociação, usam-se duas linhas de tendência adaptativas com diferentes períodos.
FATL (Fast Adaptive Trend Line) é a linha de tendência adaptativa rápida. Para sua plotagem, é necessário o filtro passa-baixo. Ele suprime o ruído de alta frequência e os ciclos de mercado com um período muito curto de oscilação.
SATL (Slow Adaptive Trend Line) é a linha de tendência adaptativa lenta. Para sua plotagem, é necessário o filtro passa-baixo 2. Ao contrário do filtro passa-baixo 1, ele transmite ciclos de mercado com um longo período de oscilação.
Os parâmetros do filtro descrito acima (frequência de corte fc e atenuação σ na banda de rejeição) são calculados a partir das estimativas de espectro do nosso instrumento de interesse. Filtro passa-baixo 1 e filtro passa-baixo 2 fornecem atenuação na banda de rejeição não inferior a 40 dB. Seu uso é não tem nenhum efeito sobre a amplitude e a fase do sinal de entrada na banda de passagem. Esta propriedade dos filtros digitais fornece supressão de ruído eficaz e, em comparação com o MA simples, produz menos alarmes falsos.
Do ponto de vista matemático, o valor FATL(k) é o valor esperado do preço Close(k), onde k é o número do dia de negociação.
RFTL (Reference Fast Trend Line) e RSTL (Reference Slow Trend Line) são as linhas de referência rápida e lenta. Eles envolvem os valores emitidos pelos filtros digitais passa-baixo 1 e 2 em resposta ao sinal de entrada, e tomados com um atraso igual ao intervalo de Nyquist correspondente.
FTLM (Fast Trend Line Momentum) e STLM (Slow Trend Line Momentum) mostram os deslocamentos do FATL e do SATL. São calculados da mesma forma como o indicador Momentum, mas, em vez de preços de fechamento, são utilizadas linhas de tendência ajustadas por filtragem. Como resultado, as linhas são mais suaves e mais regulares do que estamos acostumados a ver no Momentum.
As linhas FTLM e STLM são calculadas de acordo com as regras da matemática discreta. Esta é a diferença entre dois pontos adjacentes e independentes, limitados pela banda do processo. No cálculo convencional do Momentum, estas exigência são, muitas vezes, menosprezadas, levando a distorções fatais no espectro do sinal de entrada.
RBCI (Range Bound Channel Index) é o índice de canal, limitado em largura de banda. É calculado pelo filtro de banda, que inclui as seguintes tarefas:
- exclusão da tendência de baixa frequência, formada a partir das componentes espectrais de baixa frequência com períodos maiores do que T2 = 1/fc2;
- remoção de ruído de alta frequência gerado a partir dos componentes espectrais de alta frequência com períodos mais pequenas do que o T1 = 1/fc1.
Períodos Т1 e Т2 são selecionados de modo a satisfazer a condição Т2 > T1. Ao mesmo tempo, as frequências de corte fc1 e fc2 devem ser tais que todos os ciclos de mercado dominantes caiam em consideração.
Simplesmente, RBCI(k) = FATL(k) - SATL(k). De fato, quando o RBCI se aproxima de seus extremos locais, os preços se aproximam da borda superior ou inferior do canal de negociação (dependendo se é um valor máximo ou mínimo, respectivamente).
PCCI (Perfect Commodity Channel Index) é o índice de canal de mercadorias perfeito. A fórmula para seu cálculo é PCCI(k) = close(k) – FATL(k).
Seu método de cálculo é semelhante ao cálculo do índice de canal de mercadorias CCI. De fato, o CCI é a diferença normalizada entre o preço atual e a sua média móvel, enquanto o PCCI é a diferença entre o preço de fechamento do dia e sua expectativa matemática (que, como vimos acima, é feita a partir dos valores do FATL).
Assim, o índice PCCI é uma componente de alta frequência de flutuações de cotações, normalizada pelo seu desvio padrão.
1.3. Regras de Interpretação para os sinais dos indicadores.
Especificamos os princípios básicos do sistema de negociação.
- O sistema pertence aos de tendência, com negociação de acordo com a tendência. A tendência identificada usando o SATL.
- Pontos de entrada são determinados de acordo com as características dinâmicas das tendências rápida e lenta FTLM e STLM.
- O cálculo envolve as atuais condições de mercado (neutralidade, sobrecompra, sobrevenda, extremos locais), que são determinadas pelo índice RBCI.
- A direção da entrada no mercado é determinada pelos indicadores de tendência. Você pode fazer isso usando osciladores só se houver fase de correção.
- A colocação de ordens stop é obrigatória (nos índices RBCI, PCCI e volatilidade do mercado).
Os instrumentos acima referidos devem ser interpretados segundo as regras a seguir.
- Se a linha do SATL aponta para cima, o mercado se encontra numa tendência ascendente, se aponta para baixo, descendente. O surgimento de extremos locais indica que a tendência começa a se manifestar. O cruzamento com o RSTL é um indício de que a tendência se desenrolou completamente. Ao acontecer isso, o STML muda de caractere.
- O fato da linha do SATL ser horizontal ou quase horizontal indica que existe uma fase de correção no mercado.
- STLM é positivo para a tendência de alta é negativo, para a de baixa. Ele é considerado como um dos principais indicadores. Seus extremos locais sempre anunciam o surgimento dos respectivos extremos do SATL. O valor absoluto do STLM é diretamente proporcional à força da tendência. O fato de o STLM e SATL se moverem na mesma direção indica que a tendência se torna mais forte. A existência de várias tendências prova o enfraquecimento da tendência. A linha horizontal do STLM indica que a tendência se formou definitivamente.
- Se as linhas de tendência rápida e lenta (FATL e SATL) estão na mesma direção, a força da tendência é alta. Caso contrário, mercado está consolidado ou na etapa de correção.
- O fato de as linhas do FATL e SATL começarem ir na mesma direção significa que a tendência se desenrolou. Se a direção se junta reiteradamente após ir em várias direções, a correção do mercado acaba, e as cotações começam a se moverem na direção do SATL.
A partir dessas regras, formulamos os sinais de negociação principais.
- В начале долгосрочного тренда появляется надежный разворотный сигнал: o fato de o STLM cair indica a convergência entre a linha de tendência lenta adaptativa e a de suporte (SATL e RSTL). Durante a formação do sinal, aumenta a volatilidade dos preços agudamente. Isso é um sinal de que é a hora da mudança de tendência. Por isso, ao escolher o ponto de abertura da transação, é necessário ter em conta o PCCI. Quando o sinal é de baixa, venderemos, se, para o fechamento, o último candle do oscilador PCCI se encontrar acima do nível de -100. Se o o PCCI estiver abaixo do nível de -100, não abriremos a transação, mas sim esperaremos o oscilador ultrapassar este patamar.
- O próximo sinal indica a continuação da tendência fortalecida e formada depois de uma breve correção. Volatilidade neste caso, como regra, é mais fraca do que durante a inversão de tendência. Portanto, as condições para a formação do sinal são mais rigorosas e, ao mesmo tempo, o próprio sinal é mais robusto.
Negociamos, se os indicadores FATL, FTLM e RBCI se deslocarem de foma síncrona. Sinais falsos são filtrados pelo indicador STLM (seu valor absoluto aumenta ou mantem-se inalterado). O fato de o STLM diminuir anuncia a aproximação entre o SATL e o RSTL. Ao acontecer isso, imediatamente após surgir o sinal de baixa do RBCI, verifica-se se o mercado está sobrevendido. Escolhe-se o preço de entrada no mercado que seja igual ou melhor em relação ao preço Open da seguinte barra após a chegada do sinal.
- Este sinal é baseado na quantidade de ciclos ativos numa banda de frequências, especificada pelo índice RBCI. Não são levados em conta nem a direção da linha do STLM nem como o SATL converge/diverge com o RSTL. A única coisa importante é se o valor do STLM é positivo ou negativo, o que indicaria a direção da tendência principal, formada no mercado. Filtro adicional: direção e comportamento da linha do FATL.
A geração do sinal acorre quado, durante uma tendência de longo prazo neutra ou descendente, o ciclo de onda composto alcança o máximo local na zona de sobrecompra forte. Durante a fase de correção, o potencial do movimento proveniente dos ciclos de mercado será superior ao potencial do movimento devido à volatilidade. Se a tendência é formada, o potencial do movimento - com base nos ciclos de mercado - surge com o potencial da tendência de longo prazo.
Escolhe-se uma abertura da transação que seja igual ou melhor em relação ao preço Open da seguinte barra após a chegada do sinal.
- A base do sinal consiste em duas divergências, isto é, entre as direções do RBCI e a linha do FATL, bem como entre os índices RBCI e FTLM. Se, durante certo período, o FATL e os índices RBCI e FTLM se deslocarem em diferentes direções, nós voltaremos para a fase de espera. O sinal de baixa consta do mínimo do FTLM, quando o FATL e o RBCI não mudam de direção. No gráfico, isto parece um "aceno" do FTLM na direção do FATL.
Na maioria das vezes, vemos o sinal perto do ponto final da tendência de queda rápida (valor do FTLM próximo de 0). O sistema gera um sinal bastante preciso para um movimento de tendência curto.
Isso é um o sinal importante que antecede à inversão da tendência.
Escolhe-se o preço de entrada no mercado que seja igual ou melhor em relação ao preço Open da seguinte barra após a chegada do sinal.
- O siinal é gerado durante uma tendência longa. Os índices RBCI e PCCI atingem os valores de sobrevenda do mercado simultaneamente (para uma tendência de baixa). Geralmente, tais sinais são formados na última fase da tendência, quando as cotações de repente pulam na direção oposta e, depois, novamente "arrebentam" no sentido da tendência principal, que ainda está forte.
Escolhe-se o preço de entrada no mercado que seja igual ou melhor em relação ao preço Open da seguinte barra após a chegada do sinal.
- Na formação da tendência de baixa de longo prazo (SATL cai, mas STLM ainda se mantem positivo), o índice PCCI alcança um valor superior a 100 (zona sobrevenda do mercado). O sinal de reversão é baseado no uso de alta volatilidade do mercado no momento da formação da tendência.
Escolhe-se o preço de entrada no mercado que seja igual ou melhor em relação ao preço Open da seguinte barra após a chegada do sinal.
- Um forte sinal de uma inversão de tendência é observado após a primeira correção técnica para cima, depois de que a linha do FATL é quebrada pela linha do SATL de cima para baixo. Após isso, vendemos. O máximo local do FATL é um indicio de que esta correção técnica é concluída.
O preço de venda é superior ou igual ao preço de abertura do seguinte candle após a chegada do sinal.
- E, finalmente, mais um sinal de reversão é formado quando dois cruzamentos ocorrem simultaneamente, isto é, entre as linhas adaptativas rápida e lenta do FATL, bem como entre o FATL e o RFTL (se houver o rompimento para baixo, vendemos, se a quebra for para cima, compramos). Este sinal marca o a fratura violenta da tendência anterior que já está enfraquecida. O preço de venda é superior ou igual ao preço de abertura do seguinte candle após a chegada do sinal.
2. Construímos os filtros passa-baixos
Agora que já foram estabelecidos os principais aspectos da estratégia, é hora de abordar a parte prática do trabalho. E, claro, vamos começar o trabalho com a construção do filtro de baixa frequência, porque é desses filtros são a base da estratégia.
Para construirmos o filtro passa-baixos, precisamos definir seus principais parâmetros: частотой среза и затуханием. O autor da estratégia indica claramente que o filtro deve fornecer atenuação na banda de latência de pelo menos 40 dB, é por isso que, para definir a frequência de corte, necessitamos realizar uma análise espectral dos dados de preços do instrumento.
Como mencionado acima, a estimativa da densidade espectral foi levada a cabo pelo autor utilizando o método da máxima entropia. Este método se aplica aos paramétricos e é realizado por um modelo matemático. O modelo matemático será construído pelo método de auto-regressão.
2.1. Análise da densidade espectral.
Para estimar a densidade espectral, criaremos a classe CSpertrum (o código completo pode ser encontrado em anexo). Ao inicializar a classe, nós transferiremos o nome do instrumento, o timeframe de trabalho e o número de barras para análise.
class CSpectrum { private: int ci_HistoryBars; //Bars for analysis string cs_Symbol; //Symbol ENUM_TIMEFRAMES ce_Timeframe; //Timeframe double cda_AR[]; //Autoregression coefficients int ci_NumberCoeffs; //Number of coefficients public: CSpectrum(int bars=2880, string symbol=NULL, ENUM_TIMEFRAMES period=PERIOD_CURRENT); ~CSpectrum(); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CSpectrum::CSpectrum(int bars=2880, string symbol=NULL, ENUM_TIMEFRAMES period=PERIOD_CURRENT) { ci_HistoryBars = bars; cs_Symbol = (symbol==NULL ? _Symbol : symbol); ce_Timeframe = period; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CSpectrum::~CSpectrum() { }
Realizamos o cálculo das funções de auto-regressão e densidade espectral pelo procedimento proposto por Victor. Aqueles que desejam se familiarizar com o algoritmo podem ler este artigo. O resultado da análise espectral da área é uma matriz de dados, que, para maior clareza, pode se representada como um gráfico.
Aumentos esporádicos no gráfico mostram o aumento na potência do sinal a uma certa frequência. Precisamos encontrar esses aumentos para determinar as respostas em frequência de nossos filtros. Para fazer isso, à nossa classe CSpecrum adicionamos a função public GetPeriods, que, quando soliditado, retorna os períodos FATL e SATL.
Dentro da função, determinaremos os aumentos como fractais. Para o período do filtro SATL, determinamos o primeiro aumento, que exibe os impulsos com frequência mais baixa. Para o FATL encontramos o impulso com maior frequência e uma potência superior a -40 dB, após eliminar os impulsos de ruído com uma pequena amplitude e alta frequência. Se a função não encontrar períodos para ambos os filtros, ela retornará false.
bool CSpectrum::GetPeriods(int &FAT,int &SAT) { if(!Spectrum()) return false; FAT=SAT=0; int total=ArraySize(cad_Spectr)-1; for(int i=1;(i<total);i++) { int temp=2*(total+1)/i; if(cad_Spectr[i]==0 || temp>(int)ci_HistoryBars/4) continue; if((cad_Spectr[i]-cad_Spectr[i+1])>=0 && (cad_Spectr[i]-cad_Spectr[i-1])>0) { if(SAT==0) SAT=temp; else { if(cad_Spectr[i]<-40) { if(FAT==0) FAT=temp; break; } if(temp>=20) FAT=temp; } } } if(SAT==0 || FAT==0) return false; return true; }
2.2. Cálculo dos coeficientes filtro passa-baixo.
Como já definimos as frequências dos filtros, é hora de construir nossos filtros passa-baixos. Está é a fórmula geral do filtro digital
Onde y é a saída do filtro; x é a matriz de dados de origem; hk são as respostas ao impulso; N é o número de respostas ao impulso.
Dados de preços são usados como valores iniciais, enquanto nós definimos o número de respostas ao impulso igual ao intervalo de Nyquist. Além disso, temos de calcular as respostas ao impulso. Respostas ao impulso ideais para o filtro passa-baixo podem ser calculadas de acordo com a fórmula
Onde fc e wc são a frequência de corte.
Infelizmente, nosso mundo está longe de ser ideal. Por isso, precisamos de uma resposta ao impulso real. Para seu cálculo precisamos da função de peso w(n). Existem várias funções-peso. Eu costumo usar a função Blackman que tem a forma
Onde N é o número de elementos do filtro.
Para obter uma resposta ao impulso real, é necessário multiplicar a resposta ao impulso ideal com a função-peso correspondente
Agora que já temos definidas as fórmulas de cálculo, criamos a classe CFLF, nela calcularemos as respostas ao impulso e filtraremos os dados recebidos. Para calcular o coeficiente das respostas ao impulso, criamos a função public CalcImpulses, para a qual transferimos o período de filtragem. Em diante, o algoritmo da função repete as fórmulas mencionadas acima. Em seguida, normalizamos as respostas ao impulso, levando-as à quantidade de "1".
bool CFLF::CalcImpulses(int period) { if(period<20) return false; int N=(int)(period/2); if(ArraySize(cda_H)!=N) if(ArrayResize(cda_H,N)<N) return false; double H_id[],W[]; if(ArrayResize(H_id,N)<N || ArrayResize(W,N)<N) return false; cd_Fs=1/(double)period; for (int i=0;i<N;i++) { if (i==0) H_id[i] = 2*M_PI*cd_Fs; else H_id[i] = MathSin(2*M_PI*cd_Fs*i )/(M_PI*i); W[i] = 0.42 - 0.5 * MathCos((2*M_PI*i) /( N-1)) + 0.08 * MathCos((4*M_PI*i) /( N-1)); cda_H[i] = H_id[i] * W[i]; } //Normalization double SUM=MathSum(cda_H); if(SUM==QNaN || SUM==0) return false; for (int i=0; i<N; i++) cda_H[i]/=SUM; //summ of coefficients equal 1 //--- return true; }
2.3. Cálculo dos indicadores FATL, SATL, RTFL,RSTL.
Assim que recebermos as respostas ao impulso, podemos avançar para o cálculo dos valores dos indicadores utilizados. Será conveniente obter o valor dos indicadores FATL, SATL, RFTL e RSTL diretamente da classe do filtro.
Como vamos usar diferentes instâncias da classe para os filtros rápido e lento, só temos que criar na classe as funções AdaptiveTrendLine e ReferenceTrendLine. Vamos transferir para as funções o instrumento, timeframe e deslocamento usados em relação ao candle atual. As funções retornarão o valor filtrado.
Deve-se reparar que a função ReferenceTrendLine é substancialmente semelhante à AdaptiveTrendLine. A diferença é que a ReferenceTrendLine é calculada com deslocamento para o período da amostragem de Nyquist. Portanto, na ReferenceTrendLine, calculamos o período de Nyquist e chamamos a função AdaptiveTrendLine, indicando o deslocamento necessário em relação à barra atual.
double CFLF::AdaptiveTrendLine(string symbol=NULL,ENUM_TIMEFRAMES timeframe=0,int shift=1) { string symb=(symbol==NULL ? _Symbol : symbol); int bars=ArraySize(cda_H); double values[]; if(CopyClose(symb,timeframe,shift,bars,values)<=0) return QNaN; double mean=MathMean(values); double result=0; for(int i=0;i<bars;i++) result+=cda_H[i]*(values[bars-i-1]-mean); result+=mean; return result; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CFLF::ReferenceTrendLine(string symbol=NULL,ENUM_TIMEFRAMES timeframe=0,int shift=1) { shift+=(int)(1/(2*cd_Fs)); return AdaptiveTrendLine(symbol,timeframe,shift); }
Os restantes indicadores utilizados são derivados a partir dos valores obtidos e serão calculados e abaixo.
3. Criamos o módulo de sinais de negociação para o gerador de experts MQL5
Hoje resolvi me afastar um pouco da escrita do EA de costume para refrescar a memória sobre a existência do assistente de geração de Experts MT5. Esse recurso útil é uma espécie de construtor, no qual é montado o EA a partir dos módulos anteriormente preparados. Isso permite criar facilmente um novo Expert Advisor, acrescentando novas funções ou removendo as não utilizadas. Por isso, sugiro colocar o algoritmo para tomada de decisões de nosso EA num módulo desse tipo. Já mais de uma vez foi discutido em detalhes este método nos artigos neste site [4], [5]. Por isso neste artigo vou me concentrar apenas no pontos relacionados com nossa estratégia.
Comecemos pela criação da classe de sinal CSignalATCF com base na classe CExpertSignal e conectemos a ela nossas classes criadas mais cedo.
class CSignalATCF : public CExpertSignal { private: CSpectrum *Spectrum; //Class for spectr calculation CFLF *FFLF; //Class of fast low frequency filter CFLF *SFLF; //Class of slow low frequency filterpublic: CSignalATCF(); ~CSignalATCF(); };
Durante a inicialização, devemos transferir para o módulo o nome do instrumento, o timeframe usado, o número de barras no histórico para análise da densidade espectral, bem como o número de barras de média (usa-se no cálculo os indicadores RBCI e PCCI). Além disso, é preciso especificar qual padrão deve ser utilizado para abertura das posições. O aparência geral da descrição do módulo será:
// wizard description start //+---------------------------------------------------------------------------+ //| Description of the class | //| Title=Signals degign by DNG for Adaptive Trend & Cycles Following Method | //| Type=SignalAdvanced | //| Name=Signals Adaptive Trend & Cycles Following Method | //| ShortName=ATCF | //| Class=CSignalATCF | //| Page=https://www.mql5.com/pt/articles/3456 | //| Parameter=TimeFrame,ENUM_TIMEFRAMES,PERIOD_H4,Timeframe | //| Parameter=HistoryBars,uint,1560,Bars in history to analysis | //| Parameter=AveragePeriod,uint,500,Period for RBCI and PCCI | //| Parameter=Pattern1,bool,true,Use pattern 1 | //| Parameter=Pattern2,bool,true,Use pattern 2 | //| Parameter=Pattern3,bool,true,Use pattern 3 | //| Parameter=Pattern4,bool,true,Use pattern 4 | //| Parameter=Pattern5,bool,true,Use pattern 5 | //| Parameter=Pattern6,bool,true,Use pattern 6 | //| Parameter=Pattern7,bool,true,Use pattern 7 | //| Parameter=Pattern8,bool,true,Use pattern 8 | //+---------------------------------------------------------------------------+ // wizard description end
Agora declaramos as variáveis e funções necessárias:
class CSignalATCF : public CExpertSignal { private: ENUM_TIMEFRAMES ce_Timeframe; //Timeframe uint ci_HistoryBars; //Bars in history to analysis uint ci_AveragePeriod; //Period for RBCI and PCCI CSpectrum *Spectrum; //Class for spectr calculation CFLF *FFLF; //Class of fast low frequency filter CFLF *SFLF; //Class of slow low frequency filter //--- Indicators data double FATL, FATL1, FATL2; double SATL, SATL1; double RFTL, RFTL1, RFTL2; double RSTL, RSTL1; double FTLM, FTLM1, FTLM2; double STLM, STLM1; double RBCI, RBCI1, RBCI2; double PCCI, PCCI1, PCCI2; //--- Patterns flags bool cb_UsePattern1; bool cb_UsePattern2; bool cb_UsePattern3; bool cb_UsePattern4; bool cb_UsePattern5; bool cb_UsePattern6; bool cb_UsePattern7; bool cb_UsePattern8; //--- datetime cdt_LastSpectrCalc; datetime cdt_LastCalcIndicators; bool cb_fast_calced; bool cb_slow_calced; bool CalculateIndicators(void); public: CSignalATCF(); ~CSignalATCF(); //--- void TimeFrame(ENUM_TIMEFRAMES value); void HistoryBars(uint value); void AveragePeriod(uint value); void Pattern1(bool value) { cb_UsePattern1=value; } void Pattern2(bool value) { cb_UsePattern2=value; } void Pattern3(bool value) { cb_UsePattern3=value; } void Pattern4(bool value) { cb_UsePattern4=value; } void Pattern5(bool value) { cb_UsePattern5=value; } void Pattern6(bool value) { cb_UsePattern6=value; } void Pattern7(bool value) { cb_UsePattern7=value; } void Pattern8(bool value) { cb_UsePattern8=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void); };
Criamos a função para calcular os valores dos indicadores:
bool CSignalATCF::CalculateIndicators(void) { //--- Check time of last calculation datetime current=(datetime)SeriesInfoInteger(m_symbol.Name(),ce_Timeframe,SERIES_LASTBAR_DATE); if(current==cdt_LastCalcIndicators) return true; // Exit if data alredy calculated on this bar //--- Check fo recalc spectrum MqlDateTime Current; TimeToStruct(current,Current); Current.hour=0; Current.min=0; Current.sec=0; datetime start_day=StructToTime(Current); if(!cb_fast_calced || !cb_slow_calced || (!PositionSelect(m_symbol.Name()) && start_day>cdt_LastSpectrCalc)) { if(CheckPointer(Spectrum)==POINTER_INVALID) { Spectrum=new CSpectrum(ci_HistoryBars,m_symbol.Name(),ce_Timeframe); if(CheckPointer(Spectrum)==POINTER_INVALID) { cb_fast_calced=false; cb_slow_calced=false; return false; } } int fast,slow; if(Spectrum.GetPeriods(fast,slow)) { cdt_LastSpectrCalc=(datetime)SeriesInfoInteger(m_symbol.Name(),ce_Timeframe,SERIES_LASTBAR_DATE); if(CheckPointer(FFLF)==POINTER_INVALID) { FFLF=new CFLF(); if(CheckPointer(FFLF)==POINTER_INVALID) return false; } cb_fast_calced=FFLF.CalcImpulses(fast); if(CheckPointer(SFLF)==POINTER_INVALID) { SFLF=new CFLF(); if(CheckPointer(SFLF)==POINTER_INVALID) return false; } cb_slow_calced=SFLF.CalcImpulses(slow); } } if(!cb_fast_calced || !cb_slow_calced) return false; // Exit on some error //--- Calculate indicators data int shift=StartIndex(); double rbci[],pcci[],close[]; if(ArrayResize(rbci,ci_AveragePeriod)<(int)ci_AveragePeriod || ArrayResize(pcci,ci_AveragePeriod)<(int)ci_AveragePeriod || m_close.GetData(shift,ci_AveragePeriod,close)<(int)ci_AveragePeriod) { return false; } for(uint i=0;i<ci_AveragePeriod;i++) { double fatl=FFLF.AdaptiveTrendLine(m_symbol.Name(),ce_Timeframe,shift+i); double satl=SFLF.AdaptiveTrendLine(m_symbol.Name(),ce_Timeframe,shift+i); switch(i) { case 0: FATL=fatl; SATL=satl; break; case 1: FATL1=fatl; SATL1=satl; break; case 2: FATL2=fatl; break; } rbci[i]=fatl-satl; pcci[i]=close[i]-fatl; } RFTL=FFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift); RSTL=SFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift); RFTL1=FFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift+1); RSTL1=SFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift+1); RFTL2=FFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift+2); FTLM=FATL-RFTL; STLM=SATL-RSTL; FTLM1=FATL1-RFTL1; STLM1=SATL1-RSTL1; FTLM2=FATL2-RFTL2; double dev=MathStandardDeviation(rbci); if(dev==0 || dev==QNaN) return false; RBCI=rbci[0]/dev; RBCI1=rbci[1]/dev; RBCI2=rbci[2]/dev; dev=MathAverageDeviation(pcci); if(dev==0 || dev==QNaN) return false; PCCI=pcci[0]/(dev*0.015); PCCI1=pcci[1]/(dev*0.015); PCCI2=pcci[2]/(dev*0.015); cdt_LastCalcIndicators=current; //--- return true; }
Em seguida, codificamos as padrões de abertura e fechamento de posições, indicando os pesos correspondentes (40 para abertura e 80 para fechamento). Abaixo estão as funções para a abertura de posições longas. Para posições curtas, a função é construída de forma semelhante.
int CSignalATCF::LongCondition(void) { if(!CalculateIndicators() || m_open.GetData(1)>m_close.GetData(1)) return 0; int result=0; //--- Close if(m_high.GetData(2)<m_close.GetData(1) || (STLM1<=0 && STLM>0) || (PCCI1<PCCI && PCCI1<=PCCI2) || (RBCI>RBCI1 && RBCI1>=RBCI2 && RBCI1<-1) || (RBCI1<=0 && RBCI>0)) result=40; //--- Pattern 1 if(cb_UsePattern1 && FTLM>0 && STLM>STLM1 && PCCI<100) result=80; else //--- Pattern 2 if(cb_UsePattern2 && STLM>0 && FATL>FATL1 && FTLM>FTLM1 && RBCI>RBCI1 && (STLM>=STLM1 || (STLM<STLM1 && RBCI<1))) result=80; else //--- Pattern 3 if(cb_UsePattern3 && STLM>0 && FATL>FATL1 && RBCI>RBCI1 && RBCI1<-1 && RBCI1<=RBCI2 && FTLM>FTLM1) result=80; else //--- Pattern 4 if(cb_UsePattern4 && SATL>SATL1 && FATL>FATL1 && RBCI>RBCI1 && FTLM<FTLM1 && FTLM2<=FTLM1) result=80; else //--- Pattern 5 if(cb_UsePattern5 && SATL>SATL1 && STLM>=0 && PCCI1<=-100 && PCCI1<PCCI && PCCI>-100 && RBCI>RBCI1 && RBCI1<=RBCI2 && RBCI1<-1) result=80; else //--- Pattern 6 if(cb_UsePattern6 && SATL>SATL1 && STLM<0 && PCCI1<=-100 && PCCI>-100) result=80; else //--- Pattern 7 if(cb_UsePattern7 && FATL>FATL1 && FATL1<=SATL1 && FATL>SATL && FATL1<=FATL2) result=80; //--- Pattern 8 if(cb_UsePattern8 && FATL>FATL1 && FATL1<=SATL1 && FATL>SATL && FATL1<=RFTL1 && FATL>RFTL) result=80; return result; }
4. Criamos o Expert Advisor de acompanhamento adaptativo do mercado
Depois de criar o módulo de sinal, pode-se proceder a gerar o EA. O processo de criação do EA com ajuda do assistente é descrito neste artigo em detalhes. Durante a criação do EA, eu usei apenas o módulo de sinais de negociação, criado acima. Além disso, foi adicionado um Trailing-Stop com um número fixo de pontos. Quando a estratégia for testada, usaremos um lote fixo, o que permitirá avaliar a qualidade dos sinais gerados.
5. Testando o Expert Advisor.
Após criado o Expert Advisor, podemos testar o método adaptativo de acompanhamento do mercado na Testador de estratégias. Durante o teste, é necessário indicar o peso para abertura da posição no nível de 60 e o peso para fechamento da posição no nível de 10.
5.1. O teste sem o uso de Stop-Loss, Take-Profit e Trailing-Stop.
Para verificar a qualidade dos sinais gerados pelo EA, o primeiro teste foi realizado sem o uso de Stop-Loss, Take-Profit e Trailing-Stop. O teste foi realizado no timeframe H4 durante para 7 meses de 2017.
Infelizmente, o primeiro teste mostrou perdas na implementação de estratégia sem o uso de Stop-Loss.
A análise detalhada das transações realizadas na gráfico de preços mostra duas áreas de estratégia problemáticas:
- Expert Advisor não consegue fechar a tempo as transações durante recuos acentuados, o que leva à perda do lucro e fechamento desfavorável de transações potencialmente rentáveis.
- O EA trabalha bem com grandes movimentos, mas abre uma série de transações não rentáveis em movimentos de correção.
5.2. Teste usando Stop-Loss e Trailing-Stop.
Para minimizar as perdas do primeiro ponto foi colocado Stop-Loss e aplicado o Trailing-Stop.
Mantendo-se constantes outros fatores, o segundo teste mostrou uma diminuição na retenção da posição, um ligeiro aumento na proporção da transações rentáveis, e, ao todo, um tendência geral na direção do lucro.
Contudo, a porcentagem de transações rentáveis foi de 39,26%. E manteve-se a segunda área problemática (transações desfavoráveis).
5.3. Testando usando ordens de stop.
Para reduzir as perdas associadas com as contínuas transações não favoráveis em movimentos de correção, foi realizado o teste usando ordens de stop.
Como resultado, o terceiro teste mostrou que a quantidade de transações diminuiu quase duas vezes, enquanto que o rendimento total aumentou, e o percentual de transações rentáveis apresentou um aumento de 44,57%.
Fim do artigo
No artigo, foi examinado o método de acompanhamento adaptativo do mercado. Testes revelaram a presença de potencial nesta estratégia, mas, para uso no mercado real, é necessária a eliminação de alguns gargalos. Contudo, o método é viável. Os arquivos de origem e os resultados dos testes são apresentados no anexo ao artigo.
Referências
- Especulador de moedas, Dezembro de 2000 - Junho de 2001.
- Análise das principais características da série temporal.
- Extrapolação AR de preço - indicadores para MetaTrader 5
- Assistente MQL5: Como criar um módulo de sinais de negociação
- Crie o seu próprio robô de negociação em 6 passos!
- Assistente MQL5: nova versão
Programas utilizados no artigo:
# | Nome | Tipo | Descrição |
---|---|---|---|
1 | Spectrum.mqh | Biblioteca de classes | Classe para estimar a densidade espectral do instrumento de teste |
2 | FLF.mqh | Biblioteca de classes | Classe para construir o filtro passa-baixos e filtrar os dados de origem |
3 | SignalATCF.mqh | Biblioteca de classes | Módulo de sinais de negociação para o método de acompanhamento adaptativo do mercado |
4 | ATCF.mq5 | Expert Advisor | Expert Advisor para o método de acompanhamento adaptativo do mercado. |
5 | ACTF_Test.zip | Arquivo | O arquivo contém os resultados dos testes do EA no testador de estratégias. |
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/3456
![Criação e teste de símbolos personalizados na MetaTrader 5](https://c.mql5.com/2/29/MQL5_Custom_Symbols.png)
![Redes Neurais Profundas (Parte II). Desenvolvimento e seleção de preditores](https://c.mql5.com/2/48/Deep_Neural_Networks_02.png)
![Interfaces gráficas XI: Caixas de Edição de Texto e Caixas de Combinação nas células da tabela (build 15)](https://c.mql5.com/2/28/MQL5-avatar-XI-build_15.png)
![Redes Neurais Profundas (Parte I). Preparando os Dados](https://c.mql5.com/2/48/Deep_Neural_Networks_01.png)
![MQL5 - Linguagem para estratégias de negociação inseridas no terminal do cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- 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