[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Precision Errors



PureBytes Links

Trading Reference Links

More on this seemingly endless thread. The short version:

  > TradeStation numeric variables seem to be all single-precision
    floats with a precision of +-2^24 = +-16,777,216

  > TradeStation 4.0 can handle numbers as big as 2.147483 * 10^15
    in some of the math routines. Beyond that they have big errors
    (with no error messages).

  > In response to several private messages from people wondering
    why I think this is so important, I describe (with an example)
    errors produced by the Omega LinearRegSlope function and show
    alternate code for the same function that is much faster,
    simpler, and more accurate.

-----------

At 2:32 AM +0200 7/24/01, pierre.orphelin wrote:

> > >My 9999999 limit in the average_WC test was beyond this limit to
>> >avoid to have a part of the higher number carried by the exponent at
>> >the detriment of the mantissa.
>>
>> This and your comment above indicate that you think that TradeStation
>> uses integer arithmetic up to +-2^31 and floating point (24 bit
>> mantissa and 8 bit exponent) for bigger numbers. Perhaps you are
>> correct but I seriously doubt it. (Most other programming languages
>> allow the programmer to specify this explicitly but EasyLanguage does
>> not.) I understood that all numbers were handled as floats. It would
>> be very time consuming to check all arithmetic operations at run time
>> and do any required integer-to-float conversions. Does anybody else
>> know for sure?
>>

I thought of a test that would determine whether your perception that
Tradestation could handle integer arithmetic up to +-2^31. The bottom
line is that it can't. All numeric variables seem to be
single-precision floats as I suspected.

I ran the following code:

    Vars: k(0);
    if LastBarOnChart then begin
       for j = 1 to 16777215 begin
          k = k + 1;
       end;
       Print(j:20:15, k:20:15);
    end;

I figured that if the compiler used integer arithmetic anywhere, it
would use it for the index of the loop, which has to be an integer.

The code ran fine and printed the values.

I then changed the third line of the code to:

       for j = 1 to 16777216 begin

with everything else the same except the loop count and the program
never terminated on TS4.0. It required killing the execution.

Since 2^24 = 16,777,216, which is the largest integer that can be
represented in the single precision float, it is obvious that once
that value is reached, incrementing "j" by 1 will no longer work
since the value 1 is then less than the least significant binary bit.
So with the limited precision, the loop counter 16,777,216 + 1 =
16,777,216 forever so the loop will never terminate.

The following also works:

       for j = -16777216 to 16777215 begin

proving that integers can range from -16777216 to 16777215 but

       for j = -16777219 to 16777215 begin

never terminates because -16777219 is outside the range as above.

So it appears as if all numeric variables in TradeStation 4.0 are
single precision floats and you cannot increment integers as large
as 2^31.


> > If all numbers are floats, as I believe, your 9999999 limit is much
>> smaller than the actual limit. My tests show that the limit would be
>> at least:
>>
>>     1,234,567,948,140,544.
>
>No, it cannot!
>the above number has 16 digits,and the last 8 digits are pure garbage.
>It cannot be coded in the 2^24  mantissa with that precision (that is
>limited to 8 digits in a decimal base).

I did not say it was accurate to 16 digits. I said it could be that
large and it can. I did more testing and found that TS4.0 can handle
a number as large as:

    2.147483 * 10^15

before the IntPortion and FracPortion functions go berserk. (Other
functions may go berserk at smaller numbers.)

The floating point format can handle 3.40 * 10^38 but TradeStation
limits this to a lower value. (TS2000i seems to have a higher limit
than 2.147483 * 10^15.)


>The theoretical limit should be 8388608 (2^24-1), but it may slightly
>differ.

In this country 2^24-1 = 16,777,215 but I agree that 2^24 is
the maximum integer that can be accurately represented (such that you
can increment it by 1).


>Again, you cannot expect more precision by converting a 23 bit number (base
>2) into a base 10, so you do not have the right to display the extra Ts
>garbage numbers.

I was displaying what TradeStation displayed. Sorry if this offends you.


>And TS should not display them...

Tell that to Omega.


>I am also tired  to see the sempiternal complaint about bugs that are not
>bugs, misunderstanding of basic maths ( what I may understand), but what I
>do not like is that it always ends by TRAD fault ( what I CANNOT  always
>understand).

Where I come from users would expect the function library provided by
Omega to be coded so that it was accurate with the arithmetic
provided in the Omega product it is part of. That is not the case.
Customers should not have to write special versions of the functions
to "work-around" errors in the function library. The techniques to
write routines consistent with the limited precision arithmetic are
well known and taught as part of most computer science programs. It
still seems as if Omega doesn't care about accuracy in their product
and until they do, I am sure you and Omega will continue to hear
these kinds of complaints.

>And when I disagree, I'm a little bit sarcastic, you know...

We've noticed... But I think you might better use your influence at
Omega (aka: TradeStation, Inc) to get them to understand this is
important rather than just beating up on people who are just trying
to understand the product and tell it like it is.

-----

I had several private messages asking why this is important "since
nobody needs to plot a chart to 7 significant digits of precision".
The problem is that several of the Omega functions as they are
written use code that subtracts two very big numbers that are very,
very nearly the same value. In these cases, the accuracy of the
result may be accurate to only one or two significant digits.

As an example, I ran a test on the Omega LinearRegSlope function
applied to the Close of the DJIA using a length of 100 daily bars. (I
made a copy of the Omega code and added code to track the value of
the various variables.)

There is one equation in the function:

    Num1 = Len*Sum1 - Sum2

where both terms are very large numbers - in the billions - and very
nearly the same.

There were 38 bars where the following condition was true:

     Condition1 = AbsValue(Num1 / Sum2) < 0.0001;

In those cases, 5 of the 7 digits of precision were lost, leaving
2 digit of precision.

There were 6 bars where this condition was true:

     Condition1 = AbsValue(Num1 / Sum2) < 0.00002;

In those cases, almost 6 of the 7 digits of precision were lost,
leaving 1 digit of precision.

The crime is that there is a better algorithm for the exact same
function that gives the correct result to 7 digits of precision, 
runs probably an order of magnitude faster, and has almost half the
number of lines of code. (See code appended below.)

There are many other such cases. Gary and previous posts in this
thread discussed others.

I run into this error at least once a week on something and have to
program some "work-around". There are many cases where over half of
the bars have visible errors on a plot with some of my calculations.

So although we do not need high precision in the results, we may need
it for the internal calculations. But there are well known ways to
program around such limitations and I sure wish Omega would use these
methods to fix their function library...


Bob Fulks


------------

{ *******************************************************************

   Study         : LinRegSlope
  
   Last Edit     : 9/23/99

   Provided By   : Bob Fulks

   Description   : Calculates the value of the linear regression slope.
      Gives the same result as the Omega "LinearRegSlope" function but
      is much faster. Uses a FIR filter implementation.
                 
      © 1999 Robert G. Fulks, All rights reserved.

********************************************************************}
Inputs :  Price(NumericSeries), Length(NumericSimple);
Vars   :  Sum(0), Counter(0), Factor(0), Offset(0), Delta(0);

Sum       = 0;
Offset    = 6 / (Length * (Length + 1));
Delta     = 2 * Offset / (Length - 1);

for Counter = 0 to Length - 1 begin
   Factor   = Offset - Counter * Delta;
   Sum      = Sum + Price[Counter] * Factor;
end;

LinRegSlope = Sum;