Can price != price ? - page 2

To add comments, please log in or register
heelflip43
91
heelflip43  

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.

Simon Gniadkowski
17201
Simon Gniadkowski  
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 :-)
pips4life
129
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.

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"); 
pips4life
129
pips4life  

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
//+------------------------------------------------------------------+
William Roeder
19988
William Roeder  
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.)
Bambang Sugianto
12885
Bambang Sugianto  

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

} 
FxAutomatedcom
1054
FxAutomatedcom  
*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.
Simon Gniadkowski
17201
Simon Gniadkowski  
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.
Simon Gniadkowski
17201
Simon Gniadkowski  
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.

William Roeder
19988
William Roeder  
At lot of computation instead of the simple solution
To add comments, please log in or register