Può il prezzo != prezzo ? - pagina 2

 

Se è per il confronto, allora si potrebbe facilmente creare la propria funzione:

bool checkDoubles(double a, double b, string check)
{
if(check==">"){
if (a - b > Point / 2)return(1);else return (0);
}else if(check=="<"){
if (b - a > Point / 2)return(1);else return (0);
}else if(check==">="){
if (a - b > -Point)return(1);else return (0);
}if(check=="<="){
if (b - a > -Point)return(1);else return (0);
}else if(check=="!="){
if (MathAbs(a - b) > Point / 2)return(1);else return (0);
}else {
Print("Sorry you've entered a wrong check value");
}
return (0);
}

È solo un pensiero.

 
heelflip43:

Se è per il confronto, si potrebbe facilmente creare la propria funzione:

È solo un pensiero.


È un buon pensiero, grazie :-)
 

L'uso di "Point" o "Point/2.0" non è un valore di differenza molto buono, IMO. L'errore di arrotondamento introdotto da NormalizeDouble (che mi ha bruciato oggi), è certamente molto più piccolo di 8 cifre, più probabilmente 15 cifre.

Visti i suggerimenti precedenti, ho apportato alcune modifiche e messo insieme la seguente routine che sembra funzionare bene (anche usando il "diff" a 15 cifre decimali), anche se non è stata ancora testata rigorosamente:

//+------------------------------------------------------------------+
bool AvsB(double A, string checkStr, double B)
{
   //checkStr = StringTrimLeft(StringTrimRight(checkStr));
   double diff = 0.000000000000001; // 15 decimal places
   //double diff = 0.000000005;
   //double diff = 0.00000001;
   if     (checkStr == ">" ){if (A - B >  diff)return(true);else return(false);}
   else if(checkStr == "<" ){if (B - A >  diff)return(true);else return(false);}
   else if(checkStr == ">="){if (A - B > -diff)return(true);else return(false);}
   else if(checkStr == "<="){if (B - A > -diff)return(true);else return(false);}
   else if(checkStr == "!="){if (MathAbs(A - B) >  diff)return(true);else return(false);}
   else if(checkStr == "=" || checkStr == "=="){if (MathAbs(A - B) <  diff)return(true);else return(false);}
   else {Print("Sorry, bad usage: AvsB(A, checkStr, B).  Wrong checkStr value: ",checkStr);}
   return(false);
} // end of AvsB
//+------------------------------------------------------------------+

Here is a check of the obvious:

   if (1.34929 == NormalizeDouble(1.34929 , 5))  Alert("MT4 Pass");
   else Alert("MT4 FAIL.  ROUNDOFF BUG");    // Yes, this is what MT4 does, a fail.

   if (AvsB(1.34929 ,"==", NormalizeDouble(1.34929 , 5)))  Alert("AvsB Pass");  // It does pass using the AvsB routine!
   else Alert("AvsB FAIL.  ROUNDOFF BUG"); 
 

Ecco un'altra possibile routine che può confrontare, ma può anche normalizzare internamente sia A e/o B, e anche rilassare la differenza di confronto (di A-B o B-A) a un numero più grande basato su "cifre". Dubito che questa routine sia necessaria rispetto alla semplice "AvsB" di cui sopra, ma è offerta per il vostro uso come desiderato:

//+------------------------------------------------------------------+
bool AvsB_nA_nB_digits(double A, string checkStr, double B, bool normalizeA, bool normalizeB, int digits)
{
   //checkStr = StringTrimLeft(StringTrimRight(checkStr));
   if (normalizeA) A = NormalizeDouble(A,MathMin(8,digits));
   if (normalizeB) B = NormalizeDouble(B,MathMin(8,digits));
   
   double diff;
   switch(digits)
   {
      case 0  : diff = 0.5; break; // Or 1.0 ??
      case 1  : diff = 0.1; break;
      case 2  : diff = 0.01; break;
      case 3  : diff = 0.001; break;
      case 4  : diff = 0.0001; break;
      case 5  : diff = 0.00001; break;
      case 6  : diff = 0.000001; break;
      case 7  : diff = 0.0000001; break;
      case 8  : diff = 0.00000001; break;
      case 9  : diff = 0.000000001; break;
      case 10 : diff = 0.0000000001; break;
      case 11 : diff = 0.00000000001; break;
      case 12 : diff = 0.000000000001; break;
      case 13 : diff = 0.0000000000001; break;
      case 14 : diff = 0.00000000000001; break;
      default : diff = 0.000000000000001; break; // 15 decimal places max (I think)
   }
   
   if     (checkStr == ">" ){if (A - B >  diff)return(true);else return(false);}
   else if(checkStr == "<" ){if (B - A >  diff)return(true);else return(false);}
   else if(checkStr == ">="){if (A - B > -diff)return(true);else return(false);}
   else if(checkStr == "<="){if (B - A > -diff)return(true);else return(false);}
   else if(checkStr == "!="){if (MathAbs(A - B) >  diff)return(true);else return(false);}
   else if(checkStr == "=" || checkStr == "=="){if (MathAbs(A - B) <  diff)return(true);else return(false);}
   else {Print("Sorry, bad usage: AvsB(A, checkStr, B).  Wrong checkStr value: ",checkStr);}
   return(false);
} // end of AvsB_nA_nB_digits
//+------------------------------------------------------------------+
 
pips4life:

L'uso di "Point" o "Point/2.0" non è un valore di differenza molto buono, IMO. L'errore di arrotondamento introdotto da NormalizeDouble (che mi ha bruciato oggi), è certamente molto più piccolo di 8 cifre, più probabilmente 15 cifre.

Volete il valore più grande che non può essere considerato un errore di arrotondamento o, equivalentemente, il valore più piccolo che non può essere considerato un cambiamento di prezzo. Poiché i prezzi possono cambiare solo di un multiplo di punto, punto/2 è proprio questo.

Il valore doppio dal broker potrebbe essere ovunque da 1.23457500000000 a 1.23458499999999999 ed essere ancora considerato lo stesso prezzo 1.23458.

Se avessi usato questo, non avresti avuto il problema:

if (a > b)
if (a - b > Point / 2.)
if (a >= b)
if (a - b > -Point/2.)
if (a != b)
if (MathAbs(a - b) > Point / 2.)
 

dovremmo evitare di usare normalisedouble?

o forse... ho pensato che possiamo usare lafunzione MathRound

ex . doppio x= (MathRound( 1.37883 * 100000)) / 100000 ;

così possiamo fare la funzione

double round ( double value )

{ int D= MathPow(10,Digits);

double x =  ( MathRound (value * D)) / D ;

return(x);

} 
 
*Usa solo normalizzare il doppio nei calcoli che coinvolgono un valore doppio, non solo ovunque ci sia un doppio.
 
tonny:
*Usa NormalizeDouble solo nei calcoli che coinvolgono un valore doppio, non ovunque ci sia un doppio.
O semplicemente non usate affatto NormalizeDouble(), la maggior parte delle volte quando viene usato non c'è assolutamente bisogno di usarlo. . . l'errore 4107 può essere affrontato usando NormalizeDouble(), ma ci sono altri modi. Qualsiasi prezzo che proviene da variabili predefinite o funzioni di serie temporali non avrà mai bisogno di essere normalizzato, e nemmeno il risultato di un intero moltiplicato per Point.
 
WDholic:

dovremmo evitare di usare normalisedouble?

o forse... ho pensato che possiamo usare la funzione MathRound

ex . doppio x= (MathRound( 1.37883 * 100000)) / 100000 ;


Si finisce ancora con un doppio e ancora la possibilità di prezzo != prezzo

Sono arrivato a questa soluzione che trasforma i doppi in ints allo scopo di confrontare i doppi . . .

int Flat(double ValueToFlatten)
   {
   double Power = MathPow(10, Digits);
   int ReturnValue;
   
   ReturnValue = MathRound(Power * (ValueToFlatten + (4.9/ (Power*10) ) ) ) ;
   return (ReturnValue);
   
   }

in modo che . . .

Flat(price) != Flat(price)

non sarà mai vero.

 
Un sacco di calcoli invece della soluzione semplice