Kann Preis != Preis ? - Seite 2

 

Wenn es sich um einen Vergleich handelt, können Sie leicht Ihre eigene Funktion erstellen :

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

Das ist nur ein Gedanke.

 
heelflip43:

Wenn es sich um einen Vergleich handelt, können Sie leicht Ihre eigene Funktion erstellen:

Das ist nur ein Gedanke.


Das ist ein guter Gedanke, danke dafür :-)
 

Die Verwendung von "Point" oder "Point/2.0" ist IMO kein sehr guter Differenzwert. Der Rundungsfehler, der durch NormalizeDouble eingeführt wird (von dem ich mich heute verbrannt habe), ist sicherlich viel kleiner als 8 Stellen, eher 15 Stellen.

In Anbetracht der vorangegangenen Tipps habe ich einige Änderungen vorgenommen und die folgende Routine zusammengestellt, die gut zu funktionieren scheint (sogar mit dem "diff" auf 15 Dezimalstellen), obwohl sie noch nicht rigoros getestet worden ist:

//+------------------------------------------------------------------+
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"); 
 

Hier ist eine weitere mögliche Routine, die vergleichen kann, aber auch intern entweder A und/oder B normalisieren kann und auch die Vergleichsdifferenz (von A-B oder B-A) zu einer größeren Zahl auf der Grundlage von "Ziffern" entspannen wird. Ich bezweifle, dass diese Routine im Vergleich zu dem einfachen "AvsB" oben notwendig ist, aber sie wird für Ihre Verwendung angeboten, wie gewünscht:

//+------------------------------------------------------------------+
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:

Die Verwendung von "Point" oder "Point/2.0" ist IMO kein sehr guter Differenzwert. Der Rundungsfehler, der durch NormalizeDouble eingeführt wird (der mir heute zum Verhängnis wurde), ist sicherlich viel kleiner als 8 Ziffern, eher 15 Ziffern.

Sie wollen den größten Wert, der nicht als Rundungsfehler angesehen werden kann, oder gleichbedeutend den kleinsten Wert, der nicht als Preisänderung angesehen werden kann. Da sich Preise nur um ein Vielfaches von Punkten ändern können, ist Punkt/2 genau das.

Der doppelte Wert des Brokers könnte irgendwo zwischen 1,234575000000000000 und 1,23458499999999999 liegen und immer noch als derselbe Preis von 1,23458 angesehen werden.

Hätten Sie dies verwendet, hätten Sie das Problem nicht gehabt:

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.)
 

Sollten wir die Verwendung von normalisedouble vermeiden?

oder vielleicht.. ich habe eine Idee, dass wir dieMathRound-Funktion verwenden können

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

so können wir die Funktion

double round ( double value )

{ int D= MathPow(10,Digits);

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

return(x);

} 
 
*Schüttelt seine Krawatte mit zwei Fingern in Position* Verwende normalize double nur bei Berechnungen, die einen doppelten Wert beinhalten, nicht nur überall, wo es einen doppelten Wert gibt.
 
tonny:
*Schüttelt seine Krawatte mit zwei Fingern in Position* Verwenden Sie normalize double nur in Berechnungen, die einen Double-Wert beinhalten, nicht einfach überall, wo es einen Double-Wert gibt.
Oder verwenden Sie NormalizeDouble() überhaupt nicht, die meiste Zeit, wenn es verwendet wird, gibt es absolut keine Notwendigkeit, es zu verwenden ... Fehler 4107 kann durch die Verwendung von NormalizeDouble() behoben werden, aber es gibt andere Möglichkeiten. Jeder Preis, der aus vordefinierten Variablen oder Zeitreihenfunktionen stammt, muss niemals normalisiert werden, ebenso wenig wie das Ergebnis einer mit Punkt multiplizierten Ganzzahl.
 
WDholic:

Sollten wir die Verwendung von normalisedouble vermeiden?

oder vielleicht.. ich habe eine Idee, dass wir die MathRound-Funktion verwenden können

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


Man hat dann immer noch einen Double und die Möglichkeit, dass der Preis != Preis ist.

Ich bin zu dieser Lösung gekommen, die doubles in ints umwandelt, um doubles zu vergleichen . . .

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

so dass . . .

Flat(price) != Flat(price)

niemals wahr sein wird.

 
Viel Rechenarbeit anstelle der einfachen Lösung