O preço da lata != preço ? - página 7

 

WHRoeder: este código é bom (especialmente cheque "adicionado" e "padrão")? Pode também servir como uma referência final fácil para aqueles que visitam este tópico e vão apenas à última página (como eu fiz)

#define LT    0
#define GT    1
#define GTE   2
#define LTE   3
#define EQ    4
#define NEQ   5

bool doublecomp(double a,int type,double b){
  // See https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>Point/2.);
    case GT: return(a-b>Point/2.);
    case GTE: return(a-b>-Point); // Added
    case LTE: return(b-a>-Point); // Added
    case EQ: return(!(MathAbs(a-b)>Point/2.));
    case NEQ: return(MathAbs(a-b)>Point/2.);
    default: return(-1); // Added - needed to avoid compile error about not all control paths returning a value
  }
}
 

Esse código não é preciso.

Como se( !MathAbs( a - b ) > Ponto/2) pode ser usado para comparar para igualdade? Isso lhe diria 1,4999 == 1,5000

 
SDC: Como se( !MathAbs( a - b ) > Ponto/2) pode ser usado para comparar para igualdade? Isso lhe diria 1,4999 == 1,5000
  1. Não
    if( ! (MathAbs( a     -  b    ) > Point/2) ) be used to compare for equality? That would tell you 1.4999 == 1.5000
    if( ! (MathAbs(1.4999 - 1.5000  > 0.00005  )
    if( ! (0.0001                   > 0.00005  )
    if( ! (true                                )
    if( false                                  ) 1.4999 is NOT equal to 1.5000
  2. E eu havia apontado para Roel13 em um PM que o GEQ/LEQ deve ser -Point/2, mas ele não editou o posto
  3. E, como já informei anteriormente, você só tem que se preocupar com tais disparates se a igualdade/não-equidade for importante. Se você quiser abrir acima do alto de uma vela, importa se (por causa do arredondamento) ela pode acionar exatamente no alto? Se não usar apenas lance > alto[].
 

Eu uso

if(NormalizeDouble(price1-price2,Digits)==0)


ou para o dobro que arn preços reais, uma maior precisão

if(NormalizeDouble(value1-value2,8)==0)
 
SDC: Eu uso
if(NormalizeDouble(price1-price2,Digits)==0)
Leia o primeiro post e você aprenderá porque isso não é uma boa idéia.
 

Raptors postam sobre este código

double TestValue = iClose(NULL, 0, 0);
   
if(TestValue != NormalizeDouble(TestValue, Digits) ) //not equal

Portanto, se você usar,

double TestValue = iClose(NULL, 0, 0);

if(NormalizeDouble(TestValue - iClose(NULL,0,0),Digits)==0) // they are considered equal

Testei esse método de várias maneiras e não encontrei um cenário em que ele não retornasse o resultado esperado ou desejado.
 

Código final... Obrigado WHRoeder

#define LT    0
#define GT    1
#define GTE   2
#define LTE   3
#define EQ    4
#define NEQ   5

bool ComparePrice(double a,int type,double b){
  // See https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>Point/2.);
    case GT: return(a-b>Point/2.);
    case GTE: return(a-b>-Point/2.);
    case LTE: return(b-a>-Point/2.);
    case EQ: return(!(MathAbs(a-b)>Point/2.));
    case NEQ: return(MathAbs(a-b)>Point/2.);
  }
  return(-1);
}


E, talvez uma função secundária para comparar todas as outras duplas que não são preços.

bool CompareNormal(double a,int type,double b){
  // With thanks https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>0.0000000000000000000000000000001);
    case GT: return(a-b>0.0000000000000000000000000000001);
    case LTE: return(b-a>-0.0000000000000000000000000000001);
    case GTE: return(a-b>-0.0000000000000000000000000000001);
    case EQ: return(!(MathAbs(a-b)>0.0000000000000000000000000000001));
    case NEQ: return(MathAbs(a-b)>0.0000000000000000000000000000001);
  }
  return(-1);
}


Veja também 'MQL4 Reference > Language Basics > Data Types > Real Types (double, float)' em relação ao uso de um número pequeno para comparação.

Talvez alguém saiba escrever 0,00....1 melhor em expo

 
Roel13: Talvez alguém saiba escrever 0,00....1 melhor em expon
// case LT: return(b-a>0.0000000000000000000000000000001);
// case LT: return(b-a>1.0e-30);
Ver Tipos reais (duplo, flutuador) - Documentação MQL4
Notado que o valor do epsilon no exemplo acima não pode ser inferior à constante predefinida DBL_EPSILON. O valor desta constante é 2,2204460492503131e-016.
Novamente, nada disso é necessário, exceto no caso em que o igual/não igual é importante. Por exemplo, abra acima da alta anterior, você não quer abrir na alta devido ao arredondamento.
 

Portanto, há algo mais interessante que encontrei, potencialmente em conexão com a "// 0 compare não precisa desta função".

Talvez um bug apenas nas versões mais recentes, não tenho certeza. A comparação com 0 não funciona mais corretamente. Tive que recorrer a algo pouco amigável como;

outcome=(int(outcome*100)/100.0); // Resolução 2 dígitos

Apenas para garantir que os valores 0 realmente acabassem como valores 0.

WHRoeder, obrigado. Mais estudos necessários :)

 

Acho que este tópico é tratado com demasiada complexidade desnecessária.

Tente tornar a vida de seu programador sempre tão fácil quanto possível. Escreva definições (ou vá em frente com métodos se realmente for necessário) naquelas aulas em que você precisa de suas comparações duplas:

// add more floating point zeros if you need a higher precision
#define  isZero(x) (fabs(x) < 0.000000001)
#define  isEqual(x,y) (fabs(x-y) < 0.000000001)

Quando você precisar comparar duas duplas, use-as em uma condição como esta:

if (isEqual(myFirstDouble, mySecondDouble))
{
  // first and second doubles are considered equal
  // do something
}

Se você quiser ver se um duplo é zero (ou muito, muito próximo de zero), use uma condição como esta:

if (isZero(myDouble))
{
  // myDouble is considered zero
  // do something
}


Em uma nota lateral, já que vejo muitos posts falando sobre divisões:

Com o encapsulamento, tendemos a esquecer os custos do código que é "terceirizado" para alguns métodos de utilidade. Lembrem-se de queas divisões são computacionalmente muito caras! Especialmente, uma vez envoltas em métodos utilitários agradáveis em algum lugar nas classes de utilidade, começamos a usá-las em todos os lugares em indicadores ou EAs e há muito tempo esquecemos que passos computacionais eles executam. Quando usamos o testador de estratégia, pagamos muito tempo desnecessário por nosso desleixo.

Regra de ouro: As adições e subtrações são muito mais rápidas do que as multiplicações e divisões. A operação de divisão leva o maior tempo de computação.Otimize as divisões- sempre que possível! Se o denominador for fixo como neste loop...

for(int i=0; i < rates_total; i++)
{
    // ...
    double fraction = someNumeratorValue / 100;
    // ...
}

então substitua o denominador x por seu valor invertido 1/x:

for(int i=0; i < rates_total; i++)
{
    // ...
    double fraction = 0.01 * someNumeratorValue; // replace a denominator with it's inverted value, if possible.
    // ...
}

Além disso, se o resultado de uma divisão for sempre o mesmo, então faça o cálculo uma vez e salve o resultado em uma variável para que você possa usá-la em qualquer lugar em seu código (por exemplo, em loops):

double tradesPerDay = totalTradesPerYear/365;

for(int i=0; i < rates_total; i++)
{
    // use precomputed tradesPerDay rather than computing the division here.
}

Abraço,

A.T.