""" Cross-library wrapper registry — comprehensive indicator coverage. Unified interface: execute_indicator(library, indicator, data, df=None, **kwargs) Supported libraries: ferro_ta, talib, pandas_ta, ta, tulipy, finta 50+ indicators across all categories. """ from __future__ import annotations from typing import Any import numpy as np def _try_import(name): try: import importlib; return importlib.import_module(name) except ImportError: return None _talib = _try_import("talib") _pta = _try_import("pandas_ta") _ta = _try_import("ta") _tl = _try_import("tulipy") _fi_m = _try_import("finta") _fi = getattr(_fi_m, "TA", None) if _fi_m else None def available_libraries(): libs = ["ferro_ta"] if _talib: libs.append("talib") if _pta: libs.append("pandas_ta") if _ta: libs.append("ta") if _tl: libs.append("tulipy") if _fi: libs.append("finta") return libs def is_supported(library: str, indicator: str) -> bool: """Return True if a wrapper exists for the given (library, indicator) pair.""" if library not in available_libraries(): return False return (library, indicator) in REGISTRY def _strip_nan(arr): a = np.asarray(arr, dtype=np.float64).ravel() return a[np.isfinite(a)] def _c64(a): return np.ascontiguousarray(a, dtype=np.float64) def _empty(): return np.array([], dtype=np.float64) def _first_col(df, prefix): col = next((c for c in df.columns if c.startswith(prefix)), None) return _strip_nan(df[col].values) if col is not None else _empty() # ============================================================ # OVERLAP # ============================================================ def _sma_ft(d,df,timeperiod=20,**_): import ferro_ta; return _strip_nan(ferro_ta.SMA(d["close"],timeperiod=timeperiod)) def _sma_tl(d,df,timeperiod=20,**_): return _strip_nan(_talib.SMA(d["close"],timeperiod=timeperiod)) def _sma_pt(d,df,timeperiod=20,**_): return _strip_nan(_pta.sma(df["close"],length=timeperiod).values) def _sma_ta(d,df,timeperiod=20,**_): from ta.trend import SMAIndicator; return _strip_nan(SMAIndicator(df["close"],window=timeperiod).sma_indicator().values) def _sma_tu(d,df,timeperiod=20,**_): return _strip_nan(_tl.sma(_c64(d["close"]),period=timeperiod)) def _sma_fi(d,df,timeperiod=20,**_): return _strip_nan(_fi.SMA(df,timeperiod).values) def _ema_ft(d,df,timeperiod=20,**_): import ferro_ta; return _strip_nan(ferro_ta.EMA(d["close"],timeperiod=timeperiod)) def _ema_tl(d,df,timeperiod=20,**_): return _strip_nan(_talib.EMA(d["close"],timeperiod=timeperiod)) def _ema_pt(d,df,timeperiod=20,**_): return _strip_nan(_pta.ema(df["close"],length=timeperiod).values) def _ema_ta(d,df,timeperiod=20,**_): from ta.trend import EMAIndicator; return _strip_nan(EMAIndicator(df["close"],window=timeperiod).ema_indicator().values) def _ema_tu(d,df,timeperiod=20,**_): return _strip_nan(_tl.ema(_c64(d["close"]),period=timeperiod)) def _ema_fi(d,df,timeperiod=20,**_): return _strip_nan(_fi.EMA(df,timeperiod).values) def _wma_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.WMA(d["close"],timeperiod=timeperiod)) def _wma_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.WMA(d["close"],timeperiod=timeperiod)) def _wma_pt(d,df,timeperiod=14,**_): return _strip_nan(_pta.wma(df["close"],length=timeperiod).values) def _wma_ta(d,df,**_): return _empty() _wma_ta._stub = True def _wma_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.wma(_c64(d["close"]),period=timeperiod)) def _wma_fi(d,df,timeperiod=14,**_): return _strip_nan(_fi.WMA(df,timeperiod).values) def _dema_ft(d,df,timeperiod=20,**_): import ferro_ta; return _strip_nan(ferro_ta.DEMA(d["close"],timeperiod=timeperiod)) def _dema_tl(d,df,timeperiod=20,**_): return _strip_nan(_talib.DEMA(d["close"],timeperiod=timeperiod)) def _dema_pt(d,df,timeperiod=20,**_): return _strip_nan(_pta.dema(df["close"],length=timeperiod).values) def _dema_ta(d,df,**_): return _empty() _dema_ta._stub = True def _dema_tu(d,df,timeperiod=20,**_): return _strip_nan(_tl.dema(_c64(d["close"]),period=timeperiod)) def _dema_fi(d,df,timeperiod=20,**_): return _strip_nan(_fi.DEMA(df,timeperiod).values) def _tema_ft(d,df,timeperiod=20,**_): import ferro_ta; return _strip_nan(ferro_ta.TEMA(d["close"],timeperiod=timeperiod)) def _tema_tl(d,df,timeperiod=20,**_): return _strip_nan(_talib.TEMA(d["close"],timeperiod=timeperiod)) def _tema_pt(d,df,timeperiod=20,**_): return _strip_nan(_pta.tema(df["close"],length=timeperiod).values) def _tema_ta(d,df,**_): return _empty() _tema_ta._stub = True def _tema_tu(d,df,timeperiod=20,**_): return _strip_nan(_tl.tema(_c64(d["close"]),period=timeperiod)) def _tema_fi(d,df,timeperiod=20,**_): return _strip_nan(_fi.TEMA(df,timeperiod).values) def _t3_ft(d,df,timeperiod=5,**_): import ferro_ta; return _strip_nan(ferro_ta.T3(d["close"],timeperiod=timeperiod)) def _t3_tl(d,df,timeperiod=5,**_): return _strip_nan(_talib.T3(d["close"],timeperiod=timeperiod)) def _t3_pt(d,df,timeperiod=5,**_): return _strip_nan(_pta.t3(df["close"],length=timeperiod).values) def _t3_ta(d,df,**_): return _empty() _t3_ta._stub = True def _t3_tu(d,df,**_): return _empty() _t3_tu._stub = True def _t3_fi(d,df,**_): return _empty() _t3_fi._stub = True def _trima_ft(d,df,timeperiod=20,**_): import ferro_ta; return _strip_nan(ferro_ta.TRIMA(d["close"],timeperiod=timeperiod)) def _trima_tl(d,df,timeperiod=20,**_): return _strip_nan(_talib.TRIMA(d["close"],timeperiod=timeperiod)) def _trima_pt(d,df,timeperiod=20,**_): return _strip_nan(_pta.trima(df["close"],length=timeperiod).values) def _trima_ta(d,df,**_): return _empty() _trima_ta._stub = True def _trima_tu(d,df,timeperiod=20,**_): return _strip_nan(_tl.trima(_c64(d["close"]),period=timeperiod)) def _trima_fi(d,df,timeperiod=20,**_): return _strip_nan(_fi.TRIMA(df,timeperiod).values) def _kama_ft(d,df,timeperiod=10,**_): import ferro_ta; return _strip_nan(ferro_ta.KAMA(d["close"],timeperiod=timeperiod)) def _kama_tl(d,df,timeperiod=10,**_): return _strip_nan(_talib.KAMA(d["close"],timeperiod=timeperiod)) def _kama_pt(d,df,timeperiod=10,**_): return _strip_nan(_pta.kama(df["close"],length=timeperiod).values) def _kama_ta(d,df,**_): return _empty() _kama_ta._stub = True def _kama_tu(d,df,timeperiod=10,**_): return _strip_nan(_tl.kama(_c64(d["close"]),period=timeperiod)) def _kama_fi(d,df,**_): return _empty() _kama_fi._stub = True def _hma_ft(d,df,timeperiod=16,**_): import ferro_ta; return _strip_nan(ferro_ta.HULL_MA(d["close"],timeperiod=timeperiod)) def _hma_tl(d,df,**_): return _empty() _hma_tl._stub = True def _hma_pt(d,df,timeperiod=16,**_): return _strip_nan(_pta.hma(df["close"],length=timeperiod).values) def _hma_ta(d,df,**_): return _empty() _hma_ta._stub = True def _hma_tu(d,df,timeperiod=16,**_): return _strip_nan(_tl.hma(_c64(d["close"]),period=timeperiod)) def _hma_fi(d,df,timeperiod=16,**_): return _strip_nan(_fi.HMA(df,timeperiod).values) def _vwma_ft(d,df,timeperiod=20,**_): import ferro_ta; return _strip_nan(ferro_ta.VWMA(d["close"],d["volume"],timeperiod=timeperiod)) def _vwma_tl(d,df,**_): return _empty() _vwma_tl._stub = True def _vwma_pt(d,df,timeperiod=20,**_): r=_pta.vwma(df["close"],df["volume"],length=timeperiod); return _strip_nan(r.values) if r is not None else _empty() def _vwma_ta(d,df,**_): return _empty() _vwma_ta._stub = True def _vwma_tu(d,df,timeperiod=20,**_): return _strip_nan(_tl.vwma(_c64(d["close"]),_c64(d["volume"]),period=timeperiod)) def _vwma_fi(d,df,**_): return _empty() _vwma_fi._stub = True def _midpoint_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.MIDPOINT(d["close"],timeperiod=timeperiod)) def _midpoint_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.MIDPOINT(d["close"],timeperiod=timeperiod)) def _midpoint_pt(d,df,**_): return _empty() _midpoint_pt._stub = True def _midpoint_ta(d,df,**_): return _empty() _midpoint_ta._stub = True def _midpoint_tu(d,df,**_): return _empty() _midpoint_tu._stub = True def _midpoint_fi(d,df,**_): return _empty() _midpoint_fi._stub = True def _midprice_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.MIDPRICE(d["high"],d["low"],timeperiod=timeperiod)) def _midprice_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.MIDPRICE(d["high"],d["low"],timeperiod=timeperiod)) def _midprice_pt(d,df,**_): return _empty() _midprice_pt._stub = True def _midprice_ta(d,df,**_): return _empty() _midprice_ta._stub = True def _midprice_tu(d,df,**_): return _empty() _midprice_tu._stub = True def _midprice_fi(d,df,**_): return _empty() _midprice_fi._stub = True # ============================================================ # MOMENTUM # ============================================================ def _rsi_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.RSI(d["close"],timeperiod=timeperiod)) def _rsi_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.RSI(d["close"],timeperiod=timeperiod)) def _rsi_pt(d,df,timeperiod=14,**_): return _strip_nan(_pta.rsi(df["close"],length=timeperiod).values) def _rsi_ta(d,df,timeperiod=14,**_): from ta.momentum import RSIIndicator; return _strip_nan(RSIIndicator(df["close"],window=timeperiod).rsi().values) def _rsi_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.rsi(_c64(d["close"]),period=timeperiod)) def _rsi_fi(d,df,timeperiod=14,**_): return _strip_nan(_fi.RSI(df,timeperiod).values) def _macd_ft(d,df,fastperiod=12,slowperiod=26,signalperiod=9,**_): import ferro_ta; m,s,h=ferro_ta.MACD(d["close"],fastperiod=fastperiod,slowperiod=slowperiod,signalperiod=signalperiod); return _strip_nan(m) def _macd_tl(d,df,fastperiod=12,slowperiod=26,signalperiod=9,**_): m,s,h=_talib.MACD(d["close"],fastperiod=fastperiod,slowperiod=slowperiod,signalperiod=signalperiod); return _strip_nan(m) def _macd_pt(d,df,fastperiod=12,slowperiod=26,signalperiod=9,**_): r=_pta.macd(df["close"],fast=fastperiod,slow=slowperiod,signal=signalperiod); return _first_col(r,"MACD_") def _macd_ta(d,df,fastperiod=12,slowperiod=26,signalperiod=9,**_): from ta.trend import MACD; return _strip_nan(MACD(df["close"],window_fast=fastperiod,window_slow=slowperiod,window_sign=signalperiod).macd().values) def _macd_tu(d,df,fastperiod=12,slowperiod=26,signalperiod=9,**_): m,s,h=_tl.macd(_c64(d["close"]),short_period=fastperiod,long_period=slowperiod,signal_period=signalperiod); return _strip_nan(m) def _macd_fi(d,df,fastperiod=12,slowperiod=26,signalperiod=9,**_): return _strip_nan(_fi.MACD(df,fastperiod,slowperiod,signalperiod)["MACD"].values) def _stoch_ft(d,df,fastk_period=14,slowk_period=3,slowd_period=3,**_): import ferro_ta; k,dd=ferro_ta.STOCH(d["high"],d["low"],d["close"],fastk_period=fastk_period,slowk_period=slowk_period,slowd_period=slowd_period); return _strip_nan(k) def _stoch_tl(d,df,fastk_period=14,slowk_period=3,slowd_period=3,**_): k,dd=_talib.STOCH(d["high"],d["low"],d["close"],fastk_period=fastk_period,slowk_period=slowk_period,slowd_period=slowd_period); return _strip_nan(k) def _stoch_pt(d,df,fastk_period=14,slowk_period=3,slowd_period=3,**_): r=_pta.stoch(df["high"],df["low"],df["close"],k=fastk_period,d=slowd_period) return _first_col(r,"STOCHk_") if r is not None else _empty() def _stoch_ta(d,df,fastk_period=14,**_): from ta.momentum import StochasticOscillator; return _strip_nan(StochasticOscillator(df["high"],df["low"],df["close"],window=fastk_period).stoch().values) def _stoch_tu(d,df,fastk_period=14,slowk_period=3,slowd_period=3,**_): k,dd=_tl.stoch(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),pct_k_period=fastk_period,pct_k_slowing_period=slowk_period,pct_d_period=slowd_period); return _strip_nan(k) def _stoch_fi(d,df,fastk_period=14,**_): return _strip_nan(_fi.STOCH(df,fastk_period).values) def _cci_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.CCI(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _cci_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.CCI(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _cci_pt(d,df,timeperiod=14,**_): return _strip_nan(_pta.cci(df["high"],df["low"],df["close"],length=timeperiod).values) def _cci_ta(d,df,timeperiod=14,**_): from ta.trend import CCIIndicator; return _strip_nan(CCIIndicator(df["high"],df["low"],df["close"],window=timeperiod).cci().values) def _cci_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.cci(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),period=timeperiod)) def _cci_fi(d,df,timeperiod=14,**_): return _strip_nan(_fi.CCI(df,timeperiod).values) def _willr_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.WILLR(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _willr_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.WILLR(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _willr_pt(d,df,timeperiod=14,**_): return _strip_nan(_pta.willr(df["high"],df["low"],df["close"],length=timeperiod).values) def _willr_ta(d,df,timeperiod=14,**_): from ta.momentum import WilliamsRIndicator; return _strip_nan(WilliamsRIndicator(df["high"],df["low"],df["close"],lbp=timeperiod).williams_r().values) def _willr_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.willr(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),period=timeperiod)) def _willr_fi(d,df,timeperiod=14,**_): return _strip_nan(_fi.WILLIAMS(df,timeperiod).values) def _aroon_ft(d,df,timeperiod=14,**_): import ferro_ta; dn,up=ferro_ta.AROON(d["high"],d["low"],timeperiod=timeperiod); return _strip_nan(up) def _aroon_tl(d,df,timeperiod=14,**_): dn,up=_talib.AROON(d["high"],d["low"],timeperiod=timeperiod); return _strip_nan(up) def _aroon_pt(d,df,timeperiod=14,**_): r=_pta.aroon(df["high"],df["low"],length=timeperiod); return _first_col(r,"AROONU_") if r is not None else _empty() def _aroon_ta(d,df,timeperiod=14,**_): from ta.trend import AroonIndicator; return _strip_nan(AroonIndicator(df["high"],df["low"],window=timeperiod).aroon_up().values) def _aroon_tu(d,df,timeperiod=14,**_): dn,up=_tl.aroon(_c64(d["high"]),_c64(d["low"]),period=timeperiod); return _strip_nan(up) def _aroon_fi(d,df,**_): return _empty() _aroon_fi._stub = True def _aroonosc_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.AROONOSC(d["high"],d["low"],timeperiod=timeperiod)) def _aroonosc_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.AROONOSC(d["high"],d["low"],timeperiod=timeperiod)) def _aroonosc_pt(d,df,**_): return _empty() _aroonosc_pt._stub = True def _aroonosc_ta(d,df,**_): return _empty() _aroonosc_ta._stub = True def _aroonosc_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.aroonosc(_c64(d["high"]),_c64(d["low"]),period=timeperiod)) def _aroonosc_fi(d,df,**_): return _empty() _aroonosc_fi._stub = True def _adx_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.ADX(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _adx_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.ADX(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _adx_pt(d,df,timeperiod=14,**_): r=_pta.adx(df["high"],df["low"],df["close"],length=timeperiod); return _first_col(r,"ADX_") def _adx_ta(d,df,timeperiod=14,**_): from ta.trend import ADXIndicator; return _strip_nan(ADXIndicator(df["high"],df["low"],df["close"],window=timeperiod).adx().values) def _adx_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.adx(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),period=timeperiod)) def _adx_fi(d,df,**_): return _empty() _adx_fi._stub = True def _mom_ft(d,df,timeperiod=10,**_): import ferro_ta; return _strip_nan(ferro_ta.MOM(d["close"],timeperiod=timeperiod)) def _mom_tl(d,df,timeperiod=10,**_): return _strip_nan(_talib.MOM(d["close"],timeperiod=timeperiod)) def _mom_pt(d,df,timeperiod=10,**_): return _strip_nan(_pta.mom(df["close"],length=timeperiod).values) def _mom_ta(d,df,**_): return _empty() _mom_ta._stub = True def _mom_tu(d,df,timeperiod=10,**_): return _strip_nan(_tl.mom(_c64(d["close"]),period=timeperiod)) def _mom_fi(d,df,timeperiod=10,**_): return _strip_nan(_fi.MOM(df,timeperiod).values) def _roc_ft(d,df,timeperiod=10,**_): import ferro_ta; return _strip_nan(ferro_ta.ROC(d["close"],timeperiod=timeperiod)) def _roc_tl(d,df,timeperiod=10,**_): return _strip_nan(_talib.ROC(d["close"],timeperiod=timeperiod)) def _roc_pt(d,df,timeperiod=10,**_): return _strip_nan(_pta.roc(df["close"],length=timeperiod).values) def _roc_ta(d,df,timeperiod=10,**_): from ta.momentum import ROCIndicator; return _strip_nan(ROCIndicator(df["close"],window=timeperiod).roc().values) def _roc_tu(d,df,timeperiod=10,**_): return _strip_nan(_tl.roc(_c64(d["close"]),period=timeperiod) * 100.0) def _roc_fi(d,df,timeperiod=10,**_): return _strip_nan(_fi.ROC(df,timeperiod).values) def _cmo_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.CMO(d["close"],timeperiod=timeperiod)) def _cmo_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.CMO(d["close"],timeperiod=timeperiod)) def _cmo_pt(d,df,timeperiod=14,**_): return _strip_nan(_pta.cmo(df["close"],length=timeperiod).values) def _cmo_ta(d,df,**_): return _empty() _cmo_ta._stub = True def _cmo_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.cmo(_c64(d["close"]),period=timeperiod)) def _cmo_fi(d,df,timeperiod=14,**_): return _strip_nan(_fi.CMO(df,timeperiod).values) def _ppo_ft(d,df,fastperiod=12,slowperiod=26,**_): import ferro_ta; ppo,sig,hist=ferro_ta.PPO(d["close"],fastperiod=fastperiod,slowperiod=slowperiod); return _strip_nan(ppo) def _ppo_tl(d,df,fastperiod=12,slowperiod=26,**_): return _strip_nan(_talib.PPO(d["close"],fastperiod=fastperiod,slowperiod=slowperiod)) def _ppo_pt(d,df,fastperiod=12,slowperiod=26,**_): r=_pta.ppo(df["close"],fast=fastperiod,slow=slowperiod) return _strip_nan(r.iloc[:,0].values) if r is not None else _empty() def _ppo_ta(d,df,**_): return _empty() _ppo_ta._stub = True def _ppo_tu(d,df,fastperiod=12,slowperiod=26,**_): return _strip_nan(_tl.ppo(_c64(d["close"]),short_period=fastperiod,long_period=slowperiod)) def _ppo_fi(d,df,fastperiod=12,slowperiod=26,**_): return _strip_nan(_fi.PPO(df,fastperiod,slowperiod).values) def _trix_ft(d,df,timeperiod=18,**_): import ferro_ta; return _strip_nan(ferro_ta.TRIX(d["close"],timeperiod=timeperiod)) def _trix_tl(d,df,timeperiod=18,**_): return _strip_nan(_talib.TRIX(d["close"],timeperiod=timeperiod)) def _trix_pt(d,df,timeperiod=18,**_): r=_pta.trix(df["close"],length=timeperiod) return _strip_nan(r.iloc[:,0].values) if r is not None else _empty() def _trix_ta(d,df,timeperiod=18,**_): from ta.trend import TRIXIndicator; return _strip_nan(TRIXIndicator(df["close"],window=timeperiod).trix().values) def _trix_tu(d,df,timeperiod=18,**_): return _strip_nan(_tl.trix(_c64(d["close"]),period=timeperiod)) def _trix_fi(d,df,timeperiod=18,**_): return _strip_nan(_fi.TRIX(df,timeperiod).values) def _tsf_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.TSF(d["close"],timeperiod=timeperiod)) def _tsf_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.TSF(d["close"],timeperiod=timeperiod)) def _tsf_pt(d,df,**_): return _empty() _tsf_pt._stub = True def _tsf_ta(d,df,**_): return _empty() _tsf_ta._stub = True def _tsf_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.tsf(_c64(d["close"]),period=timeperiod)) def _tsf_fi(d,df,**_): return _empty() _tsf_fi._stub = True def _ultosc_ft(d,df,timeperiod1=7,timeperiod2=14,timeperiod3=28,**_): import ferro_ta; return _strip_nan(ferro_ta.ULTOSC(d["high"],d["low"],d["close"],timeperiod1=timeperiod1,timeperiod2=timeperiod2,timeperiod3=timeperiod3)) def _ultosc_tl(d,df,timeperiod1=7,timeperiod2=14,timeperiod3=28,**_): return _strip_nan(_talib.ULTOSC(d["high"],d["low"],d["close"],timeperiod1=timeperiod1,timeperiod2=timeperiod2,timeperiod3=timeperiod3)) def _ultosc_pt(d,df,**_): return _empty() _ultosc_pt._stub = True def _ultosc_ta(d,df,timeperiod1=7,timeperiod2=14,timeperiod3=28,**_): from ta.momentum import UltimateOscillator return _strip_nan(UltimateOscillator(df["high"],df["low"],df["close"],window1=timeperiod1,window2=timeperiod2,window3=timeperiod3).ultimate_oscillator().values) def _ultosc_tu(d,df,timeperiod1=7,timeperiod2=14,timeperiod3=28,**_): return _strip_nan(_tl.ultosc(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),short_period=timeperiod1,medium_period=timeperiod2,long_period=timeperiod3)) def _ultosc_fi(d,df,**_): return _empty() _ultosc_fi._stub = True def _bop_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.BOP(d["open"],d["high"],d["low"],d["close"])) def _bop_tl(d,df,**_): return _strip_nan(_talib.BOP(d["open"],d["high"],d["low"],d["close"])) def _bop_pt(d,df,**_): r=_pta.bop(df["open"],df["high"],df["low"],df["close"]); return _strip_nan(r.values) if r is not None else _empty() def _bop_ta(d,df,**_): return _empty() _bop_ta._stub = True def _bop_tu(d,df,**_): return _strip_nan(_tl.bop(_c64(d["open"]),_c64(d["high"]),_c64(d["low"]),_c64(d["close"]))) def _bop_fi(d,df,**_): return _empty() _bop_fi._stub = True def _plusdi_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.PLUS_DI(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _plusdi_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.PLUS_DI(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _plusdi_pt(d,df,timeperiod=14,**_): r=_pta.adx(df["high"],df["low"],df["close"],length=timeperiod); return _first_col(r,"DMP_") if r is not None else _empty() def _plusdi_ta(d,df,**_): return _empty() _plusdi_ta._stub = True def _plusdi_tu(d,df,timeperiod=14,**_): pdi,mdi=_tl.di(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),period=timeperiod); return _strip_nan(pdi) def _plusdi_fi(d,df,**_): return _empty() _plusdi_fi._stub = True def _minusdi_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.MINUS_DI(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _minusdi_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.MINUS_DI(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _minusdi_pt(d,df,**_): return _empty() _minusdi_pt._stub = True def _minusdi_ta(d,df,**_): return _empty() _minusdi_ta._stub = True def _minusdi_tu(d,df,timeperiod=14,**_): pdi,mdi=_tl.di(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),period=timeperiod); return _strip_nan(mdi) def _minusdi_fi(d,df,**_): return _empty() _minusdi_fi._stub = True # ============================================================ # VOLATILITY # ============================================================ def _bb_ft(d,df,timeperiod=20,nbdevup=2.0,nbdevdn=2.0,**_): import ferro_ta; u,m,l=ferro_ta.BBANDS(d["close"],timeperiod=timeperiod,nbdevup=nbdevup,nbdevdn=nbdevdn); return _strip_nan(u) def _bb_tl(d,df,timeperiod=20,nbdevup=2.0,nbdevdn=2.0,**_): u,m,l=_talib.BBANDS(d["close"],timeperiod=timeperiod,nbdevup=nbdevup,nbdevdn=nbdevdn); return _strip_nan(u) def _bb_pt(d,df,timeperiod=20,nbdevup=2.0,**_): r=_pta.bbands(df["close"],length=timeperiod,std=nbdevup); return _first_col(r,"BBU_") def _bb_ta(d,df,timeperiod=20,nbdevup=2.0,**_): from ta.volatility import BollingerBands; return _strip_nan(BollingerBands(df["close"],window=timeperiod,window_dev=nbdevup).bollinger_hband().values) def _bb_tu(d,df,timeperiod=20,nbdevup=2.0,**_): lo,mi,up=_tl.bbands(_c64(d["close"]),period=timeperiod,stddev=nbdevup); return _strip_nan(up) def _bb_fi(d,df,timeperiod=20,**_): return _strip_nan(_fi.BBANDS(df,timeperiod)["BB_UPPER"].values) def _atr_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.ATR(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _atr_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.ATR(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _atr_pt(d,df,timeperiod=14,**_): return _strip_nan(_pta.atr(df["high"],df["low"],df["close"],length=timeperiod).values) def _atr_ta(d,df,timeperiod=14,**_): from ta.volatility import AverageTrueRange; return _strip_nan(AverageTrueRange(df["high"],df["low"],df["close"],window=timeperiod).average_true_range().values) def _atr_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.atr(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),period=timeperiod)) def _atr_fi(d,df,timeperiod=14,**_): return _strip_nan(_fi.ATR(df,timeperiod).values) def _natr_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.NATR(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _natr_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.NATR(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _natr_pt(d,df,timeperiod=14,**_): return _strip_nan(_pta.natr(df["high"],df["low"],df["close"],length=timeperiod).values) def _natr_ta(d,df,**_): return _empty() _natr_ta._stub = True def _natr_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.natr(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),period=timeperiod)) def _natr_fi(d,df,**_): return _empty() _natr_fi._stub = True def _trange_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.TRANGE(d["high"],d["low"],d["close"])) def _trange_tl(d,df,**_): return _strip_nan(_talib.TRANGE(d["high"],d["low"],d["close"])) def _trange_pt(d,df,**_): r=_pta.true_range(df["high"],df["low"],df["close"]); return _strip_nan(r.values) if r is not None else _empty() def _trange_ta(d,df,**_): return _empty() _trange_ta._stub = True def _trange_tu(d,df,**_): return _strip_nan(_tl.tr(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]))) def _trange_fi(d,df,**_): return _strip_nan(_fi.TR(df).values) def _stddev_ft(d,df,timeperiod=20,**_): import ferro_ta; return _strip_nan(ferro_ta.STDDEV(d["close"],timeperiod=timeperiod)) def _stddev_tl(d,df,timeperiod=20,**_): return _strip_nan(_talib.STDDEV(d["close"],timeperiod=timeperiod)) def _stddev_pt(d,df,timeperiod=20,**_): r=_pta.stdev(df["close"],length=timeperiod); return _strip_nan(r.values) if r is not None else _empty() def _stddev_ta(d,df,**_): return _empty() _stddev_ta._stub = True def _stddev_tu(d,df,timeperiod=20,**_): return _strip_nan(_tl.stddev(_c64(d["close"]),period=timeperiod)) def _stddev_fi(d,df,timeperiod=20,**_): return _strip_nan(_fi.MSD(df,timeperiod).values) def _var_ft(d,df,timeperiod=20,**_): import ferro_ta; return _strip_nan(ferro_ta.VAR(d["close"],timeperiod=timeperiod)) def _var_tl(d,df,timeperiod=20,**_): return _strip_nan(_talib.VAR(d["close"],timeperiod=timeperiod)) def _var_pt(d,df,timeperiod=20,**_): r=_pta.variance(df["close"],length=timeperiod); return _strip_nan(r.values) if r is not None else _empty() def _var_ta(d,df,**_): return _empty() _var_ta._stub = True def _var_tu(d,df,timeperiod=20,**_): return _strip_nan(_tl.var(_c64(d["close"]),period=timeperiod)) def _var_fi(d,df,**_): return _empty() _var_fi._stub = True def _sar_ft(d,df,acceleration=0.02,maximum=0.2,**_): import ferro_ta; return _strip_nan(ferro_ta.SAR(d["high"],d["low"],acceleration=acceleration,maximum=maximum)) def _sar_tl(d,df,acceleration=0.02,maximum=0.2,**_): return _strip_nan(_talib.SAR(d["high"],d["low"],acceleration=acceleration,maximum=maximum)) def _sar_pt(d,df,**_): return _empty() _sar_pt._stub = True def _sar_ta(d,df,**_): return _empty() _sar_ta._stub = True def _sar_tu(d,df,acceleration=0.02,maximum=0.2,**_): return _strip_nan(_tl.psar(_c64(d["high"]),_c64(d["low"]),acceleration_factor_step=acceleration,acceleration_factor_maximum=maximum)) def _sar_fi(d,df,**_): return _empty() _sar_fi._stub = True def _kc_ft(d,df,timeperiod=20,**_): import ferro_ta; u,m,l=ferro_ta.KELTNER_CHANNELS(d["high"],d["low"],d["close"],timeperiod=timeperiod); return _strip_nan(u) def _kc_tl(d,df,**_): return _empty() _kc_tl._stub = True def _kc_pt(d,df,timeperiod=20,**_): r=_pta.kc(df["high"],df["low"],df["close"],length=timeperiod) if r is None: return _empty() col=next((c for c in r.columns if "UCe" in c or "UB" in c or c.endswith("U")),None) return _strip_nan(r[col].values) if col else _first_col(r,"KC") def _kc_ta(d,df,timeperiod=20,**_): from ta.volatility import KeltnerChannel; return _strip_nan(KeltnerChannel(df["high"],df["low"],df["close"],window=timeperiod).keltner_channel_hband().values) def _kc_tu(d,df,**_): return _empty() _kc_tu._stub = True def _kc_fi(d,df,**_): return _empty() _kc_fi._stub = True def _donchian_ft(d,df,timeperiod=20,**_): import ferro_ta; u,m,l=ferro_ta.DONCHIAN(d["high"],d["low"],timeperiod=timeperiod); return _strip_nan(u) def _donchian_tl(d,df,**_): return _empty() _donchian_tl._stub = True def _donchian_pt(d,df,timeperiod=20,**_): r=_pta.donchian(df["high"],df["low"],lower_length=timeperiod,upper_length=timeperiod) return _first_col(r,"DCU_") if r is not None else _empty() def _donchian_ta(d,df,timeperiod=20,**_): from ta.volatility import DonchianChannel; return _strip_nan(DonchianChannel(df["high"],df["low"],df["close"],window=timeperiod).donchian_channel_hband().values) def _donchian_tu(d,df,**_): return _empty() _donchian_tu._stub = True def _donchian_fi(d,df,**_): return _empty() _donchian_fi._stub = True def _supertrend_ft(d,df,timeperiod=7,**_): import ferro_ta; st,dir_=ferro_ta.SUPERTREND(d["high"],d["low"],d["close"],timeperiod=timeperiod); return _strip_nan(st) def _supertrend_tl(d,df,**_): return _empty() _supertrend_tl._stub = True def _supertrend_pt(d,df,timeperiod=7,**_): r=_pta.supertrend(df["high"],df["low"],df["close"],length=timeperiod) return _first_col(r,"SUPERT_") if r is not None else _empty() def _supertrend_ta(d,df,**_): return _empty() _supertrend_ta._stub = True def _supertrend_tu(d,df,**_): return _empty() _supertrend_tu._stub = True def _supertrend_fi(d,df,**_): return _empty() _supertrend_fi._stub = True def _chop_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.CHOPPINESS_INDEX(d["high"],d["low"],d["close"],timeperiod=timeperiod)) def _chop_tl(d,df,**_): return _empty() _chop_tl._stub = True def _chop_pt(d,df,timeperiod=14,**_): r=_pta.chop(df["high"],df["low"],df["close"],length=timeperiod); return _strip_nan(r.values) if r is not None else _empty() def _chop_ta(d,df,**_): return _empty() _chop_ta._stub = True def _chop_tu(d,df,**_): return _empty() _chop_tu._stub = True def _chop_fi(d,df,**_): return _empty() _chop_fi._stub = True # ============================================================ # VOLUME # ============================================================ def _obv_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.OBV(d["close"],d["volume"])) def _obv_tl(d,df,**_): return _strip_nan(_talib.OBV(d["close"],d["volume"])) def _obv_pt(d,df,**_): return _strip_nan(_pta.obv(df["close"],df["volume"]).values) def _obv_ta(d,df,**_): from ta.volume import OnBalanceVolumeIndicator; return _strip_nan(OnBalanceVolumeIndicator(df["close"],df["volume"]).on_balance_volume().values) def _obv_tu(d,df,**_): return _strip_nan(_tl.obv(_c64(d["close"]),_c64(d["volume"]))) def _obv_fi(d,df,**_): return _strip_nan(_fi.OBV(df).values) def _ad_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.AD(d["high"],d["low"],d["close"],d["volume"])) def _ad_tl(d,df,**_): return _strip_nan(_talib.AD(d["high"],d["low"],d["close"],d["volume"])) def _ad_pt(d,df,**_): return _strip_nan(_pta.ad(df["high"],df["low"],df["close"],df["volume"]).values) def _ad_ta(d,df,**_): from ta.volume import AccDistIndexIndicator; return _strip_nan(AccDistIndexIndicator(df["high"],df["low"],df["close"],df["volume"]).acc_dist_index().values) def _ad_tu(d,df,**_): return _strip_nan(_tl.ad(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),_c64(d["volume"]))) def _ad_fi(d,df,**_): return _empty() _ad_fi._stub = True def _adosc_ft(d,df,fastperiod=3,slowperiod=10,**_): import ferro_ta; return _strip_nan(ferro_ta.ADOSC(d["high"],d["low"],d["close"],d["volume"],fastperiod=fastperiod,slowperiod=slowperiod)) def _adosc_tl(d,df,fastperiod=3,slowperiod=10,**_): return _strip_nan(_talib.ADOSC(d["high"],d["low"],d["close"],d["volume"],fastperiod=fastperiod,slowperiod=slowperiod)) def _adosc_pt(d,df,fastperiod=3,slowperiod=10,**_): return _strip_nan(_pta.adosc(df["high"],df["low"],df["close"],df["volume"],fast=fastperiod,slow=slowperiod).values) def _adosc_ta(d,df,**_): return _empty() _adosc_ta._stub = True def _adosc_tu(d,df,fastperiod=3,slowperiod=10,**_): return _strip_nan(_tl.adosc(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),_c64(d["volume"]),short_period=fastperiod,long_period=slowperiod)) def _adosc_fi(d,df,**_): return _empty() _adosc_fi._stub = True def _mfi_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.MFI(d["high"],d["low"],d["close"],d["volume"],timeperiod=timeperiod)) def _mfi_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.MFI(d["high"],d["low"],d["close"],d["volume"],timeperiod=timeperiod)) def _mfi_pt(d,df,timeperiod=14,**_): return _strip_nan(_pta.mfi(df["high"],df["low"],df["close"],df["volume"],length=timeperiod).values) def _mfi_ta(d,df,timeperiod=14,**_): from ta.volume import MFIIndicator; return _strip_nan(MFIIndicator(df["high"],df["low"],df["close"],df["volume"],window=timeperiod).money_flow_index().values) def _mfi_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.mfi(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]),_c64(d["volume"]),period=timeperiod)) def _mfi_fi(d,df,timeperiod=14,**_): return _strip_nan(_fi.MFI(df,timeperiod).values) def _vwap_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.VWAP(d["high"],d["low"],d["close"],d["volume"])) def _vwap_tl(d,df,**_): return _empty() _vwap_tl._stub = True def _vwap_pt(d,df,**_): r=_pta.vwap(df["high"],df["low"],df["close"],df["volume"]); return _strip_nan(r.values) if r is not None else _empty() def _vwap_ta(d,df,**_): return _empty() _vwap_ta._stub = True def _vwap_tu(d,df,**_): return _empty() _vwap_tu._stub = True def _vwap_fi(d,df,**_): return _strip_nan(_fi.VWAP(df).values) # ============================================================ # PRICE TRANSFORM # ============================================================ def _avgprice_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.AVGPRICE(d["open"],d["high"],d["low"],d["close"])) def _avgprice_tl(d,df,**_): return _strip_nan(_talib.AVGPRICE(d["open"],d["high"],d["low"],d["close"])) def _avgprice_pt(d,df,**_): return _empty() _avgprice_pt._stub = True def _avgprice_ta(d,df,**_): return _empty() _avgprice_ta._stub = True def _avgprice_tu(d,df,**_): return _strip_nan(_tl.avgprice(_c64(d["open"]),_c64(d["high"]),_c64(d["low"]),_c64(d["close"]))) def _avgprice_fi(d,df,**_): return _empty() _avgprice_fi._stub = True def _medprice_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.MEDPRICE(d["high"],d["low"])) def _medprice_tl(d,df,**_): return _strip_nan(_talib.MEDPRICE(d["high"],d["low"])) def _medprice_pt(d,df,**_): return _empty() _medprice_pt._stub = True def _medprice_ta(d,df,**_): return _empty() _medprice_ta._stub = True def _medprice_tu(d,df,**_): return _strip_nan(_tl.medprice(_c64(d["high"]),_c64(d["low"]))) def _medprice_fi(d,df,**_): return _empty() _medprice_fi._stub = True def _typprice_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.TYPPRICE(d["high"],d["low"],d["close"])) def _typprice_tl(d,df,**_): return _strip_nan(_talib.TYPPRICE(d["high"],d["low"],d["close"])) def _typprice_pt(d,df,**_): return _empty() _typprice_pt._stub = True def _typprice_ta(d,df,**_): return _empty() _typprice_ta._stub = True def _typprice_tu(d,df,**_): return _strip_nan(_tl.typprice(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]))) def _typprice_fi(d,df,**_): return _empty() _typprice_fi._stub = True def _wclprice_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.WCLPRICE(d["high"],d["low"],d["close"])) def _wclprice_tl(d,df,**_): return _strip_nan(_talib.WCLPRICE(d["high"],d["low"],d["close"])) def _wclprice_pt(d,df,**_): return _empty() _wclprice_pt._stub = True def _wclprice_ta(d,df,**_): return _empty() _wclprice_ta._stub = True def _wclprice_tu(d,df,**_): return _strip_nan(_tl.wcprice(_c64(d["high"]),_c64(d["low"]),_c64(d["close"]))) def _wclprice_fi(d,df,**_): return _empty() _wclprice_fi._stub = True # ============================================================ # MATH # ============================================================ def _sqrt_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.SQRT(d["close"])) def _sqrt_tl(d,df,**_): return _strip_nan(_talib.SQRT(d["close"])) def _sqrt_pt(d,df,**_): return _empty() _sqrt_pt._stub = True def _sqrt_ta(d,df,**_): return _empty() _sqrt_ta._stub = True def _sqrt_tu(d,df,**_): return _strip_nan(_tl.sqrt(_c64(d["close"]))) def _sqrt_fi(d,df,**_): return _empty() _sqrt_fi._stub = True def _log10_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.LOG10(d["close"])) def _log10_tl(d,df,**_): return _strip_nan(_talib.LOG10(d["close"])) def _log10_pt(d,df,**_): return _empty() _log10_pt._stub = True def _log10_ta(d,df,**_): return _empty() _log10_ta._stub = True def _log10_tu(d,df,**_): return _strip_nan(_tl.log10(_c64(d["close"]))) def _log10_fi(d,df,**_): return _empty() _log10_fi._stub = True def _add_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.ADD(d["high"],d["low"])) def _add_tl(d,df,**_): return _strip_nan(_talib.ADD(d["high"],d["low"])) def _add_pt(d,df,**_): return _empty() _add_pt._stub = True def _add_ta(d,df,**_): return _empty() _add_ta._stub = True def _add_tu(d,df,**_): return _strip_nan(_tl.add(_c64(d["high"]),_c64(d["low"]))) def _add_fi(d,df,**_): return _empty() _add_fi._stub = True # ============================================================ # STATISTICS # ============================================================ def _linearreg_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.LINEARREG(d["close"],timeperiod=timeperiod)) def _linearreg_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.LINEARREG(d["close"],timeperiod=timeperiod)) def _linearreg_pt(d,df,**_): return _empty() _linearreg_pt._stub = True def _linearreg_ta(d,df,**_): return _empty() _linearreg_ta._stub = True def _linearreg_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.linreg(_c64(d["close"]),period=timeperiod)) def _linearreg_fi(d,df,**_): return _empty() _linearreg_fi._stub = True def _linreg_slope_ft(d,df,timeperiod=14,**_): import ferro_ta; return _strip_nan(ferro_ta.LINEARREG_SLOPE(d["close"],timeperiod=timeperiod)) def _linreg_slope_tl(d,df,timeperiod=14,**_): return _strip_nan(_talib.LINEARREG_SLOPE(d["close"],timeperiod=timeperiod)) def _linreg_slope_pt(d,df,**_): return _empty() _linreg_slope_pt._stub = True def _linreg_slope_ta(d,df,**_): return _empty() _linreg_slope_ta._stub = True def _linreg_slope_tu(d,df,timeperiod=14,**_): return _strip_nan(_tl.linregslope(_c64(d["close"]),period=timeperiod)) def _linreg_slope_fi(d,df,**_): return _empty() _linreg_slope_fi._stub = True def _correl_ft(d,df,timeperiod=30,**_): import ferro_ta; return _strip_nan(ferro_ta.CORREL(d["high"],d["low"],timeperiod=timeperiod)) def _correl_tl(d,df,timeperiod=30,**_): return _strip_nan(_talib.CORREL(d["high"],d["low"],timeperiod=timeperiod)) def _correl_pt(d,df,**_): return _empty() _correl_pt._stub = True def _correl_ta(d,df,**_): return _empty() _correl_ta._stub = True def _correl_tu(d,df,**_): return _empty() _correl_tu._stub = True def _correl_fi(d,df,**_): return _empty() _correl_fi._stub = True def _beta_ft(d,df,timeperiod=5,**_): import ferro_ta; return _strip_nan(ferro_ta.BETA(d["high"],d["low"],timeperiod=timeperiod)) def _beta_tl(d,df,timeperiod=5,**_): return _strip_nan(_talib.BETA(d["high"],d["low"],timeperiod=timeperiod)) def _beta_pt(d,df,**_): return _empty() _beta_pt._stub = True def _beta_ta(d,df,**_): return _empty() _beta_ta._stub = True def _beta_tu(d,df,**_): return _empty() _beta_tu._stub = True def _beta_fi(d,df,**_): return _empty() _beta_fi._stub = True # ============================================================ # CYCLE # ============================================================ def _ht_dcperiod_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.HT_DCPERIOD(d["close"])) def _ht_dcperiod_tl(d,df,**_): return _strip_nan(_talib.HT_DCPERIOD(d["close"])) def _ht_dcperiod_pt(d,df,**_): return _empty() _ht_dcperiod_pt._stub = True def _ht_dcperiod_ta(d,df,**_): return _empty() _ht_dcperiod_ta._stub = True def _ht_dcperiod_tu(d,df,**_): return _empty() _ht_dcperiod_tu._stub = True def _ht_dcperiod_fi(d,df,**_): return _empty() _ht_dcperiod_fi._stub = True def _ht_trendmode_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.HT_TRENDMODE(d["close"]).astype(float)) def _ht_trendmode_tl(d,df,**_): return _strip_nan(_talib.HT_TRENDMODE(d["close"]).astype(float)) def _ht_trendmode_pt(d,df,**_): return _empty() _ht_trendmode_pt._stub = True def _ht_trendmode_ta(d,df,**_): return _empty() _ht_trendmode_ta._stub = True def _ht_trendmode_tu(d,df,**_): return _empty() _ht_trendmode_tu._stub = True def _ht_trendmode_fi(d,df,**_): return _empty() _ht_trendmode_fi._stub = True # ============================================================ # CANDLESTICK PATTERNS # ============================================================ def _cdlengulfing_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.CDLENGULFING(d["open"],d["high"],d["low"],d["close"]).astype(float)) def _cdlengulfing_tl(d,df,**_): return _strip_nan(_talib.CDLENGULFING(d["open"],d["high"],d["low"],d["close"]).astype(float)) def _cdlengulfing_pt(d,df,**_): return _empty() _cdlengulfing_pt._stub = True def _cdlengulfing_ta(d,df,**_): return _empty() _cdlengulfing_ta._stub = True def _cdlengulfing_tu(d,df,**_): return _empty() _cdlengulfing_tu._stub = True def _cdlengulfing_fi(d,df,**_): return _empty() _cdlengulfing_fi._stub = True def _cdldoji_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.CDLDOJI(d["open"],d["high"],d["low"],d["close"]).astype(float)) def _cdldoji_tl(d,df,**_): return _strip_nan(_talib.CDLDOJI(d["open"],d["high"],d["low"],d["close"]).astype(float)) def _cdldoji_pt(d,df,**_): return _empty() _cdldoji_pt._stub = True def _cdldoji_ta(d,df,**_): return _empty() _cdldoji_ta._stub = True def _cdldoji_tu(d,df,**_): return _empty() _cdldoji_tu._stub = True def _cdldoji_fi(d,df,**_): return _empty() _cdldoji_fi._stub = True def _cdlhammer_ft(d,df,**_): import ferro_ta; return _strip_nan(ferro_ta.CDLHAMMER(d["open"],d["high"],d["low"],d["close"]).astype(float)) def _cdlhammer_tl(d,df,**_): return _strip_nan(_talib.CDLHAMMER(d["open"],d["high"],d["low"],d["close"]).astype(float)) def _cdlhammer_pt(d,df,**_): return _empty() _cdlhammer_pt._stub = True def _cdlhammer_ta(d,df,**_): return _empty() _cdlhammer_ta._stub = True def _cdlhammer_tu(d,df,**_): return _empty() _cdlhammer_tu._stub = True def _cdlhammer_fi(d,df,**_): return _empty() _cdlhammer_fi._stub = True # ============================================================ # REGISTRY BUILD # ============================================================ REGISTRY: dict[tuple[str,Any], Any] = {} def _reg(ind, ft, tl, pt, ta_, tu, fi): """ Register wrappers for a given indicator across all libraries. Wrappers marked ._stub = True (no-op return _empty()) are not registered, so execute_indicator raises KeyError for unsupported (lib, ind). Speed benchmarks then skip those pairs and the table shows N/A. """ for lib, fn in [ ("ferro_ta", ft), ("talib", tl), ("pandas_ta",pt), ("ta", ta_), ("tulipy", tu), ("finta", fi), ]: if getattr(fn, "_stub", False): continue REGISTRY[(lib, ind)] = fn _reg("SMA",_sma_ft,_sma_tl,_sma_pt,_sma_ta,_sma_tu,_sma_fi) _reg("EMA",_ema_ft,_ema_tl,_ema_pt,_ema_ta,_ema_tu,_ema_fi) _reg("WMA",_wma_ft,_wma_tl,_wma_pt,_wma_ta,_wma_tu,_wma_fi) _reg("DEMA",_dema_ft,_dema_tl,_dema_pt,_dema_ta,_dema_tu,_dema_fi) _reg("TEMA",_tema_ft,_tema_tl,_tema_pt,_tema_ta,_tema_tu,_tema_fi) _reg("T3",_t3_ft,_t3_tl,_t3_pt,_t3_ta,_t3_tu,_t3_fi) _reg("TRIMA",_trima_ft,_trima_tl,_trima_pt,_trima_ta,_trima_tu,_trima_fi) _reg("KAMA",_kama_ft,_kama_tl,_kama_pt,_kama_ta,_kama_tu,_kama_fi) _reg("HULL_MA",_hma_ft,_hma_tl,_hma_pt,_hma_ta,_hma_tu,_hma_fi) _reg("VWMA",_vwma_ft,_vwma_tl,_vwma_pt,_vwma_ta,_vwma_tu,_vwma_fi) _reg("MIDPOINT",_midpoint_ft,_midpoint_tl,_midpoint_pt,_midpoint_ta,_midpoint_tu,_midpoint_fi) _reg("MIDPRICE",_midprice_ft,_midprice_tl,_midprice_pt,_midprice_ta,_midprice_tu,_midprice_fi) _reg("RSI",_rsi_ft,_rsi_tl,_rsi_pt,_rsi_ta,_rsi_tu,_rsi_fi) _reg("MACD",_macd_ft,_macd_tl,_macd_pt,_macd_ta,_macd_tu,_macd_fi) _reg("STOCH",_stoch_ft,_stoch_tl,_stoch_pt,_stoch_ta,_stoch_tu,_stoch_fi) _reg("CCI",_cci_ft,_cci_tl,_cci_pt,_cci_ta,_cci_tu,_cci_fi) _reg("WILLR",_willr_ft,_willr_tl,_willr_pt,_willr_ta,_willr_tu,_willr_fi) _reg("AROON",_aroon_ft,_aroon_tl,_aroon_pt,_aroon_ta,_aroon_tu,_aroon_fi) _reg("AROONOSC",_aroonosc_ft,_aroonosc_tl,_aroonosc_pt,_aroonosc_ta,_aroonosc_tu,_aroonosc_fi) _reg("ADX",_adx_ft,_adx_tl,_adx_pt,_adx_ta,_adx_tu,_adx_fi) _reg("MOM",_mom_ft,_mom_tl,_mom_pt,_mom_ta,_mom_tu,_mom_fi) _reg("ROC",_roc_ft,_roc_tl,_roc_pt,_roc_ta,_roc_tu,_roc_fi) _reg("CMO",_cmo_ft,_cmo_tl,_cmo_pt,_cmo_ta,_cmo_tu,_cmo_fi) _reg("PPO",_ppo_ft,_ppo_tl,_ppo_pt,_ppo_ta,_ppo_tu,_ppo_fi) _reg("TRIX",_trix_ft,_trix_tl,_trix_pt,_trix_ta,_trix_tu,_trix_fi) _reg("TSF",_tsf_ft,_tsf_tl,_tsf_pt,_tsf_ta,_tsf_tu,_tsf_fi) _reg("ULTOSC",_ultosc_ft,_ultosc_tl,_ultosc_pt,_ultosc_ta,_ultosc_tu,_ultosc_fi) _reg("BOP",_bop_ft,_bop_tl,_bop_pt,_bop_ta,_bop_tu,_bop_fi) _reg("PLUS_DI",_plusdi_ft,_plusdi_tl,_plusdi_pt,_plusdi_ta,_plusdi_tu,_plusdi_fi) _reg("MINUS_DI",_minusdi_ft,_minusdi_tl,_minusdi_pt,_minusdi_ta,_minusdi_tu,_minusdi_fi) _reg("BBANDS",_bb_ft,_bb_tl,_bb_pt,_bb_ta,_bb_tu,_bb_fi) _reg("ATR",_atr_ft,_atr_tl,_atr_pt,_atr_ta,_atr_tu,_atr_fi) _reg("NATR",_natr_ft,_natr_tl,_natr_pt,_natr_ta,_natr_tu,_natr_fi) _reg("TRANGE",_trange_ft,_trange_tl,_trange_pt,_trange_ta,_trange_tu,_trange_fi) _reg("STDDEV",_stddev_ft,_stddev_tl,_stddev_pt,_stddev_ta,_stddev_tu,_stddev_fi) _reg("VAR",_var_ft,_var_tl,_var_pt,_var_ta,_var_tu,_var_fi) _reg("SAR",_sar_ft,_sar_tl,_sar_pt,_sar_ta,_sar_tu,_sar_fi) _reg("KELTNER_CHANNELS",_kc_ft,_kc_tl,_kc_pt,_kc_ta,_kc_tu,_kc_fi) _reg("DONCHIAN",_donchian_ft,_donchian_tl,_donchian_pt,_donchian_ta,_donchian_tu,_donchian_fi) _reg("SUPERTREND",_supertrend_ft,_supertrend_tl,_supertrend_pt,_supertrend_ta,_supertrend_tu,_supertrend_fi) _reg("CHOPPINESS_INDEX",_chop_ft,_chop_tl,_chop_pt,_chop_ta,_chop_tu,_chop_fi) _reg("OBV",_obv_ft,_obv_tl,_obv_pt,_obv_ta,_obv_tu,_obv_fi) _reg("AD",_ad_ft,_ad_tl,_ad_pt,_ad_ta,_ad_tu,_ad_fi) _reg("ADOSC",_adosc_ft,_adosc_tl,_adosc_pt,_adosc_ta,_adosc_tu,_adosc_fi) _reg("MFI",_mfi_ft,_mfi_tl,_mfi_pt,_mfi_ta,_mfi_tu,_mfi_fi) _reg("VWAP",_vwap_ft,_vwap_tl,_vwap_pt,_vwap_ta,_vwap_tu,_vwap_fi) _reg("AVGPRICE",_avgprice_ft,_avgprice_tl,_avgprice_pt,_avgprice_ta,_avgprice_tu,_avgprice_fi) _reg("MEDPRICE",_medprice_ft,_medprice_tl,_medprice_pt,_medprice_ta,_medprice_tu,_medprice_fi) _reg("TYPPRICE",_typprice_ft,_typprice_tl,_typprice_pt,_typprice_ta,_typprice_tu,_typprice_fi) _reg("WCLPRICE",_wclprice_ft,_wclprice_tl,_wclprice_pt,_wclprice_ta,_wclprice_tu,_wclprice_fi) _reg("SQRT",_sqrt_ft,_sqrt_tl,_sqrt_pt,_sqrt_ta,_sqrt_tu,_sqrt_fi) _reg("LOG10",_log10_ft,_log10_tl,_log10_pt,_log10_ta,_log10_tu,_log10_fi) _reg("ADD",_add_ft,_add_tl,_add_pt,_add_ta,_add_tu,_add_fi) _reg("LINEARREG",_linearreg_ft,_linearreg_tl,_linearreg_pt,_linearreg_ta,_linearreg_tu,_linearreg_fi) _reg("LINEARREG_SLOPE",_linreg_slope_ft,_linreg_slope_tl,_linreg_slope_pt,_linreg_slope_ta,_linreg_slope_tu,_linreg_slope_fi) _reg("CORREL",_correl_ft,_correl_tl,_correl_pt,_correl_ta,_correl_tu,_correl_fi) _reg("BETA",_beta_ft,_beta_tl,_beta_pt,_beta_ta,_beta_tu,_beta_fi) _reg("HT_DCPERIOD",_ht_dcperiod_ft,_ht_dcperiod_tl,_ht_dcperiod_pt,_ht_dcperiod_ta,_ht_dcperiod_tu,_ht_dcperiod_fi) _reg("HT_TRENDMODE",_ht_trendmode_ft,_ht_trendmode_tl,_ht_trendmode_pt,_ht_trendmode_ta,_ht_trendmode_tu,_ht_trendmode_fi) _reg("CDLENGULFING",_cdlengulfing_ft,_cdlengulfing_tl,_cdlengulfing_pt,_cdlengulfing_ta,_cdlengulfing_tu,_cdlengulfing_fi) _reg("CDLDOJI",_cdldoji_ft,_cdldoji_tl,_cdldoji_pt,_cdldoji_ta,_cdldoji_tu,_cdldoji_fi) _reg("CDLHAMMER",_cdlhammer_ft,_cdlhammer_tl,_cdlhammer_pt,_cdlhammer_ta,_cdlhammer_tu,_cdlhammer_fi) # ============================================================ # METADATA # ============================================================ INDICATOR_DEFAULTS: dict[str, dict] = { "SMA":{"timeperiod":20},"EMA":{"timeperiod":20},"WMA":{"timeperiod":14}, "DEMA":{"timeperiod":20},"TEMA":{"timeperiod":20},"T3":{"timeperiod":5}, "TRIMA":{"timeperiod":20},"KAMA":{"timeperiod":10},"HULL_MA":{"timeperiod":16}, "VWMA":{"timeperiod":20},"MIDPOINT":{"timeperiod":14},"MIDPRICE":{"timeperiod":14}, "RSI":{"timeperiod":14}, "MACD":{"fastperiod":12,"slowperiod":26,"signalperiod":9}, "STOCH":{"fastk_period":14,"slowk_period":3,"slowd_period":3}, "CCI":{"timeperiod":14},"WILLR":{"timeperiod":14}, "AROON":{"timeperiod":14},"AROONOSC":{"timeperiod":14}, "ADX":{"timeperiod":14},"MOM":{"timeperiod":10},"ROC":{"timeperiod":10}, "CMO":{"timeperiod":14},"PPO":{"fastperiod":12,"slowperiod":26}, "TRIX":{"timeperiod":18},"TSF":{"timeperiod":14}, "ULTOSC":{"timeperiod1":7,"timeperiod2":14,"timeperiod3":28}, "BOP":{},"PLUS_DI":{"timeperiod":14},"MINUS_DI":{"timeperiod":14}, "BBANDS":{"timeperiod":20,"nbdevup":2.0,"nbdevdn":2.0}, "ATR":{"timeperiod":14},"NATR":{"timeperiod":14},"TRANGE":{}, "STDDEV":{"timeperiod":20},"VAR":{"timeperiod":20}, "SAR":{"acceleration":0.02,"maximum":0.2}, "KELTNER_CHANNELS":{"timeperiod":20},"DONCHIAN":{"timeperiod":20}, "SUPERTREND":{"timeperiod":7},"CHOPPINESS_INDEX":{"timeperiod":14}, "OBV":{},"AD":{},"ADOSC":{"fastperiod":3,"slowperiod":10}, "MFI":{"timeperiod":14},"VWAP":{}, "AVGPRICE":{},"MEDPRICE":{},"TYPPRICE":{},"WCLPRICE":{}, "SQRT":{},"LOG10":{},"ADD":{}, "LINEARREG":{"timeperiod":14},"LINEARREG_SLOPE":{"timeperiod":14}, "CORREL":{"timeperiod":30},"BETA":{"timeperiod":5}, "HT_DCPERIOD":{},"HT_TRENDMODE":{}, "CDLENGULFING":{},"CDLDOJI":{},"CDLHAMMER":{}, } INDICATOR_NAMES = list(INDICATOR_DEFAULTS.keys()) LIBRARY_NAMES = ["ferro_ta","talib","pandas_ta","ta","tulipy","finta"] INDICATOR_CATEGORIES: dict[str, list[str]] = { "Overlap": ["SMA","EMA","WMA","DEMA","TEMA","T3","TRIMA","KAMA","HULL_MA","VWMA","MIDPOINT","MIDPRICE"], "Momentum": ["RSI","MACD","STOCH","CCI","WILLR","AROON","AROONOSC","ADX","MOM","ROC","CMO","PPO","TRIX","TSF","ULTOSC","BOP","PLUS_DI","MINUS_DI"], "Volatility": ["BBANDS","ATR","NATR","TRANGE","STDDEV","VAR","SAR","KELTNER_CHANNELS","DONCHIAN","SUPERTREND","CHOPPINESS_INDEX"], "Volume": ["OBV","AD","ADOSC","MFI","VWAP"], "Price Transform": ["AVGPRICE","MEDPRICE","TYPPRICE","WCLPRICE"], "Math": ["SQRT","LOG10","ADD"], "Statistics": ["LINEARREG","LINEARREG_SLOPE","CORREL","BETA"], "Cycle": ["HT_DCPERIOD","HT_TRENDMODE"], "Pattern": ["CDLENGULFING","CDLDOJI","CDLHAMMER"], } # Cumulative: compare first-differences not absolute values CUMULATIVE_INDICATORS = {"OBV","AD","ADOSC"} # Binary output: use agreement rate not allclose BINARY_INDICATORS = {"CDLENGULFING","CDLDOJI","CDLHAMMER","HT_TRENDMODE"} def execute_indicator(library, indicator, data, df=None, **kwargs): """Run indicator from library on data dict, return 1-D float64 array.""" if library not in available_libraries(): raise KeyError(f"Library not available in this environment: {library!r}") key = (library, indicator) if key not in REGISTRY: raise KeyError(f"No wrapper for {key!r}") if df is None: from benchmarks.data_generator import get_pandas_ohlcv df = get_pandas_ohlcv(data) params = {**INDICATOR_DEFAULTS.get(indicator, {}), **kwargs} return REGISTRY[key](data, df, **params)