5.1 KiB
ferro-ta ↔ finta Compatibility
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:
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
# 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.MACDonly returnsMACDandSIGNALcolumns; the histogram must be computed manually asMACD - 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_periodargument).