Comparação da média móvel (e quaisquer outros indicadores) e erro

 

Olá a todos!

Estou escrevendo um EA baseado no cruzamento de SMA (ou melhor, pensei que já tinha escrito, porque parece ser simples). Mas... Eu enfrentei um problema. O Expert Advisor trabalha com o seguinte princípio: quando uma nova barra aparece, ele analisa os valores de SMA das duas últimas barras, sem contar a última que acabo de aparecer (a penúltima e a anterior). Eu comparo valores aparentemente corretos, como descrito aqui. A única exceção é que o iMA é chamado com o último parâmetro (offset em barras) 1 e 2, respectivamente. Aproximadamente assim (se o código for reescrito por analogia com o citado):

// берем два соседних значения Быстрой МА
double fast0=iMA(Symbol(), Period(), 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double fast1=iMA(Symbol(), Period(), 10, 0, MODE_SMA, PRICE_CLOSE, 2);
 
// берем два значения Медленной МА
double slow0=iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 1);
double slow1=iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 2);
 
// сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<slow1) Print("Пересечение ВВЕРХ");
if (fast0<slow0 && fast1>slow1) Print("Пересечение ВНИЗ");

O Expert Advisor funciona de forma primitiva na presença de um sinal de travessia sobre o princípio de fechar o comércio anterior - abrir um novo comércio. Naturalmente, se todos os crossovers forem detectados, então as negociações serão sempre executadas uma após a outra (VENDER - COMPRAR - VENDER - COMPRAR - ...). Ou seja, o Expert Advisor tem apenas uma negociação aberta a qualquer momento (bem, exceto no momento antes de entrar na primeira negociação). Então aqui está a essência do problema... Para o período de minutos e SMA períodos 5 e 34 para Fechar no testador de estratégia na barra de 17.02.2015 a 01:24 eu peguei uma situação interessante. Os aparelhos com estas características se cruzam diretamente no fechamento do bar. Aqui está a foto:

17.02.2015 01:24

Para fins de depuração, eu forneço as informações. A correspondência no registro em comparação com o código dado é a seguinte:

SMAFastCurrent =fast0

SMASlowCurrent =slow0

SMAFastPrevious =fast1

SMASlowPrevious=slow1 e

SMACurDifference = SMAFastCurrent - SMASlowCurrent

SMAPrevDifference = SMAFastPrevious - SMASlowPreviousc (ou seja, a diferença entrefast0,slow0 efast1,slow1 respectivamente).

Portanto, quando estas diferenças mudam de sinal, significa que este é um sinal para uma travessia de Mooving. Mas neste exemplo em particular, o cheque para mais ou menos não funciona. Os valores dessas diferenças são exibidos no log. O retângulo vermelho mostra valores de diferenças na próxima barra após o problema (a 1:25), laranja - na próxima barra (a 1:26). E é claro, que os valores SMACurDiferença na barra anterior e SMAPrevDiferença na barra atual devem ser iguais (a barra atual torna-se a anterior e a nova barra toma seu lugar). Assim, como a travessia de Mooving ocorre no fechamento da barra de problemas à 1:24, na barra seguinte (à 1:25) os valores SMAFastCurrent e SMASlowCurrent são iguais (aproximadamente). O depurador os imprime geralmente dentro de 5 dígitos (SMAFastCurrent = 1,13371 SMASlowCurrent = 1,13371 ver figura). Sua diferença é infinitesimal, mas não 0 (SMACurDiferença = 2,220446049250313e-016). Na barra seguinte sua diferença com os mesmos valores exatos torna-se exatamente zero (compare SMACurDifferência em vermelho e SMAPrevDifferência em retângulos laranja). Na verdade, não está claro então como cortar esses erros, se mesmo valores aparentemente idênticos dão diferença diferente. Daí duas perguntas:

1. Por que a diferença dos mesmos muwings só é contada no momento da aparência alternada de duas barras adjacentes, dá um resultado diferente?

2. Eu estava pensando em introduzir um pouco de epsilon e comparar com ele, em vez de zero. Mas geralmente é feito para comparar um infinitesimal com 0. E o caso quando eu precisar determinar a mudança de sinal deste infinitesimal?

É claro que posso analisar três barras adjacentes, mas ainda é teoricamente possível que, aos preços de seus fechamentos, os muvings se toquem uns aos outros a uma distância infinitesimal. Percebo que esta situação raramente ocorre (especialmente se levarmos um tempo maior), mas ainda pode ocorrer. E deve ser capturado de alguma forma e a travessia de Mouveins também deve ser detectada neste caso.

Obrigado antecipadamente por qualquer ajuda!

Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
  • www.mql5.com
Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
 

Tente a normalização e a comparação.

O Manual de Referência MQL4 (e é o mesmo para MQL5) diz, aberto em"Tipos Reais (duplo, flutuador)":

"... Não se pode comparar dois números reais para a igualdade um com o outro. Na maioria dos casos, dois números aparentemente idênticos podem se revelar desiguais devido à diferença de 15 casas decimais. Para comparar corretamente dois números reais, você deve comparar a diferença normalizada desses números com um valor zero...."

"... é fortemente desencorajado comparar dois números reais um com o outro para a igualdade, pois tal comparação não é correta.

..............


Se, no entanto, for necessário comparar dois números reais para a igualdade, isso pode ser feito de duas maneiras diferentes. A primeira maneira é comparar a diferença entre os dois números com algum pequeno valor que define a precisão da comparação.

.............


O segundo método envolve comparar a diferença normalizada de dois números reais com um valor zero. É inútil comparar a diferença de números normalizados com zero, porque qualquer operação matemática com números normalizados resulta em um resultado não-normalizado.

...."

 
rosomah:

Tente a normalização e a comparação.

O Manual de Referência MQL4 (e é o mesmo para MQL5) diz, aberto em"Tipos Reais (duplo, flutuador)":

"... Não se pode comparar dois números reais para a igualdade um com o outro. Na maioria dos casos, dois números aparentemente idênticos podem se revelar desiguais devido à diferença de 15 casas decimais. Para comparar corretamente dois números reais, você deve comparar a diferença normalizada desses números com um valor zero...."

"Não é categoricamente recomendado comparar dois números reais um com o outro para a igualdade, uma vez que esta comparação não é válida.

..............


Se, no entanto, for necessário comparar dois números reais para a igualdade, isso pode ser feito de duas maneiras diferentes. A primeira maneira é comparar a diferença entre os dois números com algum pequeno valor que define a precisão da comparação.

.............


A segunda maneira é comparar a diferença normalizada de dois números reais com zero. É inútil comparar a diferença de números normalizados com zero, porque qualquer operação matemática com números normalizados resulta em um resultado não-normalizado.

...."

Estou bem ciente de que não é possível comparar números reais para a igualdade. Não há comparações de igualdade no código que citei. E também não há necessidade disso. O que temos aqui é uma situação em que precisamos capturar mudanças de um sinal infinitesimal que pode muito bem chegar a 0. A simples comparação de tudo com mais ou igual a 0 também é perigosa neste caso. E a normalização pode ser ainda mais perigosa aqui... Os valores iniciais de MA são normalizados para um número desconhecido (quanto menor é o tempo, menor é o valor de MA). Se a normalização para um dígito constante após o ponto decimal for aplicada, pode resultar em que todos os valores de MA serão exatamente 0. Para ser honesto, não entendo realmente qual será a diferença entre dois valores de Mestrado...

 

gammaray:

Estou bem ciente de que não é possível comparar números reais sobre igualdade. No código que citei, não há comparações de igualdade. E também não há necessidade disso. O que temos aqui é uma situação em que precisamos capturar mudanças de um sinal infinitesimal que pode muito bem atingir 0. A simples comparação de tudo com mais ou igual a 0 também é perigosa neste caso. E a normalização pode ser ainda mais perigosa aqui... Os valores iniciais de MA são normalizados para um número desconhecido (quanto menor é o tempo, menor é o valor de MA). Se a normalização para um dígito constante após o ponto decimal for aplicada, pode resultar em que todos os valores de MA serão exatamente 0. Para ser honesto, não entendo realmente qual será a diferença entre dois valores de Mestrado...

Por que a normalização é mais perigosa?

Portanto:

...

Se você precisar comparar dois números reais para a igualdade, você pode fazê-lo de duas maneiras diferentes. A primeira maneira é comparar a diferença entre os dois números com algum valor pequeno que define a precisão da comparação.

...

A segunda maneira envolve comparar a diferença normalizada de dois números reais com um valor zero. Comparar a diferença dos números normalizados com zero é inútil, já que qualquer operação matemática com números normalizados resulta em um resultado não normalizado.

Exemplo:

bool CompareDoubles(double number1,double number2)
  {
   if(NormalizeDouble(number1-number2,8)==0) return(true);
   else return(false);
  }
void OnStart()
  {
   double d_val=0.3;
   float  f_val=0.3;
   if(CompareDoubles(d_val,f_val)) Print(d_val,"equals",f_val);
   else Print("Different: d_val = ",DoubleToString(d_val,16),
              "  f_val = ",DoubleToString(f_val,16));
// Результат: Different: d_val= 0.3000000000000000   f_val= 0.3000000119209290
  }
  • E minha experiência prática pessoal (para dizer modestamente, não é pequena em termos de número de verificações meticulosas da operação do programa, onde eu me candidatei e ainda me candidatei para comparar números com o dobro, em termos de exatidão das condições desencadeadas com base em tais comparações),
Isto me permite considerar que tais comparações não são apenas não ameaçadoras:
if(NormalizeDouble(number1-number2,dig)==0)
if(NormalizeDouble(number1-number2,dig)>0)
if(NormalizeDouble(number1-number2,dig)<0)

// dig=Digits();

mas, inversamente, uma variação de uma das duas formas que podem, como diz a Documentação, ser aplicadas às comparações de números duplos.

Desde então:

Não é possível comparar dois números reais para a igualdade um com o outro. Na maioria dos casos, dois números aparentemente idênticos podem se revelar desiguais devido a uma diferença no valor de 15 casas decimais. Para comparar corretamente dois números reais, a diferença normalizada destes números deve ser comparada a zero.



P./S.: Aconteceu que o primeiro método da Documentação foi menos conveniente para mim, também com base em tarefas, que, como regra geral, eu estava resolvendo por mim mesmo. Consequentemente, não tenho muita experiência com o primeiro caminho.

Mas ao utilizar a segunda via (isto é, comparar a diferença normalizada de dois números reais com valor zero na expressão do operador condicional), não ocorreram problemas.

Mas se eu fiz uma comparação de números não-normalizados (aqui quero dizer, incluindo o que fiz sem usar a primeira maneira), então sim, houve, que eu encontrei um disparo incorreto de condições com base em comparações de números do tipo duplo.

 
gammaray:

Estas são as frases da Documentação:

O segundo método envolve a comparação da diferença normalizada de dois números reais com zero. Comparar a diferença de números normalizados com zero é inútil, porque qualquer operação matemática com números normalizados resulta em um resultado não-normalizado.

Para mim é percebido que, em termos simplistas, em operações matemáticas (e incluindo várias transformações) não se deve fazer algo como isto:

// dig=Digits();

double delta=NormalizeDouble(number1-number2,dig);

if (delta>0)


Ou seja, no post anterior acima dei exemplos de comparações da diferença normalizada de dois números reais com um valor zero. E neste post, comparando a diferença dos números normalizados com zero (no meu entendimento do texto das frases acima da Documentação).

Em poucas palavras, é isso mesmo.

 

gammaray:

...

O que a normalização da diferença entre os dois valores de Mestrado fará, para ser honesto, eu não entendo realmente

P./S.: Neste ponto, você pode simplesmente colocar Print() em seu código por um tempo para ver o que será produzido em uma grande quantidade de dados. Em Impressão impressão impressão não-normalizada e normalizada (até algumas casas decimais, inclusive maiores do que no gráfico onde você fará os experimentos) valores obtidos de operações matemáticas. Incluindo simplesmente valores iMA não normalizados e normalizados, pois eles são formados com base em operações matemáticas.

Por precaução, deixe-me também especificar que ao imprimir valores não normalizados e normalizados de tipo duplo, eles devem ser convertidos adicionalmente, é claro, de valor numérico para valor de texto usando DoubleToString (e na experiência DoubleToString com o número de casas decimais).

 
gammaray:

P./S.: Também quero acrescentar que penso que em exemplos de quaisquer esquemas escritos para programadores MQL4, a normalização dos valores dos cálculos matemáticos não pode ser prescrita ou/e não expressamente declarada:

  • para facilitar a compreensão de esquemas de formação de quaisquer condições;
  • Nem sempre e/ou nem sempre pode ser necessária uma normalização (incluindo que se possa supor que se aplique para diferentes níveis de tarefas de erros toleráveis e, conseqüentemente, uma normalização adicional diferente (ou falta dela) dos resultados de operações matemáticas sobre o número de casas decimais para algumas tarefas individuais);
  • e/ou, muito provavelmente, presume-se que um desenvolvedor esteja familiarizado com a Documentação e/ou a leia, a fim de esclarecer suas dúvidas.
Algo parecido com isto.
 
É mais preciso.
// сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<=slow1) Print("Пересечение ВВЕРХ");
if (fast0<slow0 && fast1>=slow1) Print("Пересечение ВНИЗ");

Isto é, não levava em conta que os valores ma também poderiam ser iguais.

сравнивать вещественные числа на равенство нельзя

ligeiramente diferente.
 
Aleksey Lebedev:
Um pouco sobre outra coisa.

Depende do que você tem em mente e para quais tarefas/objetivos.

Portanto, ao escrever os postes neste tópico, estou me baseando neles:

  • A captura de tela e as perguntas no primeiro post;
  • o segundo posto do autor do fio (sobre os perigos da normalização),

e, conseqüentemente, daqui e, resumindo, o significado dos meus cargos acima:

Com a ajuda da possibilidade de normalização para definir/ajustar o nível de precisão necessário de comparações (e/ou valores de saída) e/ou tolerável para algumas tarefas e erros de metas, o que por sua vez permite acionar as condições do programa exatamente onde e como ele foi projetado ao prescrever condições específicas em código. E a comparação da diferença normalizada com zero, permite ajustar/ajustar não apenas para as comparações utilizando a operação de relações: "==".


P./S.: Assim, em qualquer caso, vou especificar mais uma vez, que a comparação de números reais pela primeira via de duas aqui listadas, devido à comparação de uma diferença de números com qualquer valor pequeno, não posso citar pior, do que a aplicação da normalização, quando é necessário ajustar o nível de comparações (incluindo, quanto a mim, a segunda via parecia mais conveniente, a primeira e não considerou para si mesma mais detalhada para a aplicação prática).


 

Isto não tem nada a ver com o mql em princípio. Vamos pegar uma linguagem de programação abstrata. Neste exemplo particular que dei, o principal problema é que os valores da diferença de muwings em uma mesma barra não são iguais (2e-16 no primeiro cálculo e exatamente 0 no segundo). Neste caso, esta interseção não pode ser determinada de forma alguma. Se voltarmos ao mql, a normalização implica em arredondar o número (ou melhor, simplesmente deixar cair todos os números após um certo sinal, como no piso de função Sish, mas a uma certa casa decimal). Então, como posso saber qual dígito normalizar? Se o dígito errado for escolhido, todos os valores podem SEMPRE ser arredondados para exatamente 0. Portanto, a normalização é perigosa aqui e geralmente não resolve o problema.

Quanto ao que Alexey Lebedev escreveu. Sim, eu estava pensando nesta direção. Mas se compararmos as duas diferenças por mais ou igual a 0, há uma probabilidade de obter um sinal falso (por exemplo, a situação teoricamente possível quando os abafamentos entre barras vizinhas têm exatamente os mesmos valores). Então sua diferença não muda o sinal (não há crossover), mas o sinal para o crossover será determinado programmaticamente. Você poderia colocar apenas uma comparação em mais ou igual, como você sugeriu. Mas então o problema é que no cálculo nesta situação primeiro não será igual a 0 (2e-16), e na próxima barra será exatamente 0, mas será uma comparação rigorosa.

É importante entender porque a mesma diferença, quando calculada em barras diferentes, NÃO produz o mesmo resultado. Se o resultado fosse o mesmo, o problema seria sempre resolvido com a introdução de uma comparação não restritiva

 

gammaray:

Mas então o problema é que o cálculo nesta situação primeiro não será igual a 0 (2e-16), e na próxima barra já será exatamente 0, mas haverá uma comparação rigorosa.

É importante entender porque a mesma diferença, quando calculada em barras diferentes, NÃO produz o mesmo resultado. Se o resultado fosse o mesmo, o problema seria sempre resolvido com a introdução de uma comparação não restritiva

O mais provável é que o cálculo da função iMA seja otimizado. Primeiro valor = soma(fechamento)/N, segundo = valor anterior de MA+(novo fechamento fechado)/N.