Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to modify this project, if i have add a new indicator in ta-lib project and get ta-lib.lib #703

Open
cloudslee opened this issue Feb 2, 2025 · 21 comments

Comments

@cloudslee
Copy link

i have add a new indicator in ta-lib and get ta-lib.lib.
what shoud i do about this python wrapper?
ta-lib-python\talib.c seems generated code, how to modify it?

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 2, 2025 via email

@cloudslee
Copy link
Author

i get this error when run generate_func.py, how to fix it?
Traceback (most recent call last):
File "F:\ta-lib-python\tools\generate_func.py", line 216, in
func_info = abstract.Function(shortname).info
File "C:\Python39\lib\site-packages\talib\abstract.py", line 16, in Function
raise Exception('%s not supported by TA-LIB.' % func_name)
Exception: ACCBANDS not supported by TA-LIB.

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025

I assume it's using the current ta-lib installation to inspect that function using the abstract interface.

Is the current ta-lib not built against the new ta-lib with the new indicator?

@cloudslee
Copy link
Author

so i shoud uninstall the old ta-lib?

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025

Well, you can build it against your new ta-lib with the new indictor in C library, but without the new indicator in Python.

And then add it using the generate script.

Alternatively, add the function manually to talib/_ta_lib.pxd and copy-and-paste a definition for ACCBANDS in talib/_func.pxiand talib/_stream.pxi, which is what the generate script does anyway.

And since someone contributed talib/_ta_lib.pyi we need to add the typed declaration there too.

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025

Alternatively, you can modify the generate_func.py script to provide "defaults and docs" which is what the abstract interface is used for... something like:

diff --git a/tools/generate_func.py b/tools/generate_func.py
index 5a625ef0..5c00d400 100644
--- a/tools/generate_func.py
+++ b/tools/generate_func.py
@@ -213,8 +213,11 @@ for f in functions:

     shortname = name[3:]
     names.append(shortname)
-    func_info = abstract.Function(shortname).info
-    defaults, documentation = abstract._get_defaults_and_docs(func_info)
+    try:
+        func_info = abstract.Function(shortname).info
+        defaults, documentation = abstract._get_defaults_and_docs(func_info)
+    except:
+        defaults, documentation = {}, ""

     print('@wraparound(False)  # turn off relative indexing from end of lists')
     print('@boundscheck(False) # turn off bounds-checking for entire function')

@cloudslee
Copy link
Author

i uninstall old ta-lib, and get this error, should i install old ta-lib again?
F:\ta-lib-python\tools>generate_func.py
Traceback (most recent call last):
File "F:\ta-lib-python\tools\generate_func.py", line 7, in
from talib import abstract
ModuleNotFoundError: No module named 'talib'

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025

Okay, I pushed a change to make it fine without abstract info.

I mean the way I develop it, I use a a ta-lib-python checkout, and I build it locally and run it from the same build directory, so not installed in site-packages.

make build will build it

make generate will make new cython generated C files

if you're on windows, i made an extra change to the generate scripts to support their new install locations.

Running it, I notice this output

cannot find defaults and docs for ACCBANDS
cannot find defaults and docs for AVGDEV
cannot find defaults and docs for IMI

Are these new indicators in 0.6.x that I should support?

Is that what you're trying to add?

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025

I added those 3 indicators, look at the last few patches, and try the latest commit?

@cloudslee
Copy link
Author

the indicator what i want to add is TD Sequential Indicator, i'm not familiar with the whole process of add a new indicator,
so i copy and paste other's volume price trend (VPT) indicator, and got stucked

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025

This is basically all you need to add a new indicator:

  • Add new functions to talib/_ta_lib.pxd
  • Run tools/generate_func.py > talib/_func.pxi
  • Run tools/generate_stream.py > talib/_stream.pxi
  • Regenerate the cached talib/_ta_lib.c file using cython

Usually, you need a "second pass" that runs generate again but now that the abstract docs are available for them.

You can see that in

  1. Add the new indicators: a9652eb
  2. Update the C file: 65dc03d
  3. Update the docs: ccf7fb1

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025

Sorry, it's not so easy, but I just ran through the steps for those 3 indicators and it works okay.

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025

The "Update the C file" step is only because I like this to be installable without cython available, it's not strictly needed for local development and testing.

@cloudslee
Copy link
Author

i have add new VPT indicator in talib/_ta_lib.pxd, and run generate_func.py, generate_stream.py,
the next step, how to Regenerate the cached talib/_ta_lib.c file using cython?

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025 via email

@cloudslee
Copy link
Author

ta-lib-python>cython --directive emit_code_comments=False talib/_ta_lib.pyx
run cython command, i got this error
warning: talib_abstract.pxi:36:4: Global name __PANDAS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:55:4: Global name __POLARS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:21:0: Global name __INPUT_PRICE_SERIES_DEFAULTS matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:27:0: Global name __INPUT_ARRAYS_TYPES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:36:4: Global name __PANDAS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:55:4: Global name __POLARS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:27:0: Global name __INPUT_ARRAYS_TYPES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:28:0: Global name __ARRAY_TYPES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:27:0: Global name __INPUT_ARRAYS_TYPES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:36:4: Global name __PANDAS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:36:4: Global name __PANDAS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:55:4: Global name __POLARS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:55:4: Global name __POLARS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.

Error compiling Cython file:

...
low = check_array(low)
close = check_array(close)
length = check_length3(high, low, close)
begidx = check_begidx3(length, <double*>(high.data), <double*>(low.data), <double*>(close.data))
endidx = length - begidx - 1
lookback = begidx + lib.TA_ACCBANDS_Lookback( timeperiod )
^

talib_func.pxi:161:27: cimported module has no attribute 'TA_ACCBANDS_Lookback'

Error compiling Cython file:

...
endidx = length - begidx - 1
lookback = begidx + lib.TA_ACCBANDS_Lookback( timeperiod )
outrealupperband = make_double_array(length, lookback)
outrealmiddleband = make_double_array(length, lookback)
outreallowerband = make_double_array(length, lookback)
retCode = lib.TA_ACCBANDS( 0 , endidx , <double *>(high.data)+begidx , <double *>(low.data)+begidx , <double *>(close.data)+begidx , timeperiod , &outbegidx , &outnbelement , <double *>(outrealupperband.data)+lookback , <double *>(outrealmiddleband.data)+lookback , <double *>(outreallowerband.data)+lookback )
^

talib_func.pxi:165:17: cimported module has no attribute 'TA_ACCBANDS'

Error compiling Cython file:

...
np.ndarray outreal
real = check_array(real)
length = real.shape[0]
begidx = check_begidx1(length, <double*>(real.data))
endidx = length - begidx - 1
lookback = begidx + lib.TA_AVGDEV_Lookback( timeperiod )
^

talib_func.pxi:600:27: cimported module has no attribute 'TA_AVGDEV_Lookback'

Error compiling Cython file:

...
length = real.shape[0]
begidx = check_begidx1(length, <double*>(real.data))
endidx = length - begidx - 1
lookback = begidx + lib.TA_AVGDEV_Lookback( timeperiod )
outreal = make_double_array(length, lookback)
retCode = lib.TA_AVGDEV( 0 , endidx , <double *>(real.data)+begidx , timeperiod , &outbegidx , &outnbelement , <double *>(outreal.data)+lookback )
^

talib_func.pxi:602:17: cimported module has no attribute 'TA_AVGDEV'

Error compiling Cython file:

...
open = check_array(open)
close = check_array(close)
length = check_length2(open, close)
begidx = check_begidx2(length, <double*>(open.data), <double*>(close.data))
endidx = length - begidx - 1
lookback = begidx + lib.TA_IMI_Lookback( timeperiod )
^

talib_func.pxi:3241:27: cimported module has no attribute 'TA_IMI_Lookback'

Error compiling Cython file:

...
length = check_length2(open, close)
begidx = check_begidx2(length, <double*>(open.data), <double*>(close.data))
endidx = length - begidx - 1
lookback = begidx + lib.TA_IMI_Lookback( timeperiod )
outreal = make_double_array(length, lookback)
retCode = lib.TA_IMI( 0 , endidx , <double *>(open.data)+begidx , <double *>(close.data)+begidx , timeperiod , &outbegidx , &outnbelement , <double *>(outreal.data)+lookback )
^

talib_func.pxi:3243:17: cimported module has no attribute 'TA_IMI'
warning: talib_abstract.pxi:21:0: Global name __INPUT_PRICE_SERIES_DEFAULTS matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:27:0: Global name __INPUT_ARRAYS_TYPES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:36:4: Global name __PANDAS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:36:4: Global name __PANDAS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:55:4: Global name __POLARS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:55:4: Global name __POLARS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:27:0: Global name __INPUT_ARRAYS_TYPES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:28:0: Global name __ARRAY_TYPES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:35:4: Global name __PANDAS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:54:4: Global name __POLARS_DATAFRAME matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:27:0: Global name __INPUT_ARRAYS_TYPES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:36:4: Global name __PANDAS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:36:4: Global name __PANDAS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:55:4: Global name __POLARS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.
warning: talib_abstract.pxi:55:4: Global name __POLARS_SERIES matched from within class scope in contradiction to to Python 'class private name' rules. This may change in a future release.

Error compiling Cython file:

...
close_data = <double*>close.data
length = check_length3(high, low, close)
outrealupperband = NaN
outrealmiddleband = NaN
outreallowerband = NaN
retCode = lib.TA_ACCBANDS( (length) - 1 , (length) - 1 , high_data , low_data , close_data , timeperiod , &outbegidx , &outnbelement , &outrealupperband , &outrealmiddleband , &outreallowerband )
^

talib_stream.pxi:34:17: cimported module has no attribute 'TA_ACCBANDS'

Error compiling Cython file:

...
double outreal
real = check_array(real)
real_data = <double*>real.data
length = real.shape[0]
outreal = NaN
retCode = lib.TA_AVGDEV( (length) - 1 , (length) - 1 , real_data , timeperiod , &outbegidx , &outnbelement , &outreal )
^

talib_stream.pxi:479:17: cimported module has no attribute 'TA_AVGDEV'

Error compiling Cython file:

...
open_data = <double*>open.data
close = check_array(close)
close_data = <double*>close.data
length = check_length2(open, close)
outreal = NaN
retCode = lib.TA_IMI( (length) - 1 , (length) - 1 , open_data , close_data , timeperiod , &outbegidx , &outnbelement , &outreal )
^

talib_stream.pxi:3342:17: cimported module has no attribute 'TA_IMI'

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025 via email

@cloudslee
Copy link
Author

F:\ta-lib-python>tools\generate_func.py > talib/_func.pxi
cannot find defaults and docs for ACCBANDS
cannot find defaults and docs for AVGDEV
cannot find defaults and docs for IMI
cannot find defaults and docs for VPT

F:\ta-lib-python>tools\generate_stream.py > talib/_stream.pxi
cannot find defaults and docs for ACCBANDS
cannot find defaults and docs for AVGDEV
cannot find defaults and docs for IMI
cannot find defaults and docs for VPT

F:\ta-lib-python>cython --directive emit_code_comments=False talib/_ta_lib.pyx
the indicator that i add was VPT, not IMI

@cloudslee
Copy link
Author

yeah, it seems that my code was outdate, when i pull remote code from latest git master, it conflict with my local file

@cloudslee
Copy link
Author

it's ok, thanks

if i want to push my new indicator to ta-lib and ta-lib-python, what shoud i do?

@mrjbq7
Copy link
Member

mrjbq7 commented Feb 4, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants