""" ferro_ta — A fast Technical Analysis library powered by Rust and PyO3. Drop-in alternative to TA-Lib with pre-compiled wheels for all platforms. Indicators are organized into sub-modules matching TA-Lib's category structure, and are also importable directly from this top-level package for convenience. Sub-packages ------------ * :mod:`ferro_ta.indicators` — All indicator functions (overlap, momentum, volume, volatility, statistic, cycle, pattern, price_transform, math_ops, extended) * :mod:`ferro_ta.core` — Core utilities (exceptions, config, logging, registry, raw) * :mod:`ferro_ta.data` — Data utilities (streaming, batch, chunked, resampling, aggregation, adapters) * :mod:`ferro_ta.analysis` — Analysis tools (portfolio, backtest, regime, cross_asset, attribution, signals, features, crypto, options, futures, derivatives payoff) * :mod:`ferro_ta.tools` — Developer tools (tools, viz, dashboard, alerts, dsl, pipeline, workflow, api_info, gpu) Sub-modules (also accessible via sub-packages above) ----------------------------------------------------- * :mod:`ferro_ta.indicators.overlap` — Overlap Studies (SMA, EMA, WMA, DEMA, TEMA, TRIMA, KAMA, T3, MACD, BBANDS, SAR, MA, MAVP, MAMA, SAREXT, MACDEXT, …) * :mod:`ferro_ta.indicators.momentum` — Momentum Indicators (RSI, STOCH, ADX, CCI, WILLR, AROON, MFI, …) * :mod:`ferro_ta.indicators.volume` — Volume Indicators (AD, ADOSC, OBV) * :mod:`ferro_ta.indicators.volatility` — Volatility Indicators (ATR, NATR, TRANGE) * :mod:`ferro_ta.indicators.statistic` — Statistic Functions (STDDEV, VAR, LINEARREG, BETA, CORREL, …) * :mod:`ferro_ta.indicators.price_transform` — Price Transformations (AVGPRICE, MEDPRICE, TYPPRICE, WCLPRICE) * :mod:`ferro_ta.indicators.pattern` — Pattern Recognition (CDLDOJI, CDLENGULFING, CDLHAMMER, …) * :mod:`ferro_ta.indicators.cycle` — Cycle Indicators (HT_TRENDLINE, HT_DCPERIOD, HT_DCPHASE, HT_PHASOR, HT_SINE, HT_TRENDMODE) * :mod:`ferro_ta.indicators.math_ops` — Math Operators/Transforms (ADD, SUB, MULT, DIV, SUM, MAX, MIN, ACOS, SIN, …) * :mod:`ferro_ta.indicators.extended` — Extended Indicators (VWAP, SUPERTREND, ICHIMOKU, DONCHIAN, PIVOT_POINTS, KELTNER_CHANNELS, HULL_MA, CHANDELIER_EXIT, VWMA, CHOPPINESS_INDEX) * :mod:`ferro_ta.data.streaming` — Streaming / Incremental API (bar-by-bar stateful classes for live trading) * :mod:`ferro_ta.data.batch` — Batch Execution API (run SMA/EMA/RSI on 2-D arrays of multiple series) * :mod:`ferro_ta.data.resampling` — OHLCV resampling and multi-timeframe API * :mod:`ferro_ta.data.aggregation` — Tick/trade aggregation pipeline * :mod:`ferro_ta.tools.dsl` — Strategy expression DSL * :mod:`ferro_ta.analysis.signals` — Signal composition and screening * :mod:`ferro_ta.analysis.portfolio` — Portfolio and multi-asset analytics * :mod:`ferro_ta.analysis.cross_asset` — Cross-asset and relative strength * :mod:`ferro_ta.analysis.features` — Feature matrix and ML readiness * :mod:`ferro_ta.analysis.options` — Options pricing, Greeks, IV, smile, and chain analytics * :mod:`ferro_ta.analysis.futures` — Futures basis, carry, roll, and curve analytics * :mod:`ferro_ta.tools.viz` — Charting and visualisation API * :mod:`ferro_ta.data.adapters` — Market data adapters Usage ----- >>> import numpy as np >>> from ferro_ta import SMA, EMA, RSI, MACD, BBANDS >>> close = np.array([10.0, 11.0, 12.0, 13.0, 14.0, 13.5, 12.5]) >>> SMA(close, timeperiod=3) array([ nan, nan, 11. , 12. , 13. , 13.5, 13.33...]) >>> # Or import from sub-packages: >>> from ferro_ta.indicators.overlap import SMA, BBANDS >>> from ferro_ta.indicators.momentum import RSI, ADX >>> from ferro_ta.indicators.volatility import ATR >>> from ferro_ta.indicators.cycle import HT_TRENDLINE, HT_DCPERIOD >>> # Backward-compat flat imports still work: >>> from ferro_ta.overlap import SMA # noqa: F401 (stub) """ from __future__ import annotations import re as _re import sys as _sys from importlib.metadata import PackageNotFoundError as _PackageNotFoundError from importlib.metadata import version as _dist_version from pathlib import Path as _Path try: import tomllib as _tomllib except ImportError: # pragma: no cover try: import tomli as _tomllib # type: ignore[no-redef] except ImportError: # pragma: no cover _tomllib = None # type: ignore[assignment] def _detect_version() -> str: try: return _dist_version("ferro-ta") except _PackageNotFoundError: pass if _tomllib is not None: pyproject_toml = _Path(__file__).resolve().parents[2] / "pyproject.toml" if pyproject_toml.is_file(): try: with pyproject_toml.open("rb") as handle: data = _tomllib.load(handle) return data.get("project", {}).get("version", "0+unknown") except Exception: pass pyproject_toml = _Path(__file__).resolve().parents[2] / "pyproject.toml" if pyproject_toml.is_file(): try: text = pyproject_toml.read_text(encoding="utf-8") match = _re.search(r'^version\s*=\s*"([^"]+)"', text, _re.MULTILINE) if match: return match.group(1) except Exception: pass return "0+unknown" __version__ = _detect_version() # --------------------------------------------------------------------------- # Exceptions — exported at the top level for convenient catching # --------------------------------------------------------------------------- from ferro_ta.core.exceptions import ( # noqa: F401 FerroTAError, FerroTaError, FerroTAInputError, FerroTAValueError, InsufficientDataError, InvalidInputError, InvalidPeriodError, LengthMismatchError, NumericConvergenceError, ) # --------------------------------------------------------------------------- # Cycle Indicators # --------------------------------------------------------------------------- from ferro_ta.indicators.cycle import ( # noqa: F401 HT_DCPERIOD, HT_DCPHASE, HT_PHASOR, HT_SINE, HT_TRENDLINE, HT_TRENDMODE, ) # --------------------------------------------------------------------------- # Math Operators & Math Transforms # --------------------------------------------------------------------------- from ferro_ta.indicators.math_ops import ( # noqa: F401 ACOS, ADD, ASIN, ATAN, CEIL, COS, COSH, DIV, EXP, FLOOR, LN, LOG10, MAX, MAXINDEX, MIN, MININDEX, MULT, SIN, SINH, SQRT, SUB, SUM, TAN, TANH, ) # --------------------------------------------------------------------------- # Momentum Indicators # --------------------------------------------------------------------------- from ferro_ta.indicators.momentum import ( # noqa: F401 ADX, ADXR, APO, AROON, AROONOSC, BOP, CCI, CMO, DX, MFI, MINUS_DI, MINUS_DM, MOM, PLUS_DI, PLUS_DM, PPO, ROC, ROCP, ROCR, ROCR100, RSI, STOCH, STOCHF, STOCHRSI, TRANGE, TRIX, ULTOSC, WILLR, ) # --------------------------------------------------------------------------- # Overlap Studies # --------------------------------------------------------------------------- from ferro_ta.indicators.overlap import ( # noqa: F401 BBANDS, DEMA, EMA, KAMA, MA, MACD, MACDEXT, MACDFIX, MAMA, MAVP, MIDPOINT, MIDPRICE, SAR, SAREXT, SMA, T3, TEMA, TRIMA, WMA, ) # --------------------------------------------------------------------------- # Pattern Recognition # --------------------------------------------------------------------------- from ferro_ta.indicators.pattern import ( # noqa: F401 CDL2CROWS, CDL3BLACKCROWS, CDL3INSIDE, CDL3LINESTRIKE, CDL3OUTSIDE, CDL3STARSINSOUTH, CDL3WHITESOLDIERS, CDLABANDONEDBABY, CDLADVANCEBLOCK, CDLBELTHOLD, CDLBREAKAWAY, CDLCLOSINGMARUBOZU, CDLCONCEALBABYSWALL, CDLCOUNTERATTACK, CDLDARKCLOUDCOVER, CDLDOJI, CDLDOJISTAR, CDLDRAGONFLYDOJI, CDLENGULFING, CDLEVENINGDOJISTAR, CDLEVENINGSTAR, CDLGAPSIDESIDEWHITE, CDLGRAVESTONEDOJI, CDLHAMMER, CDLHANGINGMAN, CDLHARAMI, CDLHARAMICROSS, CDLHIGHWAVE, CDLHIKKAKE, CDLHIKKAKEMOD, CDLHOMINGPIGEON, CDLIDENTICAL3CROWS, CDLINNECK, CDLINVERTEDHAMMER, CDLKICKING, CDLKICKINGBYLENGTH, CDLLADDERBOTTOM, CDLLONGLEGGEDDOJI, CDLLONGLINE, CDLMARUBOZU, CDLMATCHINGLOW, CDLMATHOLD, CDLMORNINGDOJISTAR, CDLMORNINGSTAR, CDLONNECK, CDLPIERCING, CDLRICKSHAWMAN, CDLRISEFALL3METHODS, CDLSEPARATINGLINES, CDLSHOOTINGSTAR, CDLSHORTLINE, CDLSPINNINGTOP, CDLSTALLEDPATTERN, CDLSTICKSANDWICH, CDLTAKURI, CDLTASUKIGAP, CDLTHRUSTING, CDLTRISTAR, CDLUNIQUE3RIVER, CDLUPSIDEGAP2CROWS, CDLXSIDEGAP3METHODS, ) # --------------------------------------------------------------------------- # Price Transformations # --------------------------------------------------------------------------- from ferro_ta.indicators.price_transform import ( # noqa: F401 AVGPRICE, MEDPRICE, TYPPRICE, WCLPRICE, ) # --------------------------------------------------------------------------- # Statistic Functions # --------------------------------------------------------------------------- from ferro_ta.indicators.statistic import ( # noqa: F401 BETA, CORREL, LINEARREG, LINEARREG_ANGLE, LINEARREG_INTERCEPT, LINEARREG_SLOPE, STDDEV, TSF, VAR, ) # --------------------------------------------------------------------------- # Volatility Indicators # --------------------------------------------------------------------------- from ferro_ta.indicators.volatility import ( # noqa: F401 ATR, NATR, ) # --------------------------------------------------------------------------- # Volume Indicators # --------------------------------------------------------------------------- from ferro_ta.indicators.volume import ( # noqa: F401 AD, ADOSC, OBV, ) __all__ = [ "__version__", # Overlap Studies "SMA", "EMA", "WMA", "DEMA", "TEMA", "TRIMA", "KAMA", "T3", "BBANDS", "MACD", "MACDFIX", "MACDEXT", "SAR", "SAREXT", "MA", "MAVP", "MAMA", "MIDPOINT", "MIDPRICE", # Momentum "RSI", "MOM", "ROC", "ROCP", "ROCR", "ROCR100", "WILLR", "AROON", "AROONOSC", "CCI", "MFI", "BOP", "STOCHF", "STOCH", "STOCHRSI", "APO", "PPO", "CMO", "PLUS_DM", "MINUS_DM", "PLUS_DI", "MINUS_DI", "DX", "ADX", "ADXR", "TRIX", "ULTOSC", "TRANGE", # Volume "AD", "ADOSC", "OBV", # Volatility "ATR", "NATR", # Statistics "STDDEV", "VAR", "LINEARREG", "LINEARREG_SLOPE", "LINEARREG_INTERCEPT", "LINEARREG_ANGLE", "TSF", "BETA", "CORREL", # Price transforms "AVGPRICE", "MEDPRICE", "TYPPRICE", "WCLPRICE", # Patterns "CDL2CROWS", "CDL3BLACKCROWS", "CDL3INSIDE", "CDL3LINESTRIKE", "CDL3OUTSIDE", "CDL3STARSINSOUTH", "CDL3WHITESOLDIERS", "CDLABANDONEDBABY", "CDLADVANCEBLOCK", "CDLBELTHOLD", "CDLBREAKAWAY", "CDLCLOSINGMARUBOZU", "CDLCONCEALBABYSWALL", "CDLCOUNTERATTACK", "CDLDARKCLOUDCOVER", "CDLDOJI", "CDLDOJISTAR", "CDLDRAGONFLYDOJI", "CDLENGULFING", "CDLEVENINGDOJISTAR", "CDLEVENINGSTAR", "CDLGAPSIDESIDEWHITE", "CDLGRAVESTONEDOJI", "CDLHAMMER", "CDLHANGINGMAN", "CDLHARAMI", "CDLHARAMICROSS", "CDLHIGHWAVE", "CDLHIKKAKE", "CDLHIKKAKEMOD", "CDLHOMINGPIGEON", "CDLIDENTICAL3CROWS", "CDLINNECK", "CDLINVERTEDHAMMER", "CDLKICKING", "CDLKICKINGBYLENGTH", "CDLLADDERBOTTOM", "CDLLONGLEGGEDDOJI", "CDLLONGLINE", "CDLMARUBOZU", "CDLMATCHINGLOW", "CDLMATHOLD", "CDLMORNINGDOJISTAR", "CDLMORNINGSTAR", "CDLONNECK", "CDLPIERCING", "CDLRICKSHAWMAN", "CDLRISEFALL3METHODS", "CDLSEPARATINGLINES", "CDLSHOOTINGSTAR", "CDLSHORTLINE", "CDLSPINNINGTOP", "CDLSTALLEDPATTERN", "CDLSTICKSANDWICH", "CDLTAKURI", "CDLTASUKIGAP", "CDLTHRUSTING", "CDLTRISTAR", "CDLUNIQUE3RIVER", "CDLUPSIDEGAP2CROWS", "CDLXSIDEGAP3METHODS", # Cycle "HT_TRENDLINE", "HT_DCPERIOD", "HT_DCPHASE", "HT_PHASOR", "HT_SINE", "HT_TRENDMODE", # Math Operators "ADD", "SUB", "MULT", "DIV", "SUM", "MAX", "MIN", "MAXINDEX", "MININDEX", # Math Transforms "ACOS", "ASIN", "ATAN", "CEIL", "COS", "COSH", "EXP", "FLOOR", "LN", "LOG10", "SIN", "SINH", "SQRT", "TAN", "TANH", # Extended Indicators "VWAP", "SUPERTREND", "ICHIMOKU", "DONCHIAN", "PIVOT_POINTS", "KELTNER_CHANNELS", "HULL_MA", "CHANDELIER_EXIT", "VWMA", "CHOPPINESS_INDEX", # API discovery "about", "indicators", "methods", "info", # Logging utilities "enable_debug", "disable_debug", "debug_mode", "get_logger", "log_call", "benchmark", "traced", ] # --------------------------------------------------------------------------- # Extended Indicators # --------------------------------------------------------------------------- # --------------------------------------------------------------------------- # Pandas API — apply transparent pandas.Series / DataFrame support to every # public indicator function exported from this module. # --------------------------------------------------------------------------- from ferro_ta._utils import pandas_wrap as _pandas_wrap # noqa: E402 from ferro_ta._utils import polars_wrap as _polars_wrap # noqa: E402 from ferro_ta.analysis.attribution import ( # noqa: F401, E402 TradeStats, attribution_by_month, attribution_by_signal, from_backtest, trade_stats, ) from ferro_ta.analysis.crypto import ( # noqa: F401, E402 continuous_bar_labels, funding_pnl, resample_continuous, session_boundaries, ) from ferro_ta.analysis.regime import ( # noqa: F401, E402 detect_breaks_cusum, regime, regime_adx, regime_combined, rolling_variance_break, structural_breaks, ) from ferro_ta.core import exceptions as exceptions # noqa: F401, E402 # --------------------------------------------------------------------------- # Logging utilities — ferro_ta.enable_debug() / ferro_ta.benchmark() # --------------------------------------------------------------------------- from ferro_ta.core.logging_utils import ( # noqa: F401, E402 benchmark, debug_mode, disable_debug, enable_debug, get_logger, log_call, traced, ) from ferro_ta.data import batch as batch # noqa: F401, E402 from ferro_ta.data import streaming as streaming # noqa: F401, E402 # --------------------------------------------------------------------------- # Batch API (not in __all__ — use directly from ferro_ta.batch) # Import: from ferro_ta.batch import batch_sma, batch_ema, batch_rsi # --------------------------------------------------------------------------- from ferro_ta.data.batch import ( # noqa: F401, E402 batch_apply, batch_ema, batch_rsi, batch_sma, compute_many, ) from ferro_ta.data.chunked import ( # noqa: F401, E402 chunk_apply, make_chunk_ranges, stitch_chunks, trim_overlap, ) # --------------------------------------------------------------------------- # Streaming / Incremental API (not in __all__ — these are classes, not funcs) # Import directly: from ferro_ta.streaming import StreamingSMA, ... # --------------------------------------------------------------------------- from ferro_ta.data.streaming import ( # noqa: F401, E402 # type: ignore[assignment] StreamingATR, # type: ignore[attr-defined] StreamingBBands, # type: ignore[attr-defined] StreamingEMA, # type: ignore[attr-defined] StreamingMACD, # type: ignore[attr-defined] StreamingRSI, # type: ignore[attr-defined] StreamingSMA, # type: ignore[attr-defined] StreamingStoch, # type: ignore[attr-defined] StreamingSupertrend, # type: ignore[attr-defined] StreamingVWAP, # type: ignore[attr-defined] ) from ferro_ta.indicators import cycle as cycle # noqa: F401, E402 from ferro_ta.indicators import extended as extended # noqa: F401, E402 from ferro_ta.indicators import math_ops as math_ops # noqa: F401, E402 from ferro_ta.indicators import momentum as momentum # noqa: F401, E402 from ferro_ta.indicators import overlap as overlap # noqa: F401, E402 from ferro_ta.indicators import pattern as pattern # noqa: F401, E402 from ferro_ta.indicators import price_transform as price_transform # noqa: F401, E402 from ferro_ta.indicators import statistic as statistic # noqa: F401, E402 from ferro_ta.indicators import volatility as volatility # noqa: F401, E402 from ferro_ta.indicators import volume as volume # noqa: F401, E402 from ferro_ta.indicators.extended import ( # noqa: F401, E402 CHANDELIER_EXIT, CHOPPINESS_INDEX, DONCHIAN, HULL_MA, ICHIMOKU, KELTNER_CHANNELS, PIVOT_POINTS, SUPERTREND, VWAP, VWMA, ) # --------------------------------------------------------------------------- # Additional modules (not in __all__ — access via submodule) # --------------------------------------------------------------------------- from ferro_ta.tools.alerts import ( # noqa: F401, E402 AlertManager, check_cross, check_threshold, collect_alert_bars, ) # --------------------------------------------------------------------------- # API discovery helpers — ferro_ta.about(), ferro_ta.methods(), # ferro_ta.indicators(), and ferro_ta.info() # --------------------------------------------------------------------------- from ferro_ta.tools.api_info import about, indicators, info, methods # noqa: F401, E402 _ALIASED_SUBMODULES = { "batch": batch, "cycle": cycle, "exceptions": exceptions, "extended": extended, "math_ops": math_ops, "momentum": momentum, "overlap": overlap, "pattern": pattern, "price_transform": price_transform, "statistic": statistic, "streaming": streaming, "volatility": volatility, "volume": volume, } for _module_name, _module in _ALIASED_SUBMODULES.items(): setattr(_sys.modules[__name__], _module_name, _module) _sys.modules[f"{__name__}.{_module_name}"] = _module _g = globals() for _name in __all__: _fn = _g.get(_name) if callable(_fn) and not getattr(_fn, "_pandas_wrapped", False): _g[_name] = _pandas_wrap(_fn) _fn = _g.get(_name) if callable(_fn) and not getattr(_fn, "_polars_wrapped", False): _g[_name] = _polars_wrap(_fn) del _ALIASED_SUBMODULES, _g, _module, _module_name, _name, _fn, _sys