![[RELEASE] pandas-ta-classic v0.6.20 - Code Modernization, Fluent Chaining, Property-Based Testing, and 89% Test Coverage etc.](https://external-preview.redd.it/5tVyXgbnPcnxT6pbLqDyErwMpK_kk4huugdIFi2HmqU.png?width=1080&crop=smart&auto=webp&s=c29aea4d5020cfebe8b95d59ac165d7daa77d8e7)
[RELEASE] pandas-ta-classic v0.6.20 - Code Modernization, Fluent Chaining, Property-Based Testing, and 89% Test Coverage etc.
Hey r/algotrading,
pandas-ta-classic is the community-maintained fork of pandas-ta — a comprehensive technical analysis library for pandas DataFrames. This release is the largest update since the fork, spanning 66 commits and 338 changed files.
GitHub: github.com/xgboosted/pandas-ta-classic
PyPI: pip install pandas-ta-classic
🎯 TL;DR
- TA-Lib exact parity — Wilder smoothing, chained EMA lookbacks, and PSAR reversal checks now match the C library within
float64precision. All 60 oracle tests pass attol=1e-7. - Fluent API chaining —
df.ta.chain().sma(50).rsi().macd(). Chain indicators in one expression, calldf.ta.unchain()to go back to normal mode. - Property-based testing — 55 Hypothesis tests verify mathematical invariants (
SMA(constant) == constant, RSI ∈ [0,100]) across random inputs. - Test coverage 78% → 89% — 1427 tests, zero failures. Every indicator has offset, fill, and None-guard coverage.
- Code modernized — Python 3.9–3.14, 370 dead-code instances removed,
talalias replaced withtalibeverywhere.
⚡ Fluent API Chaining (PR #113)
import pandas_ta_classic as ta
df = df.ta.chain().sma(50).rsi().macd().bbands(20)
# df now has SMA_50, RSI_14, MACD_12_26_9, MACDh_12_26_9, MACDs_12_26_9,
# BBL_20_2.0, BBM_20_2.0, BBU_20_2.0, BBB_20_2.0, BBP_20_2.0
df.ta.unchain() # back to normal append mode
No more repetitive append=True on every call. The chain mode accumulates columns in one fluent expression, then unchain() returns you to standard usage.
🔬 TA-Lib Parity Fixes
Wilder's Smoothing
The PR #112 remediation extracted wilder_smooth() into a shared utility (utils/_wilder.py). It implements Wilder's cumulative-sum smoothing with the correct sum(raw[1:length]) seeding, matching TA-Lib's internal PLUS_DM / MINUS_DM calculation exactly. Used by dm.py — no more hand-rolled NumPy loop inlined.
Chained EMA Lookbacks
DEMA, TEMA, and T3 now correctly strip leading NaN before feeding EMA output back into EMA. This matches TA-Lib's lookback of depth*(length-1). Extracted into _ema_chain() in overlap/ema.py, reducing ~70 lines of repetitive boilerplate to ~10.
PSAR Reversal Check
The SAR guard (max/min clamp at row-1/row-2) now applies before the reversal test, matching TA-Lib's behaviour. Previously, the raw projected SAR was checked, causing off-by-one splits at reversal bars.
Bug Fixes
cdl_doji— fixed<→<=threshold and addedshift(1)to match TA-Lib's look-ahead behaviorichimoku—apply_fillnow covers all 5 output series (was 3)pvr— added None-guard, offset, and fill support- 13 indicators — added missing
apply_fillforfillna/fill_methodkwargs
🧪 Test Infrastructure
assertions.py + IndicatorSpec
assert_indicator_standard(self, IndicatorSpec(
func=ta.rsi,
args=[self.close],
expected_name="RSI_14",
expected_type=Series,
none_arg_idx=0,
))
One call tests: return type, name, columns (DataFrame), offset, fill (fillna, ffill, bfill), None-guard, and length-in-name. Applied uniformly across all indicator test modules.
Property-Based Testing
55 Hypothesis tests using @given(price_series(), ...). Examples:
SMA(constant) == constantfor all window sizesBBANDS: lower ≤ mid ≤ upperfor every rowRSIoutput always ∈ [0, 100]STDEValways non-negative- Offset preserves length, fillna removes NaN
verify_series(None)returns None
Fixture Auto-Regeneration
tests/__init__.py now regenerates expected_values.json and regression_snapshots.json on import when TA-Lib is installed. No more stale fixtures — test data is always in sync with the code.
make test-all # regenerate fixtures + run 1427 tests
make fixtures # regenerate fixture JSONs only (requires TA-Lib)
Oracle Parity
- 60/60 TA-Lib oracle tests now pass at
tol=1e-7— exact float64 match achieved by the Wilder smoothing and chained EMA fixes
📦 Package & Quality
Code Modernization
- Removed 279 unnecessary
# -*- coding: utf-8 -*-declarations (UP009) - 65 useless
f"..."prefixes (no placeholders) removed - 87 unused imports removed across candle/overlap/momentum modules
Optional[X]→X | None,List[Y]→list[Y](pyupgrade)tal→talibrename — all test files now importtalibdirectlyruffCI-critical checks (E9, F63, F7, F82) — all passed
Python Support
Tested and passing on Python 3.10, 3.11, 3.12, 3.13, 3.14.
🔗 Links
- GitHub: github.com/xgboosted/pandas-ta-classic
- PyPI:
pip install pandas-ta-classic - Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md