ta-lib-python icon indicating copy to clipboard operation
ta-lib-python copied to clipboard

Calculation Error?

Open paris0120 opened this issue 3 years ago • 48 comments

I'm developing a similar library and testing the results with this lib (https://github.com/paris0120/talibjs.git ). I find that there might be some calculation errors. I compare the results with the python version and look into the algorithm in Java. For example ADX, line 524 525:

                                                prevMinusDM /= (double)optInTimePeriod;
                                                prevPlusDM /= (double)optInTimePeriod;

I believe that they should be

                                                prevMinusDM -=prevMinusDM /(double)optInTimePeriod;
                                                prevPlusDM -= prevPlusDM /(double)optInTimePeriod;

I also got different results with ATR. However, both the trueRange and SMA function work correctly but the ATR doesn't have the correct number. (I calculated manually to verify that my version has the correct number).

paris0120 avatar May 23 '22 17:05 paris0120

Could you provide a direct links to the code lines you are comparing?

trufanov-nok avatar May 26 '22 17:05 trufanov-nok

I don't think that it's publicly available. All the functions are in the core.class.

paris0120 avatar May 26 '22 20:05 paris0120

This is ADX code from TA-Lib C library, which is under the hood of this python wrapper:
https://github.com/TA-Lib/ta-lib/blob/master/src/ta_func/ta_ADX.c#L414 It contains:

      prevMinusDM -= prevMinusDM/optInTimePeriod;
      prevPlusDM  -= prevPlusDM/optInTimePeriod;

All the functions are in the core.class.

Where I can find that core.class file?

trufanov-nok avatar May 27 '22 10:05 trufanov-nok

I have no idea where it goes wrong but here is my worksheet. The results with talib for dx is array([ nan, nan, nan, nan, 100. , 58.70967742, 55.64929196, 71.1993739 , 71.1993739 , 26.23631438])

h 146.59 145.74 145.7 145.47 145.12 145.26 145.27 145.25 145.01 145.13
l 145.85 145.53 145.4 145 144.92 145 145.12 144.91 144.92 144.93
c 146.2 145.58 145.47 145.12 145.03 145.11 145.25 144.98 144.98 145.1
tr nan 0.67 0.3 0.47 0.2 0.26 0.16 0.34 0.09 0.2
trsum         581.2 581.01 581.0075 580.7356 580.5317 580.4988
atr         145.3 145.2525 145.2519 145.1839 145.1329 145.1247
up   -0.85 -0.04 -0.23 -0.35 0.14 0.01 -0.02 -0.24 0.12
down   0.32 0.13 0.4 0.08 -0.08 -0.12 0.21 -0.01 -0.01
pdm   0 0 0 0 0.14 0.01 0 0 0.12
ndm   0.32 0.13 0.4 0.08 0 0 0.21 0 0
psum         0 0.14 0.115 0.08625 0.064688 0.168516
nsum         0.93 0.6975 0.523125 0.602344 0.451758 0.338818
pdi         0 0.000241 0.000198 0.000149 0.000111 0.00029
ndi         0.0016 0.0012 0.0009 0.001037 0.000778 0.000584
dx         100 66.56716 63.9569 74.94894 74.94894 33.56817

paris0120 avatar May 27 '22 12:05 paris0120

test script with python

h = np.array([146.59,145.74,145.7,145.47,145.12,145.26,145.27,145.25,145.01,145.13]); l = np.array([145.85,145.53,145.4,145.0,144.92,145.0,145.12,144.91,144.92,144.93]); c = np.array([146.2,145.58,145.47,145.12,145.03,145.11,145.25,144.98,144.98,145.1]); talib.ADX(h, l, c, 4)

paris0120 avatar May 27 '22 12:05 paris0120

I'm running:

import talib import numpy as np h = np.array([146.59,145.74,145.7,145.47,145.12,145.26,145.27,145.25,145.01,145.13]); l = np.array([145.85,145.53,145.4,145.0,144.92,145.0,145.12,144.91,144.92,144.93]); c = np.array([146.2,145.58,145.47,145.12,145.03,145.11,145.25,144.98,144.98,145.1]); talib.ADX(h, l, c, timeperiod=4)

And getting

array([        nan,         nan,         nan,         nan,         nan,
               nan,         nan, 71.38958582, 71.34203284, 60.06560322])

Could you recheck your results?

trufanov-nok avatar May 27 '22 17:05 trufanov-nok

I tracked back to DX. I can't go further because there is no function for DM and DI. The results above is for DX. For ADX it should be [null, null, null, null, null, null, null, 76.36825350866403, 76.01342634661, 65.40211226154518]

paris0120 avatar May 27 '22 17:05 paris0120

Here is the working sheet:

h 146.59 145.74 145.7 145.47 145.12 145.26 145.27 145.25 145.01 145.13
l 145.85 145.53 145.4 145 144.92 145 145.12 144.91 144.92 144.93
c 146.2 145.58 145.47 145.12 145.03 145.11 145.25 144.98 144.98 145.1
tr nan 0.67 0.3 0.47 0.2 0.26 0.16 0.34 0.09 0.2
trsum         581.2 581.01 581.0075 580.7356 580.5317 580.4988
atr         145.3 145.2525 145.2519 145.1839 145.1329 145.1247
up   -0.85 -0.04 -0.23 -0.35 0.14 0.01 -0.02 -0.24 0.12
down   0.32 0.13 0.4 0.08 -0.08 -0.12 0.21 -0.01 -0.01
pdm   0 0 0 0 0.14 0.01 0 0 0.12
ndm   0.32 0.13 0.4 0.08 0 0 0.21 0 0
psum         0 0.14 0.115 0.08625 0.064688 0.168516
nsum         0.93 0.6975 0.523125 0.602344 0.451758 0.338818
pdi         0 0.000241 0.000198 0.000149 0.000111 0.00029
ndi         0.0016 0.0012 0.0009 0.001037 0.000778 0.000584
dx         100 66.56716 63.9569 74.94894 74.94894 33.56817
sum               305.473 304.0537 261.6084
adx               76.36825 76.01343 65.40211

paris0120 avatar May 27 '22 17:05 paris0120

Ок, so we discussing DX. Could you show how your DX is calculated?

trufanov-nok avatar May 27 '22 17:05 trufanov-nok

I track the issue to dx. dx to adx is correct.

Here is my code. The results are consistent with the ones from the worksheet above. https://github.com/paris0120/talib.ts/blob/dev/src/index.ts#L433

paris0120 avatar May 27 '22 17:05 paris0120

I don't apply abs there coz I don't think that it makes sense, so the result there will be negative.

paris0120 avatar May 27 '22 17:05 paris0120

I don't know Typescript.... Could you veify your tRange()?
The TA-Lib's implementation (particularly used in DX) is:

   #define TRUE_RANGE(TH,TL,YC,OUT) {\
      OUT = TH-TL; \
      tempReal2 = std_fabs(TH-YC); \
      if( tempReal2 > OUT ) \
         OUT = tempReal2; \
      tempReal2 = std_fabs(TL-YC); \
      if( tempReal2 > OUT ) \
         OUT = tempReal2; \
   }

Note the std_fabs.
Your is tRange: h.subtract(l).max(h.distance(c)).max(l.distance(c)). I guess without abs it should return wrong value.

trufanov-nok avatar May 31 '22 10:05 trufanov-nok

trange works fine. I have the same result as talib. > I don't know Typescript.... Could you veify your tRange()?

The TA-Lib's implementation (particularly used in DX) is:


   #define TRUE_RANGE(TH,TL,YC,OUT) {\

      OUT = TH-TL; \

      tempReal2 = std_fabs(TH-YC); \

      if( tempReal2 > OUT ) \

         OUT = tempReal2; \

      tempReal2 = std_fabs(TL-YC); \

      if( tempReal2 > OUT ) \

         OUT = tempReal2; \

   }

Note the std_fabs.

Your is tRange: h.subtract(l).max(h.distance(c)).max(l.distance(c)). I guess without abs it should return wrong value.

paris0120 avatar May 31 '22 11:05 paris0120

I've successfully installed talibjs with: npm install talib.ts@latest --S But then

$ nodejs 
Welcome to Node.js v12.22.9.
Type ".help" for more information.
> import { TALib } from 'talibjs';
import { TALib } from 'talibjs';
^^^^^^

Uncaught:
SyntaxError: Cannot use import statement inside the Node.js repl, alternatively use dynamic import

How can I set up a working example to reproduce a problem?

trufanov-nok avatar May 31 '22 11:05 trufanov-nok

this is a library. Download my repository. run

  1. npm install
  2. npm run test

you can find the test script in test/test.ts. you can add this for tRange test

    expect(TALib.tRange(high, low, close).tRange.getValue()).toEqual([null, 0.6699999999999875, 0.29999999999998295, 0.46999999999999886, 0.20000000000001705, 0.2599999999999909, 0.1599999999999966, 0.3400000000000034, 0.09000000000000341, 0.19999999999998863,]);

paris0120 avatar May 31 '22 11:05 paris0120

I also got different results with ATR. However, both the trueRange and SMA function work correctly but the ATR doesn't have the correct number. (I calculated manually to verify that my version has the correct number).

Let's discuss ATR. SMA there is used only to calculate very first value (which is just average) then another smoothing is applied:

After that, Wilder sought to smooth the data by incorporating the previous period's ATR value.

Current ATR = [(Prior ATR x 13) + Current TR] / 14

  • Multiply the previous 14-day ATR by 13.
  • Add the most recent day's TR value.
  • Divide the total by 14

https://school.stockcharts.com/doku.php?id=technical_indicators:average_true_range_atr

In TA-Lib this smoothing looks like:

   while( --nbATR != 0 )
   {
      prevATR *= optInTimePeriod - 1;
      prevATR += tempBuffer[today++];
      prevATR /= optInTimePeriod;
      outReal[outIdx++] = prevATR;
   }

The code is here: https://github.com/TA-Lib/ta-lib/blob/master/src/ta_func/ta_ATR.c#L281

This smoothing looks very similar to your modifiedMovingAverage. I also noticed in di(): let atr =this.tRange(high, low, close).tRange.modifiedMovingAverage(period); Which is differs from your regular atr calculation.

But I suspect that modifiedMovingAverage may be not exactly the same smoothing as in TA'Lib.
Bcs in TA-Lib:

nextATR = (prevATR*(period-1) + value) / period = prevATR - prevATR/period + value / period =
prevATR - (prevATR + value) / period

In your modifiedMovingAverage the loop is

sum += this.value[i];
                if (c >= period) {
                    output.push(sum / period);
                    sum -= sum / period;
                }

i'm not sure if they are equal. Could you doublecheck?

trufanov-nok avatar May 31 '22 16:05 trufanov-nok

ATR is calculated with SMA. DI is calculated with modified ma as you suggested

https://github.com/paris0120/talib.ts/blob/dev/src/index.ts#L412

paris0120 avatar May 31 '22 17:05 paris0120

ATR is calculated with SMA

Why it's calculated with SMA?

trufanov-nok avatar May 31 '22 18:05 trufanov-nok

I follow the method here.

https://www.investopedia.com/terms/a/atr.asp

However, how I calculate ATR doesn't affect ADX because ADX is calculated with modified MA instead of SMA as I showed you above.

paris0120 avatar May 31 '22 19:05 paris0120

ADX is calculated with modified MA instead of SMA as I showed you above. And I said I suspect your modified MA is wrong too, but didn't compared them in details yet.

I follow the method here. https://www.investopedia.com/terms/a/atr.asp

In this case I could say that TA-Lib's ATR calculation is based on approach of its inventor, which is described in wiki: https://en.wikipedia.org/wiki/Average_true_range
Also I noticed that investopedia's article is controversial. There is a paragraph:

Example of How to Use the Average True Range (ATR) As a hypothetical example, assume the first value of the five-day ATR is calculated at 1.41 and the sixth day has a true range of 1.09. The sequential ATR value could be estimated by multiplying the previous value of the ATR by the number of days less one, and then adding the true range for the current period to the product.

Next, divide the sum by the selected timeframe. For example, the second value of the ATR is estimated to be 1.35, or (1.41 * (5 - 1) + (1.09)) / 5. The formula could then be repeated over the entire time period.

That's look like a TA-Lib's approach. Probably the article is misleading.

trufanov-nok avatar May 31 '22 19:05 trufanov-nok

OK I will change the ATR calculation but here the ADX function doesn't depend on ATR function. the ATR used in ADX is calculated separately with modified MA.

Or forget my library and just force on the test case I provided above. The worksheet shows my calculation with MMA.

paris0120 avatar May 31 '22 21:05 paris0120

You will change the ATR calculation, and it will not match the TA-Lib's resultrs anyway, bcs your MMA might be wrong. That's what I would expect. Let's fix ATR, and will see if ADX still incorrect. Just change ATR and test it across TA-Lib

trufanov-nok avatar May 31 '22 21:05 trufanov-nok

It's changed but this will not affect adx calculation. As I said, ADX is calculated seperately.

paris0120 avatar May 31 '22 22:05 paris0120

does atr results match ta-lib's atr now?

trufanov-nok avatar May 31 '22 22:05 trufanov-nok

I currently don't have the python lib now. I guess the results should match now for ATR. However, this won't change the results for ADX. As I showed you above, I verified the results manually. The difference is not caused by atr.

paris0120 avatar Jun 02 '22 16:06 paris0120

I currently don't have the python lib now. I guess the results should match now for ATR.

No, they are still wrong:

import {TALib} from "../index";

describe('testing index file', () => {
    let open = [146.28,145.7,145.47,145.47,145.12,145.02,145.25,145.19,144.97,144.95];
    let high = [146.59,145.74,145.7,145.47,145.12,145.26,145.27,145.25,145.01,145.13];
    let low = [145.85,145.53,145.4,145.0,144.92,145.0,145.12,144.91,144.92,144.93];
    let close = [146.2,145.58,145.47,145.12,145.03,145.11,145.25,144.98,144.98,145.1];
    let volume = [9294955,1013555,1010936,1036917,841699,947339,771789,1480890,1308324,967320];
    test('+ - * / % ^', () => {
        expect(TALib.atr(high, low, close, 4).atr.getValue()).toEqual([       null,        null,        null,        null, 0.41      ,       0.3725    , 0.319375  , 0.32453125, 0.26589844, 0.24942383]);
    });

});
 ● testing index file › + - * / % ^

    expect(received).toEqual(expected) // deep equality

    - Expected  - 6
    + Received  + 6

      Array [
        null,
        null,
        null,
        null,
    -   0.41,
    -   0.3725,
    -   0.319375,
    -   0.32453125,
    -   0.26589844,
    -   0.24942383,
    +   0.4099999999999966,
    +   0.30749999999999744,
    +   0.27250000000000085,
    +   0.240000000000002,
    +   0.21249999999999858,
    +   0.197499999999998,
      ]

In python:

import talib
import numpy as np

h = np.array([146.59,145.74,145.7,145.47,145.12,145.26,145.27,145.25,145.01,145.13]);
l = np.array([145.85,145.53,145.4,145.0,144.92,145.0,145.12,144.91,144.92,144.93]);
c = np.array([146.2,145.58,145.47,145.12,145.03,145.11,145.25,144.98,144.98,145.1]);
talib.ATR(h, l, c, timeperiod=4)

array([       nan,        nan,        nan,        nan, 0.41      ,
       0.3725    , 0.319375  , 0.32453125, 0.26589844, 0.24942383])

>>>

trufanov-nok avatar Jun 02 '22 17:06 trufanov-nok

Sorry I forgot to compile the package. It's now working.

    expect(TALib.atr(high, low, close, 4).atr.toFixed(5).getValue()).toEqual([null, null, null, null, 0.41,  0.3725, 0.31937, 0.32453, 0.2659, 0.24942]);

paris0120 avatar Jun 02 '22 17:06 paris0120

Ok, I can confirm that ATR is fixed now. Well, I need to check adx...

trufanov-nok avatar Jun 02 '22 19:06 trufanov-nok

I'm looking at DM calculation here: https://github.com/paris0120/talib.ts/blob/dev/src/index.ts#L396

it seems it conditionally multiplies pdm and ndm. But I believe it should conditionally sum them instead. Could you doeublecheck?

trufanov-nok avatar Jun 02 '22 20:06 trufanov-nok

Up and down are calculated first. Then if they meet the conditions they are the pdm or ndm otherwise 0.

It's equivalent to https://github.com/TA-Lib/ta-lib/blob/master/src/ta_func/ta_ADX.c#L465 . In your case, you don't add the value and I add the value as 0.

paris0120 avatar Jun 02 '22 20:06 paris0120

I'm not getting the typescript code then:

        let up = h.subtract(h.lag(1));
        let down = l.lag(1).subtract(l);

This seems to be up[i] = h[i] - h[i-1] and down[i] = l[i-1] - l[i]. OK. Then we have:

 pdm: up.greaterThan(down).and(up.greaterThan(0)).multiply(up),
 ndm: down.greaterThan(up).and(down.greaterThan(0)).multiply(down)

which looks for me like

if (up[i] > down[i]) and (up[i] > 0) then
pdm[i] = ???

if up.greaterThan(down).and(up.greaterThan(0)) is 0 or 1 then multiply have sense. In this case

pdm[i] = up[i] or 0

which is wrong. As pdm should be a commulative sum, like in TA-Lib's: https://github.com/TA-Lib/ta-lib/blob/master/src/ta_func/ta_ADX.c#L473

pdim[i] = pdm[i-1] + (up[i] or 0)

trufanov-nok avatar Jun 02 '22 20:06 trufanov-nok

I don't mind at all using this issue for this kind of debugging, but are we wondering if TA-Lib has a bug, or are we trying to figure out why this typescript implementation is buggy?

mrjbq7 avatar Jun 02 '22 20:06 mrjbq7

I cumulate DM in the DI calculation (https://github.com/paris0120/talib.ts/blob/dev/src/index.ts#L416) as the Smoothed DM as defined here https://www.investopedia.com/terms/a/adx.asp#:~:text=To%20get%20the%20ADX%2C%20continue,%2B%20current%20DX)%20%2F%2014.

paris0120 avatar Jun 02 '22 20:06 paris0120

I don't mind at all using this issue for this kind of debugging, but are we wondering if TA-Lib has a bug, or are we trying to figure out why this typescript implementation is buggy?

I currently believe that TA-Lib has a bug. Both the results of the worksheet and from my library don't match the results from the TA-Lib.

paris0120 avatar Jun 02 '22 20:06 paris0120

@mrjbq7

are we wondering if TA-Lib has a bug, or are we trying to figure out why this typescript implementation is buggy?

We don't know yet.

As pdm should be a commulative sum, like in TA-Lib's:

Ok, I was wrong here as it's hard to read the old C code - it's optimized for speed and do all calcs in a few loops. Looks like this sum is a part of further smoothing.

I've debugged C code a bit and found out at least one discrepancy. The TR is same in C and typescript but when C uses its smoothed value - it's different. For ex: console.log(TALib.tRange(high, low, close).tRange.modifiedMovingAverage(4).getValue());
is

    [
      null,
      null,
      null,
      null,
      0.4099999999999966,
      0.37249999999999517,
      0.3193749999999955,
      0.3245312499999975,
      0.265898437499999,
      0.2494238281249964
    ]

While TA-Libs results will be: null, null, null, 1.280000, 1.220000, 1.075000, 1.146250, 0.949687, 0.912266.
They differ from very first non null value.
Non smoothed TR values are:

    [
      null,
      0.6699999999999875,
      0.29999999999998295,
      0.46999999999999886,
      0.20000000000001705,
      0.2599999999999909,
      0.1599999999999966,
      0.3400000000000034,
      0.09000000000000341,
      0.19999999999998863
    ]

The typescript calculates very first value as:

(0.6699999999999875 + 0.29999999999998295 + 0.46999999999999886 + 0.20000000000001705) / 4 = 0.41

which is just an SMA.

TA-Libs first value calculated as

 sum = (0.6699999999999875 +  0.29999999999998295 + 0.46999999999999886); // 1.44
  val = sum - sum/4 + 0.20000000000001705 = 1.28

So unlike ATR in ADX TA-Lib smoothes the TR values differently. First smoothed value isn't SMA, it callculates all values with the Wilder's smoothing approach from very beginning. Let's check the investopedia description:

  1. First 14TR = sum of first 14 TR readings.
  2. Next 14TR value = first 14TR - (prior 14TR/14) + current TR.

Not clear enouth but nothing about SMA or averaging the first value.

So it seems you can't use modifiedMovingAverage from ATR in ADX at least for TR, but I would check other smoothed vals too.

trufanov-nok avatar Jun 02 '22 22:06 trufanov-nok

TA-Lib is older than Investopedia. It's better to refer to the Wilder's book as a source: https://media.indianpdf.com/visitors-uploaded/New-Concepts-In-Technical-Trading-Systems-J.-Welles-Wilfer-Jr-Read-Book-www.indianpdf.com_-Download-Online-Free.pdf The page 37 describes TR smoothing in ADX.

trufanov-nok avatar Jun 02 '22 23:06 trufanov-nok

TA-Lib is older than Investopedia. It's better to refer to the Wilder's book as a source: https://media.indianpdf.com/visitors-uploaded/New-Concepts-In-Technical-Trading-Systems-J.-Welles-Wilfer-Jr-Read-Book-www.indianpdf.com_-Download-Online-Free.pdf The page 37 describes TR smoothing in ADX.

Yes I did in DI https://github.com/paris0120/talib.ts/blob/dev/src/index.ts#L416

paris0120 avatar Jun 03 '22 02:06 paris0120

TA-Lib is older than Investopedia. It's better to refer to the Wilder's book as a source: https://media.indianpdf.com/visitors-uploaded/New-Concepts-In-Technical-Trading-Systems-J.-Welles-Wilfer-Jr-Read-Book-www.indianpdf.com_-Download-Online-Free.pdf The page 37 describes TR smoothing in ADX.

Let's focus on TA-Lib instead of my lib. Calculate ADX manually and verify the results.

paris0120 avatar Jun 03 '22 14:06 paris0120

ADX in TA-Lib and in your lib are calculated differently. I explained you this difference. The question is: which of them calculate ADX correctly? It seems for me that TA-Lib's approach is the correct one as your approach doesn't mach neither Investopedia nor the book.

trufanov-nok avatar Jun 03 '22 14:06 trufanov-nok

I have the smooth in the DI function. It matches the definition.

paris0120 avatar Jun 03 '22 15:06 paris0120

It doesn't match definition. You smoothment is: https://github.com/paris0120/numbers.ts/blob/0efc01709046a74c29391c86944f32d9918ac83c/src/index.ts#L612

sum += this.value[i];
                if (c >= period) {
                    output.push(sum/period);
                    sum -= sum / period;
                }

Which means when c == period the output is averaged sum. That's correct for ATR: https://en.wikipedia.org/wiki/Average_true_range

The first ATR value is calculated using the arithmetic mean formula:

And this matches ATR implementation in TA-Lib.

But nothing like that is described for TR in ADX. The investopedia and the book says nothing about averaging first smoothed value. At least I don't see it. May you find something? And TA-Lib's implementation doesn't average the first value. I've explained how it calculates the first value. That means TA-Lib uses different smoothing in ATR and for TR used in ADX. And it looks like this is aligned with the docs.

trufanov-nok avatar Jun 03 '22 15:06 trufanov-nok

It doesn't match definition. You smoothment is: https://github.com/paris0120/numbers.ts/blob/0efc01709046a74c29391c86944f32d9918ac83c/src/index.ts#L612

sum += this.value[i];
                if (c >= period) {
                    output.push(sum/period);
                    sum -= sum / period;
                }

Which means when c == period the output is averaged sum. That's correct for ATR: https://en.wikipedia.org/wiki/Average_true_range

The first ATR value is calculated using the arithmetic mean formula:

And this matches ATR implementation in TA-Lib.

But nothing like that is described for TR in ADX. The investopedia and the book says nothing about averaging first smoothed value. At least I don't see it. May you find something? And TA-Lib's implementation doesn't average the first value. I've explained how it calculates the first value. That means TA-Lib uses different smoothing in ATR and for TR used in ADX. And it looks like this is aligned with the docs.

TA-Lib does the same https://github.com/TA-Lib/ta-lib/blob/master/src/ta_func/ta_ADX.c#L386

paris0120 avatar Jun 03 '22 16:06 paris0120

Not the same. TA-Lib's first prevTR at https://github.com/TA-Lib/ta-lib/blob/master/src/ta_func/ta_ADX.c#L484 is (0.6699999999999875 + 0.29999999999998295 + 0.46999999999999886) - (0.6699999999999875 + 0.29999999999998295 + 0.46999999999999886)/4 + 0.20000000000001705 = 1.28 and yours (0.6699999999999875 + 0.29999999999998295 + 0.46999999999999886 + 0.20000000000001705) / 4 = 0.41

trufanov-nok avatar Jun 03 '22 16:06 trufanov-nok

Not the same. TA-Lib's first prevTR at https://github.com/TA-Lib/ta-lib/blob/master/src/ta_func/ta_ADX.c#L484 is (0.6699999999999875 + 0.29999999999998295 + 0.46999999999999886) - (0.6699999999999875 + 0.29999999999998295 + 0.46999999999999886)/4 + 0.20000000000001705 = 1.28 and yours (0.6699999999999875 + 0.29999999999998295 + 0.46999999999999886 + 0.20000000000001705) / 4 = 0.41

I guess that's the difference. I can't see the meaning of dividing the sum of 3 numbers by 4. You can call it a feature but personally I feel that it's a bug.

paris0120 avatar Jun 03 '22 16:06 paris0120

Does TA-Lib match other libraries, besides yours?

mrjbq7 avatar Jun 03 '22 16:06 mrjbq7

Does TA-Lib match other libraries, besides yours?

Sadly, all the libraries I found are based on TA-Lib. That's why I'm rewriting one.

paris0120 avatar Jun 03 '22 16:06 paris0120

There is an example table of ADX calculation step by step in WIlder's book at page 42.
https://media.indianpdf.com/visitors-uploaded/New-Concepts-In-Technical-Trading-Systems-J.-Welles-Wilfer-Jr-Read-Book-www.indianpdf.com_-Download-Online-Free.pdf

The column 6 is current TR, Column 9 is smoothed TR(14 period). First TR14 value is at day 15 and it's: 43.32. And it looks like it's

sum = 3 + 2.25 + 2.75 + 1 + 2.50 + 3.50 + 3.50 + 4.25 + 3.50 + 6.50 +2.25 + 2 + 4 = 41
tr14 = 41 - 41/14 + 5.25 = 43.32

Note that there are 13 values in sum, bcs TR1 cant be calculated at day 1.
I guess TA-Lib authors copied this approach from his book and Wilder is inventor of ADX if I recall right.

P.S. There is a "Totals" row before day 15 which seems to be just for the info and it contains sums of previous raws for some columns. Due to a bad authors calligraphy I read 44 instead of 41 for column 6. But it's 41 - I even recalculated the column to ensure.

trufanov-nok avatar Jun 03 '22 17:06 trufanov-nok

1 + 2.50 + 3.50

Really appreciate the effort. I really don't see how this works. The mean is first underestimated and then takes a long period to regress to an unbiased mean. I guess Wilder didn't know much about math.

paris0120 avatar Jun 03 '22 17:06 paris0120