Can price != price ? - page 2

 

If it's for comparison then you could easily create your own function:

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

It's just a thought.

 
heelflip43:

If it's for comparison then you could easily create your own function:

It's just a thought.


It's a good thought, thank you for it :-)
 

The use of "Point" or "Point/2.0" is not a very good difference value, IMO. The roundoff error introduced by NormalizeDouble (which I got burned by today), is certainly much smaller than 8 digits, more likely 15 digits.

Given the previous tips, and made some changes and put together the following routine which seems to work fine (even using the "diff" to 15 decimal places), although it hasn't been rigorously tested yet:

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

Here's yet another possible routine that can compare, but can also internally normalize either A and/or B, and will also relax the comparison difference (of A-B or B-A) to a larger number based on "digits". I doubt this routine is necessary compared to the simple "AvsB" above, but it's offered for your use as desired:

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

The use of "Point" or "Point/2.0" is not a very good difference value, IMO. The roundoff error introduced by NormalizeDouble (which I got burned by today), is certainly much smaller than 8 digits, more likely 15 digits.

You want the biggest value that can not be considered roundoff error or equivalently, the smallest value that can not be considered a price change. Since prices can only change by a multiple of point, point/2 is just that.

The double value from the broker could be anywhere from 1.234575000000000000 through 1.23458499999999999 and still be considered the same 1.23458 price.

If you had used this, you wouldn't have had the problem:

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

should we avoid using normalisedouble  ??

or may be.. i have a thought that we can use  MathRound function

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

 

so we can make function

 

double round ( double value )

{ int D= MathPow(10,Digits);

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

return(x);

} 
 
*Shakes his tie into position with two fingers* Only use normalize double in calculations involving a double value not just everywhere there is a double.
 
tonny:
*Shakes his tie into position with two fingers* Only use normalize double in calculations involving a double value not just everywhere there is a double.
Or just don't use NormalizeDouble() at all,  most of the time when it is used there is absolutely no need to use it . . .  error 4107 can be addressed by using NormalizeDouble(),  but there are other ways.  Any price that comes from Predefined Variables or timeseries functions will never need to be Normalized,  neither will the result of an integer multiplied by Point.
 
WDholic:

should we avoid using normalisedouble  ??

or may be.. i have a thought that we can use  MathRound function

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


You still end up with a double and still the possibility of  price != price

I arrived at this solution which turns doubles into ints for the purpose of comparing doubles . . .

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

 so that . . .

Flat(price) != Flat(price)

 will never be true.

 
At lot of computation instead of the simple solution
Reason: