# ferro-ta ↔ finta Compatibility [finta](https://github.com/peerchemist/finta) implements over 80 financial technical indicators as class methods on a single `TA` class, operating entirely on Pandas DataFrames. --- ## Key architectural differences | Aspect | ferro-ta | finta | |--------|---------|-------| | **Backend** | Rust/C + SIMD | Pure Pandas | | **Input type** | NumPy array or list | OHLCV Pandas DataFrame (required) | | **DatetimeIndex** | Not required | **Required** | | **Column names** | Separate arrays | `open/high/low/close/volume` | | **Output type** | NumPy array | Pandas Series or DataFrame | | **NaN handling** | Pads warmup with NaN | Pads warmup with NaN | | **Streaming** | Yes (StreamingXxx classes) | No | | **Speed** | ~700× faster on ATR | Baseline (pure Pandas) | --- ## Required DataFrame format finta requires a **Pandas DataFrame with a DatetimeIndex** and lowercase column names: ```python import pandas as pd import numpy as np df = pd.DataFrame({ "open": open_prices, "high": high_prices, "low": low_prices, "close": close_prices, "volume": volume_data, # required for volume indicators }, index=pd.date_range("2020-01-01", periods=len(close_prices), freq="D")) ``` ferro-ta accepts raw NumPy arrays or Python lists — no DataFrame needed. --- ## Function signature mapping finta uses a class-method API: `TA.INDICATOR(ohlcv_df, period, ...)`. | Indicator | ferro-ta | finta | |-----------|---------|-------| | SMA | `SMA(close, timeperiod=20)` | `TA.SMA(df, 20)` | | EMA | `EMA(close, timeperiod=20)` | `TA.EMA(df, 20)` | | WMA | `WMA(close, timeperiod=14)` | `TA.WMA(df, 14)` | | DEMA | `DEMA(close, timeperiod=30)` | `TA.DEMA(df, 30)` | | TEMA | `TEMA(close, timeperiod=30)` | `TA.TEMA(df, 30)` | | HMA | Not supported | `TA.HMA(df, 16)` | | RSI | `RSI(close, timeperiod=14)` | `TA.RSI(df, 14)` | | MACD | `MACD(close, 12, 26, 9)` → (macd, signal, hist) | `TA.MACD(df, 12, 26, 9)` → DataFrame with `MACD`/`SIGNAL` columns | | BBANDS | `BBANDS(close, 20, 2.0, 2.0)` → (upper, mid, lower) | `TA.BBANDS(df, 20)` → DataFrame with `BB_UPPER`/`BB_MIDDLE`/`BB_LOWER` | | ATR | `ATR(high, low, close, timeperiod=14)` | `TA.ATR(df, 14)` | | TRUE RANGE | `TRANGE(high, low, close)` | `TA.TR(df)` | | OBV | `OBV(close, volume)` | `TA.OBV(df)` | | MFI | `MFI(high, low, close, volume, timeperiod=14)` | `TA.MFI(df, 14)` | | CCI | `CCI(high, low, close, timeperiod=14)` | `TA.CCI(df, 14)` | | STOCH | `STOCH(high, low, close, 5, 3, 3)` | `TA.STOCH(df, 14)` | | WILLR | `WILLR(high, low, close, timeperiod=14)` | `TA.WILLIAMS(df, 14)` | | ADX | `ADX(high, low, close, timeperiod=14)` | `TA.ADX(df, 14)` | | AROON | `AROON(high, low, timeperiod=14)` → (up, down) | `TA.AROON(df, 14)` → DataFrame | --- ## Numerical accuracy finta uses sample standard deviation (ddof=1) for Bollinger Bands while ferro-ta follows the TA-Lib convention (population std, ddof=0). For a window of 20 bars this creates a ~0.5% difference in band width. For EMA-based indicators, finta seeds with the first data point while ferro-ta follows TA-Lib (SMA of first `timeperiod` bars). Values converge after ~3× the period. Cross-library correlation between ferro-ta and finta is ≥ 0.95 for all indicators after discarding the warm-up period. --- ## Speed comparison On 10,000 bars (median µs, Apple M-series): | Indicator | ferro-ta | finta | ferro-ta speedup | |-----------|--------:|-------:|----------------:| | SMA | 16.7 | 178.1 | **10.7×** | | MACD | 70.4 | 383.9 | **5.5×** | | ATR | 51.4 | 1,247 | **24×** | On 100,000 bars: | Indicator | ferro-ta | finta | ferro-ta speedup | |-----------|--------:|--------:|----------------:| | SMA | 126.2 | 699.7 | **5.6×** | | MACD | 465.9 | 1,470.8 | **3.2×** | | ATR | 478.5 | 6,782 | **14×** | finta's ATR scales especially poorly because it relies on Pandas `.apply()` with a lambda, which cannot be vectorised. --- ## Migration guide ```python # FROM finta import pandas as pd from finta import TA ohlcv = pd.DataFrame(...) # must have DatetimeIndex + open/high/low/close/volume sma = TA.SMA(ohlcv, 20) # returns Pandas Series macd_df = TA.MACD(ohlcv, 12, 26, 9) # returns DataFrame with MACD/SIGNAL cols bb_df = TA.BBANDS(ohlcv, 20) # returns DataFrame with BB_UPPER/MIDDLE/LOWER # TO ferro-ta (NumPy arrays — no DataFrame required) import ferro_ta import numpy as np close = ohlcv["close"].values sma = ferro_ta.SMA(close, timeperiod=20) macd, signal, hist = ferro_ta.MACD(close, fastperiod=12, slowperiod=26, signalperiod=9) upper, middle, lower = ferro_ta.BBANDS(close, timeperiod=20, nbdevup=2.0, nbdevdn=2.0) ``` --- ## Known limitations - finta cannot process raw NumPy arrays — a properly formatted DataFrame with DatetimeIndex is always required. - `TA.MACD` only returns `MACD` and `SIGNAL` columns; the histogram must be computed manually as `MACD - SIGNAL`. - Several finta indicators use non-standard formulas that may not match TA-Lib conventions (e.g. STOCH uses a fixed 14-period window regardless of the `fastk_period` argument).