TA-Lib
The C reference every other Python indicator library is measured against — and the reason two
libraries computing "the same" RSI hand you two different backtests.
|
|
| pip / import |
pip install TA-Lib · import talib (repo ta-lib-python, now the ta-lib org) |
| Version |
0.7.1 (2026-07-16) · C core 0.7.1 · requires_python >=3.9 |
| Licence |
BSD-ish |
| Status |
✅ 54 wheels incl. cp311-win_amd64, bundling the C library since 0.6.5 (2025-08-07) |
The trap that costs you money
🚨 Every pure-Python port emits values before TA-Lib does, computed on partial windows —
silently wrong, not NaN. TA-Lib's documented "unstable period" behaviour is exactly why its warm-up
start indices differ from every port. Swap libraries, or restart the calculation per symbol on a
short slice, and the same strategy becomes two different backtests.
Measured — TA-Lib python 0.7.1 / C core 0.7.1, pandas 3.0.5, numpy 2.4.6, 500-bar synthetic GBM,
seed 7; maxabs = max absolute difference over the overlapping non-NaN region:
| Library |
SMA/BBands/CCI/OBV |
RSI(14) |
EMA(20) |
ATR(14) |
ADX(14) |
MACD |
| talipp 2.7.0 |
exact |
1.4e-14, exact incl. warm-up start index |
2.8e-14 |
3.2e-02 warm-up only |
— |
0.155 warm-up only |
| pandas-ta-classic 0.6.52 |
≤3e-11 |
3.6e-14 |
2.8e-14 |
8.9e-16 |
🚨 4.25, emits from bar 13 vs TA-Lib's 27 |
0.155 early bars |
| ta 0.11.0 |
identical |
🚨 3.84 |
🚨 0.363 |
🚨 0.0477, emits from bar 0 |
🚨 0.642, emits from bar 0 |
🚨 0.378, 8 bars early |
How long ta's RSI(14) takes to converge on the same input: |diff| > 1.0 through bar 36 ·
> 0.1 through bar 67 · > 0.01 through bar 97 · > 1e-6 through bar 217.
🚨 Universal rule: discard the first ~10–15 × period bars of any recursive indicator (EMA, RSI,
ATR, ADX, MACD), whatever the library.
The install folklore is obsolete
"Needs the C library compiled by hand; no Windows wheels" was true and is not any more. ta-lib-python ships prebuilt wheels bundling the TA-Lib C library since v0.6.5. pip install TA-Lib just works on Windows. If you are still writing build instructions into a README, that guidance is stale.
Calling it correctly
It takes numpy float64 arrays, not Series. Pass .values and reattach the index yourself, or
use the abstract API, which accepts dict / pandas / polars inputs.
import talib
rsi = talib.RSI(close, timeperiod=14) # close must be float64 ndarray
from talib import abstract
out = abstract.MACD(df, fastperiod=12, slowperiod=26, signalperiod=9)
Which library for which job
| Package |
Version |
Licence |
Verdict |
| TA-Lib |
0.7.1 (2026-07-16) |
BSD-ish |
✅ the reference |
talipp |
2.7.0 (2025-09-09) |
MIT |
✅ incremental/streaming; closest match, only one that also matches TA-Lib's RSI warm-up start index |
pandas-ta-classic |
0.6.52 (2026-06-24) |
MIT |
✅ the maintained successor, 427★, py≥3.10; watch ADX warm-up |
ta (bukosabino) |
0.11.0 (2023-11-02) |
MIT |
⚠️ pure python, sdist only, ~3 yrs stale — usable with fillna=False |
🚨 pandas-ta |
0.4.71b0 (2025-09-14) |
🚨 NONE DECLARED |
🔴 do not install |
🔴 finta |
1.3 (2021) |
LGPL-3.0 |
repo ARCHIVED 2022-07-24 |
🔴 tulipy / bta-lib |
0.4.0 (2019) / — |
LGPL / — |
dead |
✅ talipp's incremental .add() produces bit-identical output to batch construction. That is the whole reason it exists, and it is the correct choice when a strategy runs streaming — it removes the backtest-vs-live warm-up divergence.
🚨 pandas-ta — supply-chain caution
github.com/twopirllc/pandas-ta → HTTP 404 (removed ~June 2025).
- PyPI now lists only two releases, 0.4.67b0 and 0.4.71b0. All prior history, including the
widely used 0.3.14b, was deleted.
- No
license field and no license classifier; requires_python >=3.12; the Repository URL
still points at the dead 404 repo.
pandas-ta.dev — DNS does not resolve, and archive.org has no snapshots.
A package with no licence, wiped release history, a dead upstream repo and a dead homepage is a
supply-chain risk regardless of intent. Pin to pandas-ta-classic, ta, or TA-Lib.
🚨 ta's verified bugs, if you must use it
Isolated by perturbing only future bars and checking whether early bars changed:
IchimokuIndicator(..., visual=True).ichimoku_a() — CONFIRMED LOOK-AHEAD, 26 early bars
changed, max |Δ| 35.34, even with fillna=False.
DPOIndicator(..., fillna=True).dpo() — CONFIRMED LOOK-AHEAD, 11 early bars, max |Δ| 34.43.
_check_fillna() does ffill().bfill() — the bfill() pulls future values backwards into
leading NaNs; PSAR up/down are genuinely affected.
ichimoku_b() hardcodes min_periods=0 — the first 51 Span B values are computed on partial
windows and are silently wrong.
ta.utils.dropna() silently deletes every row where any numeric column equals 0.0 — it will
destroy zero-volume and zero-return rows.
See also
../../../fin-core/skills/signal-construction/SKILL.md — leak-free signal construction, §2 measured agreement
../../../fin-core/skills/signal-construction/references/indicator-libraries.md — the source card
../../../fin-core/skills/signal-construction/references/_repainting.md — the full repainting detail
Where this sits
This file is the deep dive on one library and assumes the choice is already made.
For which library to pick, how it compares with the alternatives, and the traps that span
several of them, the entry point is the domain skill signal-construction (../../../fin-core/skills/signal-construction/SKILL.md).
1---2name: lib-talib3description: The C reference implementation of technical indicators, where every pure-Python port disagrees during warm-up and none of them say so. TRIGGER - import talib, pip install TA-Lib, ta-lib-python, talib.RSI, talib.MACD, talib.ATR, talib.ADX, talib.BBANDS, talib.OBV, from talib import abstract, talib.get_functions, unstable period, indicator warm-up, an indicator differing between two libraries or between backtest and live; "Exception: input array type is not double", a failed ta-lib C build or missing ta_libc.h. Memory is stale here: the install pain is solved - 0.7.1 (2026-07-16) ships 54 prebuilt wheels bundling the C library, including cp311-win_amd64 - while pandas-ta's repo, homepage and release history are all gone. SKIP for whether a signal actually predicts returns (factor-and-timeseries-research) and for leak-free signal construction generally (signal-construction). SKIP for choosing between libraries, or when no library is named - the domain skill's job.4license: MIT5---67# TA-Lib89The C reference every other Python indicator library is measured against — and the reason two10libraries computing "the same" RSI hand you two different backtests.1112| | |13|---|---|14| pip / import | `pip install TA-Lib` · `import talib` (repo `ta-lib-python`, now the `ta-lib` org) |15| Version | **0.7.1 (2026-07-16)** · C core 0.7.1 · `requires_python >=3.9` |16| Licence | BSD-ish |17| Status | ✅ **54 wheels incl. `cp311-win_amd64`**, bundling the C library since **0.6.5 (2025-08-07)** |1819## The trap that costs you money2021🚨 **Every pure-Python port emits values *before* TA-Lib does, computed on partial windows —22silently wrong, not NaN.** TA-Lib's documented "unstable period" behaviour is exactly why its warm-up23start indices differ from every port. Swap libraries, or restart the calculation per symbol on a24short slice, and **the same strategy becomes two different backtests**.2526Measured — TA-Lib python 0.7.1 / C core 0.7.1, pandas 3.0.5, numpy 2.4.6, 500-bar synthetic GBM,27seed 7; `maxabs` = max absolute difference over the overlapping non-NaN region:2829| Library | SMA/BBands/CCI/OBV | RSI(14) | EMA(20) | ATR(14) | ADX(14) | MACD |30|---|---|---|---|---|---|---|31| **talipp 2.7.0** | exact | **1.4e-14, exact incl. warm-up start index** | 2.8e-14 | 3.2e-02 warm-up only | — | 0.155 warm-up only |32| **pandas-ta-classic 0.6.52** | ≤3e-11 | **3.6e-14** | 2.8e-14 | 8.9e-16 | 🚨 **4.25**, emits from bar 13 vs TA-Lib's 27 | 0.155 early bars |33| **ta 0.11.0** | identical | 🚨 **3.84** | 🚨 0.363 | 🚨 0.0477, emits **from bar 0** | 🚨 **0.642**, emits **from bar 0** | 🚨 0.378, 8 bars early |3435**How long `ta`'s RSI(14) takes to converge on the same input:** `|diff| > 1.0` through **bar 36** ·36`> 0.1` through **bar 67** · `> 0.01` through **bar 97** · `> 1e-6` through **bar 217**.3738> 🚨 **Universal rule: discard the first ~10–15 × period bars of any recursive indicator (EMA, RSI,39> ATR, ADX, MACD), whatever the library.**4041## The install folklore is obsolete4243"Needs the C library compiled by hand; no Windows wheels" was true and **is not any more**. `ta-lib-python` ships prebuilt wheels **bundling the TA-Lib C library** since v0.6.5. `pip install TA-Lib` just works on Windows. If you are still writing build instructions into a README, that guidance is stale.4445## Calling it correctly4647**It takes numpy float64 arrays, not Series.** Pass `.values` and reattach the index yourself, or48use the abstract API, which accepts dict / pandas / polars inputs.4950```python51import talib52rsi = talib.RSI(close, timeperiod=14) # close must be float64 ndarray5354from talib import abstract55out = abstract.MACD(df, fastperiod=12, slowperiod=26, signalperiod=9)56```5758## Which library for which job5960| Package | Version | Licence | Verdict |61|---|---|---|---|62| **TA-Lib** | 0.7.1 (2026-07-16) | BSD-ish | ✅ the reference |63| **`talipp`** | 2.7.0 (2025-09-09) | MIT | ✅ incremental/streaming; closest match, **only one that also matches TA-Lib's RSI warm-up start index** |64| **`pandas-ta-classic`** | 0.6.52 (2026-06-24) | **MIT** | ✅ the maintained successor, 427★, py≥3.10; watch ADX warm-up |65| `ta` (bukosabino) | 0.11.0 (2023-11-02) | MIT | ⚠️ pure python, **sdist only**, ~3 yrs stale — usable with `fillna=False` |66| 🚨 `pandas-ta` | 0.4.71b0 (2025-09-14) | 🚨 **NONE DECLARED** | 🔴 **do not install** |67| 🔴 `finta` | 1.3 (2021) | LGPL-3.0 | repo **ARCHIVED** 2022-07-24 |68| 🔴 `tulipy` / `bta-lib` | 0.4.0 (2019) / — | LGPL / — | dead |6970✅ **`talipp`'s incremental `.add()` produces bit-identical output to batch construction.** That is the whole reason it exists, and it is the correct choice when a strategy runs streaming — it removes the backtest-vs-live warm-up divergence.7172## 🚨 `pandas-ta` — supply-chain caution7374- `github.com/twopirllc/pandas-ta` → **HTTP 404** (removed ~June 2025).75- PyPI now lists **only two releases**, 0.4.67b0 and 0.4.71b0. **All prior history, including the76 widely used 0.3.14b, was deleted.**77- **No `license` field and no license classifier**; `requires_python >=3.12`; the `Repository` URL78 still points at the dead 404 repo.79- `pandas-ta.dev` — **DNS does not resolve**, and archive.org has **no snapshots**.8081**A package with no licence, wiped release history, a dead upstream repo and a dead homepage is a82supply-chain risk regardless of intent.** Pin to `pandas-ta-classic`, `ta`, or TA-Lib.8384## 🚨 `ta`'s verified bugs, if you must use it8586Isolated by perturbing only future bars and checking whether early bars changed:87881. `IchimokuIndicator(..., visual=True).ichimoku_a()` — **CONFIRMED LOOK-AHEAD**, 26 early bars89 changed, max |Δ| 35.34, **even with `fillna=False`**.902. `DPOIndicator(..., fillna=True).dpo()` — **CONFIRMED LOOK-AHEAD**, 11 early bars, max |Δ| 34.43.913. `_check_fillna()` does `ffill().bfill()` — the **`bfill()` pulls future values backwards** into92 leading NaNs; **PSAR up/down are genuinely affected**.934. `ichimoku_b()` hardcodes `min_periods=0` — the first 51 Span B values are computed on partial94 windows and are **silently wrong**.955. `ta.utils.dropna()` **silently deletes every row where any numeric column equals `0.0`** — it will96 destroy zero-volume and zero-return rows.9798## See also99100- `../../../fin-core/skills/signal-construction/SKILL.md` — leak-free signal construction, §2 measured agreement101- `../../../fin-core/skills/signal-construction/references/indicator-libraries.md` — the source card102- `../../../fin-core/skills/signal-construction/references/_repainting.md` — the full repainting detail103104## Where this sits105106This file is the deep dive on **one** library and assumes the choice is already made.107For which library to pick, how it compares with the alternatives, and the traps that span108several of them, the entry point is the domain skill **`signal-construction`** (`../../../fin-core/skills/signal-construction/SKILL.md`).109