Skip to content

feat: support TA-Lib C 0.8.1 (proposal, for after the 0.8.1 release) - #754

Open
mario4tier wants to merge 1 commit into
fix/752-unstable-period-idsfrom
feat/talib-c-0.8.1-support
Open

feat: support TA-Lib C 0.8.1 (proposal, for after the 0.8.1 release)#754
mario4tier wants to merge 1 commit into
fix/752-unstable-period-idsfrom
feat/talib-c-0.8.1-support

Conversation

@mario4tier

@mario4tier mario4tier commented Jul 29, 2026

Copy link
Copy Markdown
Member

Please treat this as a proposal, not a request.

These are the changes ta-lib-python needs for TA-Lib C 0.8.1, which is
not released yet — so this should land after the C release is tagged,
not before. It also depends on #753 (the unstable-period id fix for #752)

@mrjbq7 — please don't feel obligated to use this PR. I think it is a good start and at a minimum it should at least show you the scope of the differences that need addressing for 0.8.1.


What breaks against 0.8.1 today

Two of them are hard failures, not just stale expectations:

  1. abstract is unusable. _abstract.pxi's __get_flags() does
    flags_lookup_dict[2**i] for every set bit and raises KeyError: 33554432
    on TA_FUNC_FLG_STREAM, a flag added in 0.8.1. This takes out
    abstract.Function() entirely, so tests/test_abstract.py and
    tests/test_polars.py cannot even be collected. TA_FUNC_FLG_PATH_DEP and
    TA_OUT_NULLABLE are also new. Fixed by ignoring unknown bits and naming
    the new ones.
  2. The code generators crash. 0.8.1's ta_func.h declares TA-Lib C's own
    streaming API (TA_<FUNC>_Open/_OpenAndFill/_Update/_Peek/_Close), and the
    header parser in tools/generate_func.py asserts on
    TA_ACCBANDS_Stream **stream. Both generators now skip those declarations.
    (talib's stream_* wrappers are unrelated — they are generated from the
    batch functions.)

What 0.8.1 adds

  • Seven functions: CMF, CMOU, HMA, NVI, PVI, PVO, VWMA — declarations in
    _ta_lib.pxd, regenerated _func.pxi/_stream.pxi, entries in
    __function_groups__, and both type stubs. Function count 161 → 168.
  • MA_Type.HMA (9) and MA_Type.DISABLED (10).
  • Behaviour changes that need no code, since defaults come from ta_abstract
    at runtime: APO/PPO default matype SMA → EMA, BBANDS default
    timeperiod 5 → 20. Only hardcoded test expectations and stubs moved.

Older ta-lib now fails at import, with an explanation

Binding the new functions makes 0.8.1 a hard minimum. The failure mode is
nasty by default: linking a shared object against an older ta-lib succeeds
— a .so may carry undefined symbols — so pip install looks fine and then
import talib dies with undefined symbol: TA_CMF_Lookback.

talib/__init__.py now catches that and chains a message onto it:

ImportError: .../_ta_lib...so: undefined symbol: TA_CMF_Lookback

talib could not load its extension module. This build requires the TA-Lib C
library 0.8.1 or later; an older one is missing functions this wrapper calls.
See https://ta-lib.org/install/

The original linker error is preserved via raise ... from error. This is
deliberately a runtime check rather than a setup.py probe: a build-time probe
would need a hardcoded symbol name that silently goes stale whenever the
minimum moves (the same failure mode as #752), and it could not catch a
prebuilt wheel meeting an older system library. setup.py is unchanged.

Verification

ta-lib C built fresh from source, ta-lib-python built in place
(setup.py build_ext --inplace, Cython 3.2.9, no wheels):

ta-lib C build import tests
0.8.1 78 passed, 0 failed
0.7.1 ✅ (links) ❌ message above
0.6.4 ✅ (links) ❌ message above

All five test files collect on 0.8.1: test_abstract.py 17, test_func.py 50,
test_pandas.py 2, test_polars.py 4, test_stream.py 5.

For contrast, unmodified master against the same 0.8.1: 24 passed, 1 failed,
2 collection errors.

Open items for you to decide

  • Version number. pyproject.toml is untouched and the CHANGELOG heading
    0.8.0 is a placeholder — release numbering is yours.
  • CI is blocked until the C tag exists. TALIB_C_VER is bumped to 0.8.1 in
    wheels.yml and the three build scripts, and those download
    refs/tags/v0.8.1.zip. Wheel jobs will 404 until TA-Lib C 0.8.1 is tagged.
  • docs/func_groups/*.md are hand-written and do not list the seven new
    functions. Nothing tests them; happy to add if you want it here.
  • talib/_ta_lib.c is left untouched, since it is only committed on Cython
    version bumps.

TA-Lib C 0.8.1 is now the minimum required version.

- Bind the seven new functions: CMF, CMOU, HMA, NVI, PVI, PVO, VWMA
  (declarations in _ta_lib.pxd, regenerated _func.pxi/_stream.pxi, added to
  __function_groups__ and to both type stubs).
- Add MA_Type.HMA and MA_Type.DISABLED.
- abstract: __get_flags() raised KeyError on flag bits added after this
  wrapper was written. 0.8.1 sets TA_FUNC_FLG_STREAM, which made
  abstract.Function() unusable and left tests/test_abstract.py and
  tests/test_polars.py uncollectable. Unknown bits are now ignored, and the
  known new bits (streaming API, path-dependent, nullable output) are named.
- tools/generate_func.py, tools/generate_stream.py: skip TA-Lib C's own
  streaming API (TA_<FUNC>_Open/_OpenAndFill/_Update/_Peek/_Close), which the
  header parser could not handle.
- Building against an older ta-lib still links: a shared object may keep
  undefined symbols, so the failure only appears when the extension is loaded,
  as "undefined symbol: TA_CMF_Lookback". Catch that at import and say what is
  actually wrong.
- Bump the pinned TALIB_C_VER in the wheel workflow and the three build
  scripts to 0.8.1.
- Tests: APO/PPO now default matype to EMA and BBANDS timeperiod to 20 per
  TA-Lib C 0.8.1; version is 0.8.1 and the function count is 168. Added a
  smoke test per new function and an MA(HMA) == HMA check.
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

Successfully merging this pull request may close these issues.

1 participant