Follow-up testing showed the earlier diagnosis was wrong. numpy np.average (unweighted) and numpy np.mean are bit-for-bit identical (0/5000 random-window mismatches), so the numba-OFF fallback path is bit-identical to the pre-njit output. The ~1-ULP deviation is entirely numba's JIT-compiled np.mean reduction differing from numpy's, only on the JIT path. Corrected the docstring and CHANGELOG accordingly; jma remains the sole indicator whose JIT and fallback paths differ from each other. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
35 KiB
35 KiB
Changelog
All notable changes to this project will be documented in this file. Format: Keep a Changelog.
[Unreleased]
Added
- backtesting.py integration (PR #124 by @Adhyansinghgupta): Bridge function (
ta_bridge),SMACrossoverexample strategy (examples/backtesting_py_strategy.py), and integration tutorial (docs/tutorials/backtesting_py.md). Addedbacktestingtointegrationoptional dependencies. - backtrader integration (
docs/tutorials/backtrader.md,examples/backtrader_strategy.py): Precompute-then-feed pattern using dynamicPandasDatasubclass (make_feed()); covers single-output, multi-output (MACD), and OHLCV-dependent (ATR) indicators. Addedbacktradertointegrationoptional dependencies. - vectorbt integration tutorial (
docs/tutorials/vectorbt.md): Documented thedf.ta.tsignals()→vbt.Portfolio.from_signals()integration pattern, including multi-output indicator handling and benchmark comparison. - Type stubs for
AnalysisIndicators(pandas_ta_classic/core.pyi): IDE autocomplete and mypy now see full method signatures for every indicator. ichimoku()single-DataFrame return (as_dataframe=True): opt in to a single DataFrame of the visible period instead of the legacy(visible, span)tuple. Passappend_span=Trueto also append the future-dated projected span rows.append_spanis now a real parameter on the underlyingichimoku()function (previously accessor-only) and is forwarded bydf.ta.ichimoku().
Changed
td_seq~3500× faster (numba): the Tom DeMark Sequential consecutive-run count replacedrolling(13).apply(python_callback)with a numba@njitloop (~1912 ms→~0.5 msper 5000-bar call, the single largest indicator bottleneck). Bit-for-bit identical; falls back to a plain Python loop without numba. Reproduce withpython tools/bench_indicators.py.hilo~250× faster (numba): the Gann HiLo per-bar.iloc[]state loop moved into a numba@njitkernel over numpy arrays (~130 ms→~0.5 msper 5000-bar call). Output is identical for allmamodes; falls back to a plain Python loop without numba.jma~130× faster (numba): the Jurik Moving Average per-bar recursion (volatility bands + 3-stage filter) moved into a numba@njitloop with scalar coefficients precomputed by the caller (~50 ms→~0.4 msper 5000-bar call). The trailing-window average usesnp.meanin place of the originalnp.average; for an unweighted call numpy computes these bit-for-bit identically, so the numba-off fallback is bit-identical to the previous output. Under numba (JIT on),np.meancompiles to numba's own reduction, whose summation order differs from numpy's at the ULP level (~4e-16 relative, full float64 precision); compounded through the recursivejma[i] = jma[i-1] + det1update the JIT path lands within ~1 ULP of the original but not bit-for-bit identical. Inconsequential for any practical use;jmais the only optimised indicator here whose JIT and numba-off paths are not bit-identical to each other (every other one is).ha~50× faster (numba): the recursive Heikin-Ashi open (df.iat[]scalar loop) moved into a numba@njitscan over the precomputed HA_close array (~75 ms→~1.5 msper 5000-bar call). Output is identical; falls back to a plain Python loop without numba.stc~40× faster (numba): the two Schaff Trend Cycle stochastic-smoothing loops moved into a shared numba@njitkernel, parametrised by the gate series (pass 1 gates on the rolling minimum, pass 2 on the rolling range) (~82 ms→~2 msper 5000-bar call). Output is bit-for-bit identical (the cumulative 8-decimal rounding is preserved inside the kernel); falls back to a plain Python loop without numba.wad~15× faster: Williams A/D replacedSeries.combine(prev_close, max/min)(a per-element Python callback) with vectorisednp.fmax/np.fmin(~16 ms→~1 msper 5000-bar call). Output is identical; pure numpy, no numba needed.wilder_smooth/dm~5× faster (numba): Wilder's cumulative smoothing (utils/_wilder.py, used bydm) moved its per-bar recursion into a numba@njitkernel. The seed (np.nansum(raw[1:length])) is still computed with numpy in the caller and passed in, so the cumulative sum matches bit-for-bit — the kernel runs only the deterministic scalar recursion.dm~10.5 ms→~2.0 msper 5000-bar call. Bit-for-bit identical; falls back to a plain Python loop without numba.pmax~4.6× faster (numba): the PMAX adaptive-band / trend-direction per-bar loop is now@njit-compiled with its Python-list accumulators replaced by numpy arrays (~5.4 ms→~1.2 msper 5000-bar call; the residual is the ATR/MA prep). The loop is pure comparisons +min/max+ assignment, so output is bit-for-bit identical; falls back to a plain Python loop without numba.npround~400× faster (vectorised): replaced the per-elementclose.apply(np.round)Python callback with a single vectorisednp.round(close)(~6 ms→~0.02 msper 5000-bar call). Output is bit-for-bit identical.aroon,maxindex,minindex,minmaxindex~9–17× faster (vectorised): the rollingargmax/argminarg-position loops (Series.rolling(length).apply(np.argmax/argmin, raw=True)) now use a shared_sliding_argextreme()helper built onnumpy.lib.stride_tricks.sliding_window_view(mirrors the existing_sliding_weighted_ma). aroon~12 ms→~0.7 ms, minmaxindex~8 ms→~0.8 ms, maxindex/minindex~4 ms→~0.4 msper 5000-bar call. Integer arg-positions → bit-for-bit identical output; pure numpy, no numba needed.ebsw~850× faster (numba): the Even Better SineWave per-bar.iloc[]HighPass + SuperSmoother recursion moved into a numba@njitkernel over a numpy array, with the (bar-invariant) filter coefficients hoisted out of the loop and the 2-elementFilterHistlist replaced by two scalars (~34 ms→~0.04 msper 5000-bar call). Output is bit-for-bit identical; falls back to a plain Python loop without numba.kama~90× faster (numba): Kaufman's Adaptive MA per-bar smoothing recursion moved into a numba@njitloop over numpy arrays (the vectorised efficiency-ratio/smoothing-constant prep stays in pandas) (~30 ms→~0.3 msper 5000-bar call). Output is bit-for-bit identical; falls back to a plain Python loop without numba.mama~55× faster (numba): the MESA Adaptive MA / FAMA inline Hilbert-Transform loop is now@njit-compiled (~16 ms→~0.3 msper 5000-bar call). Output is bit-for-bit identical (verified against the pure-Python.py_func); falls back to a plain Python loop without numba.- Candlestick patterns ~32× faster (numba): all 60 native
cdl_*pattern per-bar detection loops (the TA-Lib incremental running-window algorithm) moved into numba@njitkernels over numpy arrays, with the average-factor constants and range arrays hoisted by the caller.cdl_pattern(name="all")drops from~288 msto~9 msper 5000-bar call. Output is bit-for-bit identical for every pattern; falls back to a plain Python loop without numba. - Faster cold import (~3–4×):
import pandas_ta_classictakes ~280 ms (was ~930 ms) because indicator functions load on demand. Public API unchanged. - Math operators individually importable: Each math/trig operator (
add,sub,mult,div,rolling_max/min/sum,acos,cos,exp,ln, …) now lives in its own submodule, e.g.from pandas_ta_classic.math.add import add. combination()delegates tomath.comb: Replaces the hand-rolled nCr loop. Signature and results unchanged; the unusedmultichoosekwarg alias was dropped (userepetition).npNaNalias removed internally: All modules now usenp.nandirectly. No public API change.- All
npXnumpy import aliases removed (26 aliases, e.g.npSqrt,npArange,npNdArray): modules now useimport numpy as np+np.xdirectly. Internal only; no public API change. - Explicit package namespace:
pandas_ta_classic/__init__.py,core.py, andutils/__init__.pyno longer use star imports — every re-export is explicit with__all__defined. All documented names (utility functions, metrics,Strategy, lazy-loaded indicators) are unchanged. Incidental namespace leaks (e.g.ta.np,ta.pd,ta.DataFrame,ta.logger) are gone; import these from their real homes. - Lint-clean repo:
ruff check .passes with zero errors and zero per-file ignores. Ambiguous variables renamed (O→O_in candle loops,l→lowin tests);sys.pathbootstrap hacks removed fromtests/fixtures/,tools/, anddocs/conf.py(the editable install makes them redundant); notebook cells reordered to import-first. linear_regression()always uses the numpy implementation: the"r"key is now consistently the Pearson correlation coefficient. Previously, environments with scikit-learn installed silently usedLinearRegression.score()(R²) instead, so results depended on the environment. Affectspure_profit_score.optimal_leverage()returns a float: the result is no longer truncated withint(), thecapitalargument is documented, the unused**kwargsparameter is removed, and the "Incomplete. Do NOT use" docstring warning is removed. Zero-variance input now raisesValueError(previously crashed withOverflowError).- Optional-dependency extras restructured: the
integrationextra is split intodata(yfinance,alpha-vantage— the only integrations the library imports, lazily viautils/data) andbacktest(backtesting,vectorbt,backtrader— docs/examples only).integrationis retained as an alias fordata,backtest. The[all]extra no longer pullsdata/backtest, sopip install "pandas-ta-classic[all]"stays installable on newer Python/OS combinations that lack wheels for these unmaintained, platform-fragile packages; install them explicitly when needed. - tulipy oracle frozen to a golden file:
tulipy(unmaintained, no wheels for CPython ≥3.12) is removed from theoracleextra and no longer imported at test time. Its deterministic outputs are snapshotted intests/fixtures/tulipy_oracle.json(regenerate withtests/fixtures/generate_tulipy_oracle.pyon CPython <3.12), andtest_oracle_tulipy.pynow compares native output against the frozen arrays on every Python version. This fixes thetesting-oracleCI job on Python 3.12–3.14, where the tulipy install previously failed.ta-libremains the live primary oracle. (The MSW oracle tolerance was loosened to1e-3to stay robust to ~1e-4numpy-version float drift in that recursive trig indicator.) tal_ma()no longer needs TA-Lib and fails fast: the MA-name→MA_Typemapping is now a plain dict of the (frozen) TA-Lib enum values, sotal_ma("ema") == 1regardless of whether TA-Lib is installed (previously it silently returned0/SMA when TA-Lib was absent). Unknown names now raiseValueErrorand non-string input raisesTypeErrorinstead of silently defaulting to SMA. Callers (bbands,ppo,apo) already normalisemamodeto a valid string, so their behaviour is unchanged.
Deprecated
- Built-in data fetching (
df.ta.ticker(),ta.yf(),ta.av()): emit aFutureWarningand will be removed in a future release. Data fetching is out of scope for a technical-analysis library. Fetch OHLCV withyfinance/alpha-vantagedirectly and pass the DataFrame to pandas-ta-classic; see the newexamples/fetch_market_data.pyfor the replacement patterns. Thedataoptional extra remains available during the deprecation window. ichimoku()tuple return: returning a(visible, span)tuple is deprecated and now emits aDeprecationWarning. Passas_dataframe=Trueto opt in to the single-DataFrame return (addappend_span=Truefor the projected span rows), oras_dataframe=Falseto keep the tuple without warning. The accessordf.ta.ichimoku()already returns a DataFrame and is unaffected.CDL_PATTERN_NAMES: UseALL_PATTERNSinstead. Accessing the old name emits aDeprecationWarning.tsignalsdriftparameter: Passingdriftnow emits aDeprecationWarningand the value is ignored — trade signals are always computed with a 1-period difference. The parameter will be removed in a future release.- Inactive
driftparameters oncfo,inertia,kst,rsx,chop,accbands,kvo: These indicators accepted adriftparameter that never entered their calculation (dead since the upstream template). Passingdriftnow emits aDeprecationWarning; the value has never affected the result and the parameter will be removed in a future release. Misleading docstrings were corrected (e.g.cfo's "short period",chop'sATR(drift)pseudocode).
Removed
- Dead code (audit, zero callers):
BasePandasObjectand_check_na_columns()incore.py; CPR helpersround_to_strike,calculate_option_strikes,detect_cpr_breakout,detect_cpr_rejection; math utilsgeometric_mean,log_geometric_mean, and the hand-rollederf; time utilsdf_dates,df_month_to_date/mtd,df_quarter_to_date/qtd;category_files(); six unusedCandleArrayshelper methods; thepkg_resourcesPython < 3.8 fallback in_meta.py;tests/context.pyand other unused test scaffolding. crossany(): zero callers and zero tests; usecross(a, b, above=True) | cross(a, b, above=False)if needed. Docs entry removed.high_low_range()/real_body()wrappers (utils/_candles.py): call sites now usenon_zero_range()directly (real_body(open_, close)≡non_zero_range(close, open_)).ytdalias: usedf_year_to_date(). Internal_camelCase2Titleinlined at its single call site.- Unused dev/optional dependencies:
stochastic(never imported),cython(no.pyxsources),pytest-covandpytest-benchmark(no coverage/benchmark runs),isort(black owns formatting). CorrespondingImportsprobes and the Makefile isort step removed. - Unused hard dependencies:
scipy,scikit-learn, andstatsmodelsdropped from[project.dependencies]— nothing in the package imports them anymore._linear_regression_sklearn()removed (see Changed). StaleImportsprobes pruned (backtrader,matplotlib,mplfinance,numba,scipy,sklearn,statsmodels,vectorbt,yaml); numba acceleration is unaffected (utils/_njit.pyself-detects numba).
Fixed
tsignalsdriftcorrupted trade signals:trends.diff(drift)computed entries/exits against the statedriftbars ago instead of the previous bar, sodrift != 1reported spurious entries mid-trend and missed real crossovers (contradicting the documenteddiff()behavior). Now always uses a 1-period difference. Output at the default (drift=1) is unchanged.- Cross-package indicator imports: A submodule import could overwrite a re-exported function of the same name on the parent package (e.g.
from pandas_ta_classic.volatility import atroccasionally returned theatrmodule instead of the function). Resolved. - Test-fixture regen no longer drops
cmo_14entries when running tests without tulipy installed. Generators now merge with existing JSON instead of overwriting.
[0.6.52] - 2026-06-25
Added
- SMC Liquidity Sweep (
smc_sweep) (PR #123 by @Adhyansinghgupta): Bullish and bearish smart-money liquidity sweep indicator for momentum analysis. Available asdf.ta.smc_sweep(). - ichimoku
append_span(PR #120): Newappend_spanparameter on the ichimoku accessor for span-appending control.
Changed
- CPR numeric encoding (PR #117):
calculate_price_position()andcalculate_cpr_width()now returnnp.int8instead of string labels.CPR_POSITION:1(above TC),0(inside CPR),-1(below BC).CPR_WIDTH_CLASS:1(wide),0(medium),-1(narrow). All indicator columns are now numeric. AnalysisIndicators.__call__fail-fast: Removedexcept BaseException: passswallowing all indicator errors. Indicator exceptions now propagate to callers instead of silently returningNone. Code that relied ondf.ta.rsi()never raising must add its own error handling.
Fixed
- ichimoku accessor returns DataFrame (PR #116):
df.ta.ichimoku()now returns a DataFrame instead of a tuple. - macdext silent double-fallback (PR #121): Eliminated silent double-fallback for KAMA/MAMA matypes in
macdext.
Documentation
- long_run / short_run / xsignals (PR #119): Clarified
fast/slowas pre-computed Series; addedxa/xbrange guidance. - beta / correl benchmark (PR #118): Documented that
benchmarkis required for non-Noneoutput.
Dependencies
- actions/checkout v7 (PR #122): Bumped from v6 to v7.
[0.6.20] - 2026-05-21
Added
apply_offset/apply_fillhelpers (PR #105): Extracted intoutils/and all indicators migrated to use them. Removes ~200 lines of duplicated offset/fill logic.- Comprehensive candle pattern tests (PR #106): 59 TA-Lib candle patterns covered by CI tests.
- Fluent API chaining (PR #113): DataFrame accessor supports method chaining.
- Property-based testing (PR #114): Hypothesis-based tests added to test suite.
- Full Indicator Name Comments: All indicator files include full indicator names as comments on line 1 (format:
# Full Indicator Name (ABBREVIATION)). - UV Package Manager Support: All documentation includes
uvinstall instructions alongsidepip. - Native Candlestick Patterns: Added native
cdl_dojiandcdl_insideimplementations (no TA-Lib required). Accessible viadf.ta.cdl_doji(),df.ta.cdl_inside(), ordf.ta.cdl_pattern().
Changed
- Wilder smoothing shared utility (PR #112 remediation): Extracted
wilder_smooth()intoutils/_wilder.pyfor TA-Lib-exact cumulative smoothing. Used bydm.pyfor PLUS_DM/MINUS_DM parity. - Chained EMA helper (PR #112 remediation): Added
_ema_chain()tooverlap/ema.pyfor consistent NaN-stripping in DEMA, TEMA, T3. Reduces repetitive boilerplate by ~60 lines. - Fixture auto-regeneration:
tests/__init__.pynow regeneratesexpected_values.jsonandregression_snapshots.jsonon import when TA-Lib is available.make fixturesandmake test-alltargets added toMakefile. tal→talibrename: All test files now importtalibdirectly instead of aliasing astal, matching source code convention.- Dead code removal: Removed ~370 instances of unused imports (F401), 8 unused local variables (F841), 1 duplicate method (
test_custom_a), 65 useless f-string prefixes (F541), and 279 unnecessary UTF-8 encoding declarations (UP009). - Code modernization: Applied pyupgrade (UP) and flake8-return (RET) fixes —
Optional[X]→X|None,List→list, removed redundantelseafterreturn. - Linreg TA-Lib dispatch: Replaced 6-branch
if/elifchain with_TALIB_DISPATCHlookup dictionary. - PSAR cleanup: Removed
import numpy as _npfrom function body; uses module-levelnpinstead. - test_strategy: Fixed duplicate
test_custom_amethod (was shadowed, never ran). Fixed stale column count assertion.
Fixed
- TA-Lib-exact native implementations (PR #112): Corrected native paths for many indicators to match TA-Lib output exactly.
- stdev variance calculation (PR #109):
ddofdefault updated toFalsefor population variance. - Modularity refactor (PR #108): Issue #46 modularity improvements.
- Accessor usability (PR #107): Issue #48 usability and docs fixes.
- Alpha Vantage integration (PRs #110, #111): Support for both
alpha_vantageandalphaVantagelibraries; improved import checks and error handling. - Feature fix PR #112 (PR #115): Follow-up corrections to the TA-Lib-exact implementation from PR #112.
[0.5.44] - 2026-04-30
Added
- TA-Lib / tulipy parity indicator set (PR #104): Added wrappers and native implementations for
msw,fosc,macdext,macdfix,rocp,rocr,rocr100,stochf,avgprice,medprice,typprice,linregangle,linregintercept,linregslope,mavp,md,stderr,dx,edecay,plus_dm,minus_dm,sarext,avolume,cvi,hvol,emv,marketfi,vosc, andwad. - Math operator namespace: Added
pandas_ta_classic/math/exposing arithmetic operators (add,sub,mult,div), rolling operators (rolling_max,rolling_min,rolling_sum), and math transforms for TA-Lib/tulipy compatibility. - Oracle parity suites: Added
tests/test_oracle_talib.pyandtests/test_oracle_tulipy.pyfor cross-library validation on shared SPY fixtures. - 60 native CDL pattern files (PR #87): Added
candles/cdl_*.pyimplementations for 60 patterns. Combined withcdl_dojiandcdl_inside, total accessible viacdl_pattern()is 62. TA-Lib is never used for CDL patterns — native implementations take priority regardless of TA-Lib installation. Added shared_cdl_math.pyhelper. - 5 Hilbert Transform cycle indicators (PR #83):
ht_dcperiod,ht_dcphase,ht_phasor,ht_sine,ht_trendmode. Shared_hilbert.pyhelper. Cycles category grows from 2 to 7. - MAMA / FAMA (PR #84): MESA Adaptive Moving Average with FAMA output. Uses Ehlers' adaptive phase computation.
- HT_TRENDLINE (PR #84): Hilbert Transform Instantaneous Trendline. Added to overlap category.
- TSF (PR #85): Time Series Forecast — linear regression projected one period ahead. Matches TA-Lib TSF.
- Beta (PR #86): Asset volatility relative to a benchmark series. Matches TA-Lib BETA.
- CORREL (PR #86): Pearson Correlation Coefficient between two series. Matches TA-Lib CORREL.
- ADXR (PR #89): Average Directional Movement Index Rating — smoothed average of ADX. Matches TA-Lib ADXR.
- CPR (PR #77): Central Pivot Range with 4 calculation methods (classic, camarilla, fibonacci, woodie).
- Chandelier Exit (
ce): Trailing stop.CE_L = rolling_max(high, length) - multiplier × ATR,CE_S = rolling_min(low, length) + multiplier × ATR. Defaultlength=22,multiplier=3.0. Returns DataFrame withCE_L_{length}_{multiplier}andCE_S_{length}_{multiplier}. - 9 New Technical Indicators (Issue #29): LRSI (Laguerre RSI), PMAX (Price Max), VFI (Volume Flow Indicator), MMAR (Madrid Moving Average Ribbon), Rainbow (Rainbow Charts), PO (Projection Oscillator), DSP (Detrended Synthetic Price), TRIXH (TRIX Histogram), VWMACD (Volume Weighted MACD).
Changed
- QQE output columns (PR #97):
qqe()now returns 6 columns instead of 3. New columns:QQEb_l(long band),QQEb_s(short band),QQEd(±1 trend direction). Breaking change: code relying on a fixed column count or positional indexing must be updated. - Updated indicator counts: 164 indicators in Category (was 151); total 224 with native CDL patterns (was 213).
linregbreaking default change:degreeskwarg now defaults toTrue(wasFalse) to match TA-Lib. Callers usinglinreg(close, angle=True)withoutdegrees=Falsewill now receive degrees instead of radians.stdev/variancebreaking default change:ddofnow defaults to0(population, was1sample) to match TA-Lib. Callers relying on sample variance must passddof=1explicitly.natrbreaking default change:mamodenow defaults to'rma'(Wilder smoothing, was'ema') to match TA-Lib. Callers relying on EMA-based NATR must passmamode='ema'explicitly.- Native preferred by default for all indicators with
talibparameter: Native implementation used by default across all 59 indicators. Callers wanting TA-Lib output must passtalib=Trueexplicitly. - Enhanced RVGI: Relative Vigor Index now includes histogram column (RVGI − Signal).
- Dynamic Category Discovery:
Categorydict in_meta.pynow built dynamically from filesystem structure. Auto-discovers previously undocumented indicators (cdl_doji,cdl_inside,hwma,ma,drawdown,dm,vp). - Python Version Support: Rolling 5-version support policy (LATEST-4 through LATEST). Managed dynamically via
LATEST_PYTHON_VERSIONin.github/workflows/ci.yml. - Development Status: Changed from Beta to Production/Stable in
pyproject.toml.
Performance
- numpy vectorization (PR #88): 15 indicators (QQE, PSAR, HWC, HT_TRENDLINE, SSF, squeeze, squeeze_pro, RVGI, TD_SEQ, TOS_STDEVALL, ALMA, SINWMA, SWMA, TRIMA, VIDYA) now use
sliding_window_viewinstead of pandas.ilocloops. Adds shared_sliding_weighted_ma()utility. - Numba JIT acceleration (PR #99): 10 indicators (SSF, MCGD, HWMA, RSX, PSAR, Supertrend, QQE, and 3 more) gain optional
@njit(cache=True)via numba. Graceful no-op fallback inutils/_njit.py. Enable withpip install pandas-ta-classic[performance]. Speedups: RSX 230×, HWMA 70×, MCGD 43×, SSF 42×, Supertrend 13×, QQE 10×, PSAR 6×.
Fixed
- Oracle test policy: Replaced skip-based oracle tests with explicit assertions for value equivalence or documented divergence. Zero skipped tests.
- TA-Lib compatibility paths: Added/updated
talib=Truebehavior formacdfix,psar,stochrsi,plus_dm,minus_dm. - Indicator formula parity: Corrected
edecay(multiplicative exponential decay),emvscaling (divisor=10000).
[0.4.47] - 2026-03-17
Fixed
- Dependency cleanup, pandas 3.0 compat, Windows pool fix (PR #79).
- Initialization and edge-case bugs across 11 indicators (PR #80).
- Numerical bugs in
linreg,tsi,brar,bbands,cti(PR #94). - TA-Lib reference alignment for 8 indicators (PR #81).
- Rolling stats cross-version determinism: Replaced pandas rolling stats with numpy (PR #82).
- None-guards to prevent crashes on short/invalid input across 26 files (PR #95).
- print() → logging across library code (PR #93). Breaking: code catching print output must switch to log capture.
- Strategy dataclass bugs (PR #96). Breaking: some Strategy API surface changed.
- Code of Conduct Contact: Updated enforcement contact from original maintainer email to GitHub Issues.
- PyPI Release Version: Set
SETUPTOOLS_SCM_PRETEND_VERSIONfrom the release tag to prevent.dev0versions being published. - Version Scheme: Changed from post-release to default scheme. Tagged releases get clean versions (e.g.,
0.4.47); commits after a tag get.devNsuffix. - PyPI Image Display: Updated README.md to use absolute GitHub URLs so images render correctly on the PyPI package page.
- CI/CD Shallow Clone: Added
fetch-depth: 0to all checkout steps to ensure full git history for setuptools-scm. - Version Fallback: Changed fallback from
0.0.0.dev0to0.0.0(PEP 440 compliant).
Added
- Automatic Version Management: Version now determined from git tags via
setuptools-scm. Development builds get.devsuffix; tagged releases use the tag exactly. See CONTRIBUTING.md for documentation.
[0.3.78] - 2026-02-27
Changed
- Type hints (PR #67 by @rmarcink): Type annotations added across all public function signatures.
Pre-0.3.78 — Historical
Items below describe the state of the library as inherited from the original
pandas-taproject and pre-2026 development. Preserved for historical reference.
General
- A Strategy Class to help name and group your favorite indicators.
- If a TA Lib is already installed, Pandas TA will run TA Lib's version. (BETA)
- Some indicators have had their
mamodekwarg updated with more moving average choices with the Moving Average Utility functionta.ma(). For simplicity, all choices are single source moving averages. This is primarily an internal utility used by indicators that have amamodekwarg. This includes indicators: accbands, amat, aobv, atr, bbands, bias, efi, hilo, kc, natr, qqe, rvi, and thermo; the defaultmamodeparameters have not changed. However,ta.ma()can be used by the user as well if needed. For more information:help(ta.ma)- Moving Average Choices: dema, ema, fwma, hma, linreg, midpoint, pwma, rma, sinwma, sma, swma, t3, tema, trima, vidya, wma, zlma.
- An experimental and independent Watchlist Class located in the Examples Directory that can be used in conjunction with the new Strategy Class.
- Linear Regression (linear_regression) is a new utility method for Simple Linear Regression using Numpy or Scikit Learn's implementation.
- Added utility/convience function,
to_utc, to convert the DataFrame index to UTC. See:help(ta.to_utc)Now as a Pandas TA DataFrame Property to easily convert the DataFrame index to UTC.
Breaking / Depreciated Indicators
- Trend Return (trend_return) has been removed and replaced with tsignals. When given a trend Series like
close > sma(close, 50)it returns the Trend, Trade Entries and Trade Exits of that trend to make it compatible with vectorbt by settingasbool=Trueto get boolean Trade Entries and Exits. Seehelp(ta.tsignals)
New Indicators
- Arnaud Legoux Moving Average (alma) uses the curve of the Normal (Gauss) distribution to allow regulating the smoothness and high sensitivity of the indicator. See:
help(ta.alma) - Draw Down (drawdown) calculates the percentage decline from the peak equity of a trading account, or fund. See
help(ta.drawdown) - Candle Patterns (cdl_pattern) If TA Lib is installed, then all those Candle Patterns are available. See the list and examples above on how to call the patterns. See
help(ta.cdl_pattern) - Candle Z Score (cdl_z) normalizes OHLC Candles with a rolling Z Score. See
help(ta.cdl_z) - Correlation Trend Indicator (cti) is an oscillator created by John Ehler in 2020. See
help(ta.cti) - Cross Signals (xsignals) was created by Kevin Johnson. It is a wrapper of Trade Signals that returns Trends, Trades, Entries and Exits. Cross Signals are commonly used for bbands, rsi, zscore crossing some value either above or below two values at different times. See
help(ta.xsignals) - Directional Movement (dm) developed by J. Welles Wilder in 1978 attempts to determine which direction the price of an asset is moving. See
help(ta.dm) - Even Better Sinewave (ebsw) measures market cycles and uses a low pass filter to remove noise. See:
help(ta.ebsw) - Jurik Moving Average (jma) attempts to eliminate noise to see the "true" underlying activity.. See:
help(ta.jma) - Klinger Volume Oscillator (kvo) was developed by Stephen J. Klinger. It is designed to predict price reversals in a market by comparing volume to price.. See
help(ta.kvo) - Schaff Trend Cycle (stc) is an evolution of the popular MACD incorportating two cascaded stochastic calculations with additional smoothing. See
help(ta.stc) - Squeeze Pro (squeeze_pro) is an extended version of "TTM Squeeze" from John Carter. See
help(ta.squeeze_pro) - Tom DeMark's Sequential (td_seq) attempts to identify a price point where an uptrend or a downtrend exhausts itself and reverses. Currently exlcuded from
df.ta.strategy()for performance reasons. Seehelp(ta.td_seq) - Think or Swim Standard Deviation All (tos_stdevall) indicator which
returns the standard deviation of data for the entire plot or for the interval
of the last bars defined by the length parameter. See
help(ta.tos_stdevall) - Vertical Horizontal Filter (vhf) was created by Adam White to identify trending and ranging markets.. See
help(ta.vhf)
Updated Indicators
- Acceleration Bands (accbands) Argument
mamoderenamed tomode. Seehelp(ta.accbands). - ADX (adx): Added
mamodewith default "RMA" and with the samemamodeoptions as TradingView. New argumentlensigso it behaves like TradingView's builtin ADX indicator. Seehelp(ta.adx). - Archer Moving Averages Trends (amat): Added
driftargument and more descriptive column names. - Average True Range (atr): The default
mamodeis now "RMA" and with the samemamodeoptions as TradingView. Seehelp(ta.atr). - Bollinger Bands (bbands): New argument
ddoffto control the Degrees of Freedom. Also included BB Percent (BBP) as the final column. Default is 0. Seehelp(ta.bbands). - Choppiness Index (chop): New argument
lnto use Natural Logarithm (True) instead of the Standard Logarithm (False). Default is False. Seehelp(ta.chop). - Chande Kroll Stop (cksp): Added
tvmodewith defaultTrue. Whentvmode=False, cksp implements "The New Technical Trader" with default values. Seehelp(ta.cksp). - Chande Momentum Oscillator (cmo): New argument
talibwill use TA Lib's version and if TA Lib is installed. Default is True. Seehelp(ta.cmo). - Decreasing (decreasing): New argument
strictchecks if the series is continuously decreasing over periodlengthwith a faster calculation. Default:False. Thepercentargument has also been added with default None. Seehelp(ta.decreasing). - Increasing (increasing): New argument
strictchecks if the series is continuously increasing over periodlengthwith a faster calculation. Default:False. Thepercentargument has also been added with default None. Seehelp(ta.increasing). - Klinger Volume Oscillator (kvo): Implements TradingView's Klinger Volume Oscillator version. See
help(ta.kvo). - Linear Regression (linreg): Checks numpy's version to determine whether to utilize the
as_stridedmethod or the newersliding_window_viewmethod. This should resolve Issues with Google Colab and it's delayed dependency updates as well as TensorFlow's dependencies as discussed in Issues #285 and #329. - Moving Average Convergence Divergence (macd): New argument
asmodeenables AS version of MACD. Default is False. Seehelp(ta.macd). - Parabolic Stop and Reverse (psar): Bug fix and adjustment to match TradingView's
sar. New argumentaf0to initialize the Acceleration Factor. Seehelp(ta.psar). - Percentage Price Oscillator (ppo): Included new argument
mamodeas an option. Default is sma to match TA Lib. Seehelp(ta.ppo). - True Strength Index (tsi): Added
signalwith default13and Signal MA Modemamodewith default ema as arguments. Seehelp(ta.tsi). - Volume Profile (vp): Calculation improvements. See Pull Request #320 See
help(ta.vp). - Volume Weighted Moving Average (vwma): Fixed bug in DataFrame Extension call. See
help(ta.vwma). - Volume Weighted Average Price (vwap): Added a new parameter called
anchor. Default: "D" for "Daily". See Timeseries Offset Aliases for additional options. Requires the DataFrame index to be a DatetimeIndex. Seehelp(ta.vwap). - Volume Weighted Moving Average (vwma): Fixed bug in DataFrame Extension call. See
help(ta.vwma). - Z Score (zscore): Changed return column name from
Z_lengthtoZS_length. Seehelp(ta.zscore).