ADX is wrong?

Hi,
I’m using ADX for some of my models. Specifically, I use ADX(150,21).
ADX should give results between 0 and 100, yet for some stocks I get values in the trillions.
For example check out ADX(150,21) for Boeing (NYSE:BA).
Is the ADX in portfolio123.com broken?

As I too use ADX I ran a test. Indeed something is amiss. Up to ADX(75,0) values are as expected. From ADX(76,0) to ADX(100,0) values are Zero. From ADX(101,0) and up values are in the billions and trillions.

We’re investigating now.

The existing faulty ADX works well for me in some situations.
If you find an error, please don’t just run it over.
I wish that you keep it working because I rely on it in my algos. You may want to name it ADX_obsolete or ADX_legacy or something.

I wish that you publish the current formula of ADX, even if it faulty. I want to understand why using this potentially faulty parameter works so well in some situations.
Thanks.

Confirmed. Looks like some kind of buffer overrun for high period values. Very sorry about this, should have been tested more thoroughly. Fix coming soon.

Thanks.
But please keep the legacy faulty ADX running for some time (potentially under a different name), to allow us the time to test the fixed ADX and transition to it slowly.
Please provide a report on the exact calculation of the old and new ADX so we’d understand why it behaved so well (for me).
I’d like to understand if the fixed ADX and the old ADX are correlated, i.e., if I FRANK both, do I get the same ranking.

tal_dn , I don’t think there’s anything wrong with ADX with periods < 75 and for periods> 75 looks like garbage. But we’ll know for sure soon. Are you using ADX with periods < 75 ?

I’m using ADX(150,21). I’ll send an email with some of my finding. Not posting as wish to keep details about my model confidential.

We just posted a correction to the ADX function.

There are two things that changed in the function. First, we discovered that the original function wasn’t loading data correctly when the first parameter – the period that you’re examining – was higher than 74. This means that we were delivering zeroes when it was from 75-99 and then garbage afterward. This has been fixed, and it should be good through the maximum for that parameter, 150.

Second, there is now some more smoothing in the function. This smoothing increases as the period increases.

We have made the old function available for a limited time so that you can do a comparison between the old and new versions. To use the new function, just…y’know, use the function.

To use the old function, add this:

ADX(14,0,#Close,1)

Everything after the zero is optional, and the one at the end causes the old behavior to be used.

I should be clear here: The old output for periods 75 and above was a bug and it was garbage, even if it was consistent garbage. We will not be rolling that back. The comparison is to look at the results for uses of the function that were for periods 74 and below.

Thanks for fixing.
But I really ask that you provide an elaborate description of the error, prior to the fix.
Let me explain why this is important.
I use adx(150,21) in several portfolios, both momentum and value. I discovered that stocks in which adx(150,21) has lower values outperform stocks with higher adx(150,21) values. The outperformance is consistent across different market caps, different time frames and different universes. It also looks good in rolling tests. Somehow, the ADX(150,21) is a source of alpha, and a significant one.
The garbage that is being loaded for adx(150,21) is not random. It is consistent. Although it does not perform its intended function, it did something good. And I must understand what it did. I would argue that it is not garbage at all, rather an important signal.
Ranking stocks according to adx(150,21) and charting a histogram shows a monotonous behavior - lower adx stocks outperform higher adx stocks.
It would not be the first valuable indicator that is discovered by chance.
Please investigate and elaborate on the nature of the data that is being loaded for adx(150,21).
I am willing to meet you and show you several portfolios rigorously tested with and without adx(150,21).
Thanks.

I agree with tal_dn.
I also get much better return and smoother performance curve with the old ADX formula.
I suggest that you leave the option to use the old formula, making clear that for >= 75 the formula does not provide the ADX but something else which for some unknown reasons appears to work very well in improving performance.

Also I get different results for a period of 74 when using the old and new formula. Results are significantly better with the old formula. So there is a difference in the formulas, even for periods less than 75. Perhaps this is due to the smoothing which the new formula incorporates.

If the above is correct then the old formula should provide the same results for periods of 75 and 99. I tested this and get different results. So obviously the old formula does not only provide zeros for periods 75 to 99.

To shed some light on the kind of nonsense going on that’s giving apparently meaningful values:
Running the old [font=courier new]ADX(150, X)[/font], it reads the output from [font=courier new]out[outNbElement-1][/font] where [font=courier new]outNbElement[/font] is 0 (read index -1 of stack array [font=courier new]out[/font]) as a double-precision real, which actually corresponds to addresses in the stack for the two most recent sample in the high price buffer, which are single-precision reals. So what’s actually happening is it’s taking the bits from two single-precision reals and is munging them together.
If I run [font=courier new]ADX(150, 0)[/font] for AAPL today, that means:[]taking the bits [font=courier new]0x4332D1EC[/font] ([font=courier new]Hi(1)[/font], [font=courier new]178.820007[/font]) and the bits for [font=courier new]0x432F63D7[/font] ([font=courier new]Hi(0)[/font], [font=courier new]175.389999[/font]),
[
]concatenating them to get [font=courier new]0x432F63D74332D1EC[/font],
[*]and reinterpreting that as a double-precision real, giving the final value of [font=courier new]4.417750237276406e15[/font].When using ADX with period in the range 101-150 and offset X, you’ll always find that values to be loosely correlated to the magnitude of [font=courier new]Hi(X)[/font].
Things get hairier when periods 75-100 are involved because it’s truly reading uninitialized stack (chaotic junk).

The “chaotic junk” works well in this model.
I get almost double the Total Return with the old ADX.
I am using sell rule:
ADX(75,0,#close,1) < ADX(75,5,#close,1) & rank<= 97 & nodays>12 // with old ADX
and
ADX(75,0,#close) < ADX(75,5,#close) & rank<= 97 & nodays>12 // with new ADX



Besides the bug with periods 75 or greater the other fix we did is to increase how much data is included in the averages. Old ADX was using no more than 200 bars to smooth the averages. This was done for efficiency, and works fine for short periods, like 14. For longer periods 200 bars max produces very jagged line. See below for ADX(50) old in blue vs new in red for IBM.

Sorry about this. We should have done a visual inspect for longer periods.


2 possible conclusions:

  • the chaotic junk works
  • this is 2 outcomes of a non-ergodic game for which doubling the gain on 19 years is in the range of uncertainty.
    The second possible conclusion has nothing to do with the quality of the model (which looks excellent in this case), but a lot with the way we use and look at simulations.
    From my modest experience, triggering sell rules more often means more possible butterfly effects.

We’ve decided that it’s time to place a date on removing the testing parameter for ADX. That date is June 14th. Please make adjustments to your systems before then.