Può il prezzo != prezzo ? - pagina 7

 

WHRoeder: questo codice è buono (soprattutto controlla "added" e "default")? Può anche servire come facile riferimento finale per coloro che visitano questo thread e vanno solo all'ultima pagina (come ho fatto io)

#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
  }
}
 

Quel codice non è accurato.

Come si può usare if( !MathAbs( a - b ) > Point/2) per confrontare per l'uguaglianza? Questo vi direbbe 1.4999 == 1.5000

 
SDC: Come si può usare if( !MathAbs( a - b ) > Point/2) per confrontare l'uguaglianza? Questo vi direbbe 1.4999 == 1.5000
  1. Non è così
    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 avevo fatto notare a Roel13 in un PM che il GEQ/LEQ deve essere -Point/2 ma non ha modificato il post
  3. E come ho postato in precedenza, devi preoccuparti di queste sciocchezze solo se l'uguaglianza/non uguaglianza è importante. Se vuoi aprire sopra il massimo di una candela, ha importanza se (a causa dell'arrotondamento) potrebbe scattare esattamente al massimo? Se no basta usare bid > high[].
 

Io uso

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


o per i doppi che non sono prezzi reali, una maggiore precisione

if(NormalizeDouble(value1-value2,8)==0)
 
SDC: Io uso
if(NormalizeDouble(price1-price2,Digits)==0)
Leggete il primo post e imparerete perché non è una buona idea.
 

Il post di Raptors su questo codice

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

Quindi se usate,

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

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

Ho testato quel metodo in vari modi e non ho trovato uno scenario in cui non restituisse il risultato atteso o desiderato.
 

Codice finale... Grazie 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, forse una funzione secondaria per confrontare tutti gli altri doppi che non sono prezzi...

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);
}


Vedi anche 'MQL4 Reference > Language Basics > Data Types > Real Types (double, float)' per quanto riguarda l'uso di numeri piccoli per il confronto.

Forse qualcuno sa come scrivere meglio 0.00...1 in expon

 
Roel13: Forse qualcuno sa come scrivere meglio 0.00...1 in expon
// case LT: return(b-a>0.0000000000000000000000000000001);
// case LT: return(b-a>1.0e-30);
Vedere Tipi reali (double, float) - Documentazione MQL4
Notate che il valore di epsilon nell'esempio precedente non può essere inferiore alla costante predefinita DBL_EPSILON. Il valore di questa costante è 2.2204460492503131e-016.
Di nuovo, niente di tutto questo è necessario, tranne nel caso in cui l'uguale/non uguale è importante. Ad esempio, se si apre sopra il massimo precedente, non si vuole aprire al massimo a causa dell'arrotondamento.
 

Quindi c'è qualcos'altro di interessante che ho trovato, potenzialmente in connessione con "// 0 compare non ha bisogno di questa funzione".

Forse un bug solo nelle ultime versioni, non sono sicuro. Il confronto con 0 non funziona più correttamente. Ho dovuto ricorrere a qualcosa di poco amichevole come

risultato=(int(risultato*100)/100.0); // Risoluzione 2 cifre

Solo per assicurarmi che i valori 0 finissero effettivamente come valori 0.

WHRoeder, grazie. Più studio necessario :)

 

Penso che questo argomento sia trattato con troppa complessità inutile.

Cercate di rendere la vita del vostro programmatore sempre più facile possibile. Scrivete delle definizioni (o andate avanti con i metodi se proprio dovete) in quelle classi dove avete bisogno dei vostri doppi confronti:

// 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 hai bisogno di confrontare due doppi allora usalo in una condizione come questa:

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

Se volete vedere se un doppio è zero (o molto, molto vicino allo zero) usate una condizione come questa:

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


Una nota a margine, dato che vedo molti post che parlano di divisioni:

Con l'incapsulamento tendiamo a dimenticare i costi del codice che viene "esternalizzato" ad alcuni metodi di utilità. Ricordatevi chele divisioni sono computazionalmente molto costose! Soprattutto, una volta avvolte in bei metodi di utilità da qualche parte nelle classi di utilità, cominciamo ad usarle ovunque negli indicatori o negli EA e ci siamo dimenticati da tempo quali passi computazionali eseguono. Quando usiamo lo strategy tester paghiamo un sacco di tempo inutile per la nostra sciatteria.

Regola empirica: Addizioni e sottrazioni sono molto più veloci di moltiplicazioni e divisioni. L'operazione di divisione richiede il tempo di calcolo più alto.Ottimizzate le divisioni- dove possibile! Se il denominatore è fisso come in questo ciclo...

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

allora sostituisci il denominatore x con il suo valore invertito 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.
    // ...
}

Inoltre, se il risultato di una divisione è sempre lo stesso, allora fai il calcolo una volta sola e salva il risultato in una variabile in modo da poterlo usare ovunque nel tuo codice (ad esempio nei loop):

double tradesPerDay = totalTradesPerYear/365;

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

Grazie,

A.T.