Você está perdendo oportunidades de negociação:
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Registro
Login
Você concorda com a política do site e com os termos de uso
Se você não tem uma conta, por favor registre-se
Comecei com esta premissa básica sobre a igualdade de preços (e não apenas a igualdade das duplas) -
(P1) Assumindo y = 1.50000: x == y, desde que x seja qualquer número real que seja (i) maior ou igual a 1.499995 e (ii) menor que 1.500005.
Construindo sobre P1, concluí que -
(P2) Assumindo y = 1.50000: a == y, b == y, e a == b, desde que a e b sejam números reais que sejam (i) maiores ou iguais a 1.499995 e (ii) menores que 1.500005.
Exemplos incluem: 1.500055 == 1.50006, 1.500055 == 1.500064, 1.500051 != 1.500059, e 1.500054 != 1.500056.
Usando o acima, criei uma função (abaixo) que (1) toma dois preços como argumentos, (2) arredonda esses preços para o ponto equivalente mais próximo, e (3) determina se esses dois preços são iguais.
Esta função é simples e direta, mas eu deveria comentar um pouco sobre a parte "Condicionamento de Preços". Como muitos de nós sabemos, duplica (ou seja Descobri que quando arredondei 1.5000551 e 1.5000550 para o ponto mais próximo e comparei o resultado (1.50006 e 1.50005, respectivamente), eles pareciam não ser iguais mesmo que, sob P1 e P2 acima, eles deveriam ser iguais. Concluí (depois de conduzir alguns testes) que o literal 1.5000550 foi armazenado na variável como ~1.5000549999. Para remediar isto, decidi que se o preço estivesse dentro de 15 milésimos de um ponto a partir da metade (x.xxxxx5), eu assumiria que o preço atingiu o limite mínimo para arredondamento até o ponto mais próximo. Assim, acrescento 15 dez milésimos de ponto a cada preço antes de arredondar para o ponto mais próximo. Neste momento, não acredito que esta adição tenha consequências involuntárias. Além disso, estes valores podem ser ajustados para aumentar/diminuir a suposição de arredondamento para o ponto mais próximo.
RaptorUK e WHRoeder(e outros):Usando o acima descrito como um plano, construí a seguinte função chamada ComparePrices() que é baseada no posto anterior do RaptorUK:
Como sempre, comentários instrutivos/construtivos são bem-vindos. :)
Eu mesmo tive uma pequena brincadeira com isso - tentando alcançar um compromisso aceitável de legibilidade e desempenho.
Eu me conformei com as funções individuais eq(a,b), ne(a,b), lt(a,b) etc...
Ex:
if (eq(a,b)) { ...}
Com relação ao desempenho da minha lenta VM para 4999999 iterações, obtive as seguintes medidas de base:
Loop vazio : 370ms
inline MathAbs(a-b) < gHalfPoint (global) : 2482ms
Função Bool Vazio: 4266ms <... tenho o objetivo de chegar o mais próximo possível desta figura.
As implementações mais rápidas de eq() que gerenciei estão abaixo.
Eles são cerca de 2,3 vezes mais lentos do que uma chamada de MathsAbs() em linha e 1,3 vezes mais lentos do que uma chamada de função booleana vazia .que apenas retorna verdadeiro.
Também como um aparte descobri que a MQL não faz curto-circuito com expressões booleanas.
em 5558ms
Ou se preferir estática a global (para manter todos os códigos em um só lugar):
em 5718ms
lt(), gt() etc. devem ser mais rápidos, pois eq() e ne() são mais complicados.
O ponto flutuante NUNCA é exato para alguns números.
https://en.wikipedia.org/wiki/Floating_point
Os números de ponto flutuante são números racionais porque podem ser representados como um número inteiro dividido por outro. Por exemplo, 1,45×103 é (145/100)*1000 ou 145000/100. A base, entretanto, determina as frações que podem ser representadas. Por exemplo, 1/5 não pode ser representado exatamente como um número de ponto flutuante usando uma base binária, mas pode ser representado exatamente usando uma base decimal (0,2, ou 2×10-1). Entretanto, 1/3 não pode ser representado exatamente por binário (0,010101...) nem decimal (0,333....), mas na base 3 é trivial (0,1 ou 1×3-1) .O valor duplo do corretor poderia ser de 1,2345750000000000000000 a 1,23458499999999999 e ainda ser considerado o mesmo preço de 1,23458.
No entanto, sua função diz que 1.2345750000000000000000 NÃO é GToE de 1.2345849999999999999
Contudo, sua função diz que 1.23458499999999999999 NÃO é LToE de 1.2345750000000000000000
Você deve usar um ponto/2 nas comparações https://www.mql5.com/en/forum/136997/page3#780837
Eu mesmo tive uma pequena brincadeira com isso - tentando alcançar um compromisso aceitável de legibilidade e desempenho.
O valor duplo do corretor poderia ser de 1,2345750000000000000000 a 1,23458499999999999 e ainda ser considerado o mesmo preço de 1,23458.
Eu concordo em geral. Veja meu P1 e P2 no meu post acima.
WHRoeder:
No entanto, sua função diz que 1.234575000000000000 NÃO é GToE de 1.2345849999999999999
Contudo, sua função diz que 1.23458499999999999999 NÃO é LToE de 1.2345750000000000000000
O problema surge de como o MT4/MQL armazena valores de ponto flutuante em variáveis. Por exemplo, o MT4/MQL é um valor de ponto flutuante:
imprime as duas variáveis no log/jornal:
Como você pode ver, p2 não é mais 1,23458499999999999, mas, em vez disso, passa a ser 1,23458500--devido, creio eu, a arredondar. Esta é a razão pela qual minha função diz que p1 não é GToE para p2; e como você pode ver no código abaixo, seu código também sugere o mesmo - ou seja, que p1 não é GToE para p2 e que p1 não é Igual a p2.
Você deve usar um ponto/2 nas comparações
Há uma possibilidade de que o Ponto/2 seja muito pequeno de um desvio máximo. Por exemplo:
Se a suposição é que 1,234575 é igual a 1,234580, então por que o número 2 mostra o NEQ? Além disso, se assumirmos que 1,23458 é um preço que pode significar um preço do corretor que está em qualquer lugar entre 1,2345750000000000000000 até 1,23458499999999999, por que o nº 1 deve mostrar o NEQ? Eles não deveriam ser iguais se compartilham o mesmo ponto de preço (daí minha Premissa nº 2 no meu posto acima)?
@Thirteen,
Em seu código você está olhando para diferenças de arredondamento intencionais devido à lógica de aplicação, não para erros de arredondamento involuntários devido a erros de ponto flutuante, daí a diferença:
Os dois tipos de "arredondamento" são:
a) Erros de arredondamento intrínsecos devido a frações binárias no formato IEEE. - Estes números devem ser exatamente os mesmos, mas não são devidos à representação binária das frações decimais. Eles são arredondados pela representação MQ4 de decimais.
b) Arredondamento explícito para algum número ou casas decimais. (por exemplo, ao imprimir, ou enviar preços para um Corretor). - Estes não são realmente destinados a serem os mesmos valores, em vez disso, estão sendo arredondados pela lógica de aplicação para a conveniência de alguém.
Isto não é realmente um erro. Erros devidos apenas à representação em ponto flutuante dificilmente serão tão grandes (a menos que se calcule mal uma série). Mas você pode querer fazer este tipo de comparação em sua aplicação de acordo com sua própria lógica.
Os erros de arredondamento intrínsecos[a] são geralmente muito pequenos ( ordens de magnitude menor que o Ponto ) e não intencionais. A aplicação não é capaz de arredondar esses números para ser exatamente o valor pretendido, usando o duplo tipo de dados.
As diferenças explícitas de arredondamento[b] são intencionais e muito maiores (+/- 0,5 ponto). (neste caso). portanto, dois números arredondados pela lógica de sua aplicação para o mesmo valor de ponto podem ser quase um ponto inteiro à parte originalmente.
O ideal seria primeiro arredondar os números [b] (somente se for necessário arredondar) e depois compará-los [a] em que ponto o erro é muito pequeno devido a limitações de duplo. (por exemplo, < 0,0000001)
Mas seu código é para comparar antes de arredondá-los, caso em que você tem que detalhar com as diferenças muito maiores possíveis. No entanto, o arredondamento nem sempre é necessário. Eu só o utilizaria quando enviasse os preços ao corretor.
Pense nisso de outra forma (se o MQ4 tivesse usado o código decimal binário - que permite a representação exata das frações decimais - então todas as questões relativas ao Preço != Preço desapareceriam,
mas você ainda teria que arredondar e comparar números em sua aplicação para o ponto mais próximo para certas operações. (Principalmente, funçÕes de PedidoXXX)
>> "se assumirmos que 1,23458 é um preço que pode significar um preço do corretor que vai de 1,2345750000000000000000 a 1,23458499999999999".
Eu poderia estar errado aqui (não tenho certeza de como os corretores trabalham), mas acho que um preço do corretor de 1,23458 é exatamente isso. especialmente com lotes de 100.000 dólares e maiores para considerar. Caso contrário, muito dinheiro a ser feito (pelo corretor) explorando a diferença nos preços publicados.
Meu entendimento é que na verdade é somente quando se envia para o corretor que você tem que arredondar, não durante toda a sua aplicação. Nesse caso, as comparações para pequenos erros devem ser suficientes.
A imprecisão do ponto flutuante é separada do arredondamento dos preços do corretor. Mas se você quiser lidar com os dois ao mesmo tempo, acho que isso é preferência pessoal (pode ficar confuso?).
Aqui está minha versão completa, (espero que sem bugs).
Isto oferece 6 funções:
eq(a,b) = ne(a,b) != gt(a,b) > lt(a,b) < ge(a,b) >= le(a,b) <= if (ge(Bid,target)) sell sell sell...
O racional é manter o código legível (IMO), e reduzir a probabilidade de erros de digitação, sem que haja muita perda de desempenho.Para todos os efeitos, estas funções devem ser tão rápidas quanto possível, utilizando as funções de usuário do MQ4,
(para desempenho vs MathAbs(a-b) < HalfPoint ver https://www.mql5.com/en/forum/136997/page5#822505 embora em um EA real (em oposição a um benchmark) eu suspeito que a diferença é insignificante.
Aqui está minha versão completa, (espero que sem bugs).
...
A premissa frequentemente citada é:
Considerando esta premissa e usando seu código como pano de fundo, você poderia me explicar por que você está dizendo (a) 1.234576 e 1.234584 não são considerados iguais, (b) 1.234577 e 1.234583 não são considerados iguais, mas (c) 1.234578 e 1.234582 são considerados iguais? Por que (e como) o exemplo (b) é menos igual do que o exemplo (c)?
Como afirmei acima, considero todos esses preços iguais porque cada ação tem o mesmo preço - nomadamente, 1,23458. Este exemplo ilustra porque acredito (e tenho dito acima) que o Ponto/2 pode ser muito pequeno de um desvio máximo.
@Thirteen, minha resposta às suas observações continua a ser a mesma 3 posts acima do link https://www.mql5.com/en/forum/136997/page5#822672. Vou repetir a parte que pode levar ao momento de luz-bolbo na compreensão do meu ponto de vista: (com um pouco de revisão e ênfase acrescentada)
Think of it another way (If MQ4 had used Binary Coded Decimal - which allows exact representation of Decimal fractions - then most of the original issues regarding Price != Price would go away, (and is often used on financial platforms for that very reason )
mas você ainda teria que arredondar e comparar números em sua aplicação para o ponto mais próximo para certas operações. (Principalmente, funxões OrderXXX)
Depende apenas de como você escreve seu código, e se você quiser diferenciar entre arredondamento de aplicações (onde dois números diferentes são conceitual/logicamente tratados como o mesmo para simplicidade/conveniência),
e erros de ponto flutuante. Não há certo e errado, mas acho que uma abordagem mais confusa do que a outra....
Além disso, sou pessoalmente um pouco cético em relação à premissa não citada (mas aberta à correção!), novamente mencionada no post anterior.