扩展指标

This commit is contained in:
2026-07-09 05:08:16 +08:00
commit 308c46ab9a
537 changed files with 152299 additions and 0 deletions
@@ -0,0 +1,25 @@
"""
ferro_ta.indicators — Technical indicator functions.
Sub-modules
-----------
* :mod:`ferro_ta.indicators.momentum` — Momentum Indicators (RSI, STOCH, ADX, CCI, …)
* :mod:`ferro_ta.indicators.overlap` — Overlap Studies (SMA, EMA, BBANDS, MACD, …)
* :mod:`ferro_ta.indicators.volatility` — Volatility Indicators (ATR, NATR, TRANGE)
* :mod:`ferro_ta.indicators.volume` — Volume Indicators (AD, ADOSC, OBV)
* :mod:`ferro_ta.indicators.statistic` — Statistic Functions (STDDEV, VAR, LINEARREG, …)
* :mod:`ferro_ta.indicators.price_transform` — Price Transforms (AVGPRICE, MEDPRICE, …)
* :mod:`ferro_ta.indicators.pattern` — Candlestick Pattern Recognition (CDL*)
* :mod:`ferro_ta.indicators.cycle` — Cycle Indicators (HT_TRENDLINE, HT_DCPERIOD, …)
* :mod:`ferro_ta.indicators.math_ops` — Math Operators/Transforms (ADD, SUB, SUM, …)
* :mod:`ferro_ta.indicators.extended` — Extended Indicators (VWAP, SUPERTREND, ICHIMOKU, …)
All indicators are also importable directly from :mod:`ferro_ta`::
import ferro_ta
result = ferro_ta.RSI(close, timeperiod=14)
# or directly from the sub-module:
from ferro_ta.indicators.momentum import RSI
result = RSI(close, timeperiod=14)
"""
@@ -0,0 +1,187 @@
"""
Cycle Indicators — Hilbert Transform-based cycle analysis.
All functions use a 63-bar lookback period (first 63 values are NaN).
Functions
---------
HT_TRENDLINE — Hilbert Transform - Instantaneous Trendline
HT_DCPERIOD — Hilbert Transform - Dominant Cycle Period
HT_DCPHASE — Hilbert Transform - Dominant Cycle Phase
HT_PHASOR — Hilbert Transform - Phasor Components (returns inphase, quadrature)
HT_SINE — Hilbert Transform - SineWave (returns sine, leadsine)
HT_TRENDMODE — Hilbert Transform - Trend vs Cycle Mode (1=trend, 0=cycle)
"""
from __future__ import annotations
import numpy as np
from numpy.typing import ArrayLike
from ferro_ta._ferro_ta import (
ht_dcperiod as _ht_dcperiod,
)
from ferro_ta._ferro_ta import (
ht_dcphase as _ht_dcphase,
)
from ferro_ta._ferro_ta import (
ht_phasor as _ht_phasor,
)
from ferro_ta._ferro_ta import (
ht_sine as _ht_sine,
)
from ferro_ta._ferro_ta import (
ht_trendline as _ht_trendline,
)
from ferro_ta._ferro_ta import (
ht_trendmode as _ht_trendmode,
)
from ferro_ta._utils import _to_f64
from ferro_ta.core.exceptions import _normalize_rust_error
def HT_TRENDLINE(close: ArrayLike) -> np.ndarray:
"""Hilbert Transform - Instantaneous Trendline.
Computes the underlying trend of the price series using the Hilbert
Transform. The trendline is the dominant-cycle-period average of the
smoothed price.
Parameters
----------
close : array-like
Sequence of closing prices.
Returns
-------
numpy.ndarray
Trendline values; first 63 entries are ``NaN``.
"""
try:
return _ht_trendline(_to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
def HT_DCPERIOD(close: ArrayLike) -> np.ndarray:
"""Hilbert Transform - Dominant Cycle Period.
Estimates the current dominant cycle period in bars using the Hilbert
Transform. Values are smoothed and clamped to [6, 50].
Parameters
----------
close : array-like
Sequence of closing prices.
Returns
-------
numpy.ndarray
Dominant cycle period values; first 63 entries are ``NaN``.
"""
try:
return _ht_dcperiod(_to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
def HT_DCPHASE(close: ArrayLike) -> np.ndarray:
"""Hilbert Transform - Dominant Cycle Phase.
Returns the instantaneous phase (in degrees) of the dominant cycle.
Parameters
----------
close : array-like
Sequence of closing prices.
Returns
-------
numpy.ndarray
Phase values in degrees; first 63 entries are ``NaN``.
"""
try:
return _ht_dcphase(_to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
def HT_PHASOR(
close: ArrayLike,
) -> tuple[np.ndarray, np.ndarray]:
"""Hilbert Transform - Phasor Components.
Returns the In-Phase (I) and Quadrature (Q) components of the Hilbert
Transform. These represent the real and imaginary parts of the analytic
signal derived from the price series.
Parameters
----------
close : array-like
Sequence of closing prices.
Returns
-------
tuple[numpy.ndarray, numpy.ndarray]
``(inphase, quadrature)`` — two arrays; first 63 entries are ``NaN``.
"""
try:
return _ht_phasor(_to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
def HT_SINE(
close: ArrayLike,
) -> tuple[np.ndarray, np.ndarray]:
"""Hilbert Transform - SineWave.
Returns the sine and lead-sine (45-degree lead) of the dominant cycle
phase. Used to detect cycle turning points.
Parameters
----------
close : array-like
Sequence of closing prices.
Returns
-------
tuple[numpy.ndarray, numpy.ndarray]
``(sine, leadsine)`` — two arrays; first 63 entries are ``NaN``.
"""
try:
return _ht_sine(_to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
def HT_TRENDMODE(close: ArrayLike) -> np.ndarray:
"""Hilbert Transform - Trend vs Cycle Mode.
Returns 1 when the market is in a trending mode (dominant cycle period
below 20 bars) and 0 when in a cycling mode.
Parameters
----------
close : array-like
Sequence of closing prices.
Returns
-------
numpy.ndarray[int32]
Array of 1 (trending) or 0 (cycling).
"""
try:
return _ht_trendmode(_to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
__all__ = [
"HT_TRENDLINE",
"HT_DCPERIOD",
"HT_DCPHASE",
"HT_PHASOR",
"HT_SINE",
"HT_TRENDMODE",
]
@@ -0,0 +1,498 @@
"""
Extended Indicators — Popular indicators not in the TA-Lib standard set.
All indicator logic is implemented in Rust (PyO3) for maximum performance.
This module provides the public Python API with:
- Input validation
- ``_to_f64`` conversion
- pandas/polars-compatible return values (numpy arrays)
Functions
---------
VWAP — Volume Weighted Average Price (cumulative or rolling)
SUPERTREND — ATR-based trend-following signal
ICHIMOKU — Ichimoku Cloud
DONCHIAN — Donchian Channels
PIVOT_POINTS — Classic / Fibonacci / Camarilla pivot levels
KELTNER_CHANNELS — EMA ± ATR bands
HULL_MA — Hull Moving Average (WMA-based)
CHANDELIER_EXIT — ATR-based stop-loss / exit levels
VWMA — Volume Weighted Moving Average
CHOPPINESS_INDEX — Market choppiness / trending strength index
Rust backend
------------
All computations delegate to Rust functions in the ``_ferro_ta`` extension::
from ferro_ta._ferro_ta import supertrend, donchian, vwap, ...
"""
from __future__ import annotations
import numpy as np
from numpy.typing import ArrayLike
# ---------------------------------------------------------------------------
# Import Rust implementations
# ---------------------------------------------------------------------------
from ferro_ta._ferro_ta import (
chandelier_exit as _rust_chandelier_exit,
)
from ferro_ta._ferro_ta import (
choppiness_index as _rust_choppiness_index,
)
from ferro_ta._ferro_ta import (
donchian as _rust_donchian,
)
from ferro_ta._ferro_ta import (
hull_ma as _rust_hull_ma,
)
from ferro_ta._ferro_ta import (
ichimoku as _rust_ichimoku,
)
from ferro_ta._ferro_ta import (
keltner_channels as _rust_keltner_channels,
)
from ferro_ta._ferro_ta import (
pivot_points as _rust_pivot_points,
)
from ferro_ta._ferro_ta import (
supertrend as _rust_supertrend,
)
from ferro_ta._ferro_ta import (
vwap as _rust_vwap,
)
from ferro_ta._ferro_ta import (
vwma as _rust_vwma,
)
from ferro_ta._utils import _to_f64
from ferro_ta.core.exceptions import FerroTAValueError, _normalize_rust_error
def VWAP(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
volume: ArrayLike,
timeperiod: int = 0,
) -> np.ndarray:
"""Volume Weighted Average Price.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
volume : array-like
Sequence of volumes.
timeperiod : int, optional
Rolling window length. ``0`` (default) computes a cumulative VWAP
from bar 0 (session VWAP). Any value ``>= 1`` uses a rolling window
of that length; the first ``timeperiod - 1`` values are ``NaN``.
Returns
-------
numpy.ndarray
Array of VWAP values.
Notes
-----
Typical price is used: ``(high + low + close) / 3``.
Implemented in Rust for maximum performance.
"""
if timeperiod < 0:
raise FerroTAValueError("timeperiod must be >= 0 for VWAP")
h = _to_f64(high)
lo = _to_f64(low)
c = _to_f64(close)
v = _to_f64(volume)
try:
return np.asarray(_rust_vwap(h, lo, c, v, timeperiod))
except ValueError as e:
_normalize_rust_error(e)
def SUPERTREND(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 7,
multiplier: float = 3.0,
) -> tuple[np.ndarray, np.ndarray]:
"""Supertrend indicator.
An ATR-based trend-following indicator. Returns the Supertrend line and a
direction array.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
ATR period (default 7).
multiplier : float, optional
ATR multiplier for band width (default 3.0).
Returns
-------
supertrend : numpy.ndarray
The Supertrend line values. ``NaN`` during the warmup period.
direction : numpy.ndarray
``1`` = uptrend (price above Supertrend), ``-1`` = downtrend.
``0`` during warmup.
Notes
-----
Implemented in Rust — the sequential band-adjustment loop that was
previously a Python bottleneck now runs at native speed.
Examples
--------
>>> import numpy as np
>>> from ferro_ta import SUPERTREND
>>> h = np.array([10.0, 11.0, 12.0, 11.0, 10.0, 9.0, 8.0, 9.0, 10.0, 11.0,
... 12.0, 13.0, 14.0, 13.0, 12.0])
>>> l = h - 1.0
>>> c = (h + l) / 2.0
>>> st, dir_ = SUPERTREND(h, l, c)
"""
h = _to_f64(high)
lo = _to_f64(low)
c = _to_f64(close)
try:
st, d = _rust_supertrend(h, lo, c, timeperiod, multiplier)
except ValueError as e:
_normalize_rust_error(e)
return np.asarray(st), np.asarray(d)
def ICHIMOKU(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
tenkan_period: int = 9,
kijun_period: int = 26,
senkou_b_period: int = 52,
displacement: int = 26,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
"""Ichimoku Cloud (Ichimoku Kinko Hyo).
Parameters
----------
high : array-like
low : array-like
close : array-like
tenkan_period : int, default 9
Conversion line (Tenkan-sen) period.
kijun_period : int, default 26
Base line (Kijun-sen) period.
senkou_b_period : int, default 52
Leading Span B period.
displacement : int, default 26
Displacement / cloud offset for Senkou A & B.
Returns
-------
tenkan, kijun, senkou_a, senkou_b, chikou : numpy.ndarray
Each is a 1-D float64 array of the same length as the inputs.
Notes
-----
Implemented in Rust with O(n) monotonic deque for all rolling windows.
"""
h = _to_f64(high)
lo = _to_f64(low)
c = _to_f64(close)
try:
t, k, sa, sb, ch = _rust_ichimoku(
h, lo, c, tenkan_period, kijun_period, senkou_b_period, displacement
)
except ValueError as e:
_normalize_rust_error(e)
return (
np.asarray(t),
np.asarray(k),
np.asarray(sa),
np.asarray(sb),
np.asarray(ch),
)
def DONCHIAN(
high: ArrayLike,
low: ArrayLike,
timeperiod: int = 20,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Donchian Channels — rolling highest high / lowest low.
Parameters
----------
high : array-like
low : array-like
timeperiod : int, default 20
Returns
-------
upper, middle, lower : numpy.ndarray
Rolling highest high, midpoint, and lowest low.
Notes
-----
Implemented in Rust with O(n) monotonic deque (no Python loop).
"""
h = _to_f64(high)
lo = _to_f64(low)
try:
upper, middle, lower = _rust_donchian(h, lo, timeperiod)
except ValueError as e:
_normalize_rust_error(e)
return np.asarray(upper), np.asarray(middle), np.asarray(lower)
def PIVOT_POINTS(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
method: str = "classic",
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
"""Pivot Points — support / resistance levels.
Computes pivot points for each bar using the *previous bar's* H/L/C.
The first bar output is NaN.
Parameters
----------
high : array-like
low : array-like
close : array-like
method : {'classic', 'fibonacci', 'camarilla'}, default 'classic'
Returns
-------
pivot, r1, s1, r2, s2 : numpy.ndarray
Notes
-----
**Classic**: P=(H+L+C)/3; R1=2PL; S1=2PH; R2=P+(HL); S2=P(HL)
**Fibonacci**: P=(H+L+C)/3; R1=P+0.382*(HL); S1=P0.382*(HL);
R2=P+0.618*(HL); S2=P0.618*(HL)
**Camarilla**: P=(H+L+C)/3; R1=C+1.1*(HL)/12; S1=C1.1*(HL)/12;
R2=C+1.1*(HL)/6; S2=C1.1*(HL)/6
"""
valid_methods = {"classic", "fibonacci", "camarilla"}
if method.lower() not in valid_methods:
raise FerroTAValueError(
f"Unknown pivot method '{method}'. Use 'classic', 'fibonacci', or 'camarilla'."
)
h = _to_f64(high)
lo = _to_f64(low)
c = _to_f64(close)
try:
pivot, r1, s1, r2, s2 = _rust_pivot_points(h, lo, c, method)
except ValueError as e:
_normalize_rust_error(e)
return (
np.asarray(pivot),
np.asarray(r1),
np.asarray(s1),
np.asarray(r2),
np.asarray(s2),
)
def KELTNER_CHANNELS(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 20,
atr_period: int = 10,
multiplier: float = 2.0,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Keltner Channels — EMA ± (multiplier × ATR).
Parameters
----------
high : array-like
low : array-like
close : array-like
timeperiod : int, default 20
EMA period for the middle band.
atr_period : int, default 10
ATR period for band width.
multiplier : float, default 2.0
ATR multiplier.
Returns
-------
upper, middle, lower : numpy.ndarray
Notes
-----
Implemented in Rust — EMA and ATR computed inline without Python calls.
"""
h = _to_f64(high)
lo = _to_f64(low)
c = _to_f64(close)
try:
upper, middle, lower = _rust_keltner_channels(
h, lo, c, timeperiod, atr_period, multiplier
)
except ValueError as e:
_normalize_rust_error(e)
return np.asarray(upper), np.asarray(middle), np.asarray(lower)
def HULL_MA(
close: ArrayLike,
timeperiod: int = 16,
) -> np.ndarray:
"""Hull Moving Average (HMA).
A fast-responding moving average that reduces lag.
Parameters
----------
close : array-like
timeperiod : int, default 16
Returns
-------
numpy.ndarray
Notes
-----
Formula: ``HMA(n) = WMA(2 * WMA(n/2) - WMA(n), sqrt(n))``
Implemented in Rust — all WMA computations are in-process.
"""
c = _to_f64(close)
try:
return np.asarray(_rust_hull_ma(c, timeperiod))
except ValueError as e:
_normalize_rust_error(e)
def CHANDELIER_EXIT(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 22,
multiplier: float = 3.0,
) -> tuple[np.ndarray, np.ndarray]:
"""Chandelier Exit — ATR-based trailing stop levels.
Parameters
----------
high : array-like
low : array-like
close : array-like
timeperiod : int, default 22
Lookback period for highest high / lowest low and ATR.
multiplier : float, default 3.0
ATR multiplier.
Returns
-------
long_exit, short_exit : numpy.ndarray
Notes
-----
Implemented in Rust with O(n) monotonic deque for rolling max/min.
"""
h = _to_f64(high)
lo = _to_f64(low)
c = _to_f64(close)
try:
long_exit, short_exit = _rust_chandelier_exit(h, lo, c, timeperiod, multiplier)
except ValueError as e:
_normalize_rust_error(e)
return np.asarray(long_exit), np.asarray(short_exit)
def VWMA(
close: ArrayLike,
volume: ArrayLike,
timeperiod: int = 20,
) -> np.ndarray:
"""Volume Weighted Moving Average.
Parameters
----------
close : array-like
volume : array-like
timeperiod : int, default 20
Returns
-------
numpy.ndarray
Notes
-----
``VWMA = sum(close * volume, n) / sum(volume, n)``
Implemented in Rust with O(n) prefix-sum approach.
"""
c = _to_f64(close)
v = _to_f64(volume)
try:
return np.asarray(_rust_vwma(c, v, timeperiod))
except ValueError as e:
_normalize_rust_error(e)
def CHOPPINESS_INDEX(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Choppiness Index — measures market choppiness (range-bound vs trending).
Parameters
----------
high : array-like
low : array-like
close : array-like
timeperiod : int, default 14
Returns
-------
numpy.ndarray
Values in ``[0, 100]``. Values near 100 indicate choppy/range-bound
markets; values near 0 indicate strong trends.
Notes
-----
``CI = 100 * log10(sum(ATR(1), n) / (highest_high lowest_low)) / log10(n)``
Implemented in Rust with O(n) monotonic deques (no Python loop).
"""
h = _to_f64(high)
lo = _to_f64(low)
c = _to_f64(close)
try:
return np.asarray(_rust_choppiness_index(h, lo, c, timeperiod))
except ValueError as e:
_normalize_rust_error(e)
__all__ = [
"VWAP",
"SUPERTREND",
"ICHIMOKU",
"DONCHIAN",
"PIVOT_POINTS",
"KELTNER_CHANNELS",
"HULL_MA",
"CHANDELIER_EXIT",
"VWMA",
"CHOPPINESS_INDEX",
]
@@ -0,0 +1,372 @@
"""
Math Operators & Math Transforms — TA-Lib compatibility shims.
Rolling functions (SUM, MAX, MIN, MAXINDEX, MININDEX) are implemented in Rust
using O(n) monotonic deque / prefix-sum algorithms. All other functions are
thin NumPy wrappers (element-wise operations).
Functions
---------
Math Operators:
ADD — Element-wise addition
SUB — Element-wise subtraction
MULT — Element-wise multiplication
DIV — Element-wise division
SUM — Rolling sum over *timeperiod* bars (Rust)
MAX — Rolling maximum over *timeperiod* bars (Rust)
MIN — Rolling minimum over *timeperiod* bars (Rust)
MAXINDEX — Index of rolling maximum over *timeperiod* bars (Rust)
MININDEX — Index of rolling minimum over *timeperiod* bars (Rust)
Math Transforms (element-wise):
ACOS ASIN ATAN CEIL COS COSH EXP FLOOR LN LOG10 SIN SINH SQRT TAN TANH
Rust backend
------------
Rolling operators delegate to::
from ferro_ta._ferro_ta import rolling_sum, rolling_max, rolling_min, ...
"""
from __future__ import annotations
import numpy as np
from numpy.typing import ArrayLike
# ---------------------------------------------------------------------------
# Import Rust rolling operators
# ---------------------------------------------------------------------------
from ferro_ta._ferro_ta import (
rolling_max as _rust_rolling_max,
)
from ferro_ta._ferro_ta import (
rolling_maxindex as _rust_rolling_maxindex,
)
from ferro_ta._ferro_ta import (
rolling_min as _rust_rolling_min,
)
from ferro_ta._ferro_ta import (
rolling_minindex as _rust_rolling_minindex,
)
from ferro_ta._ferro_ta import (
rolling_sum as _rust_rolling_sum,
)
from ferro_ta._utils import _to_f64
from ferro_ta.core.exceptions import _normalize_rust_error
# ---------------------------------------------------------------------------
# Math Operators
# ---------------------------------------------------------------------------
def ADD(real0: ArrayLike, real1: ArrayLike) -> np.ndarray:
"""Element-wise addition: real0 + real1.
Parameters
----------
real0, real1 : array-like
Input arrays (same length).
Returns
-------
numpy.ndarray[float64]
"""
try:
return np.add(_to_f64(real0), _to_f64(real1))
except ValueError as e:
_normalize_rust_error(e)
def SUB(real0: ArrayLike, real1: ArrayLike) -> np.ndarray:
"""Element-wise subtraction: real0 - real1.
Parameters
----------
real0, real1 : array-like
Input arrays (same length).
Returns
-------
numpy.ndarray[float64]
"""
try:
return np.subtract(_to_f64(real0), _to_f64(real1))
except ValueError as e:
_normalize_rust_error(e)
def MULT(real0: ArrayLike, real1: ArrayLike) -> np.ndarray:
"""Element-wise multiplication: real0 * real1.
Parameters
----------
real0, real1 : array-like
Input arrays (same length).
Returns
-------
numpy.ndarray[float64]
"""
try:
return np.multiply(_to_f64(real0), _to_f64(real1))
except ValueError as e:
_normalize_rust_error(e)
def DIV(real0: ArrayLike, real1: ArrayLike) -> np.ndarray:
"""Element-wise division: real0 / real1.
Parameters
----------
real0, real1 : array-like
Input arrays (same length).
Returns
-------
numpy.ndarray[float64]
"""
try:
# Suppress divide-by-zero warnings while preserving inf/NaN outputs.
with np.errstate(divide="ignore", invalid="ignore"):
return np.divide(_to_f64(real0), _to_f64(real1))
except ValueError as e:
_normalize_rust_error(e)
def SUM(real: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Rolling sum over *timeperiod* bars.
Parameters
----------
real : array-like
timeperiod : int, default 30
Returns
-------
numpy.ndarray[float64]
NaN for the first ``timeperiod - 1`` bars.
Notes
-----
Implemented in Rust using O(n) prefix-sum algorithm.
"""
try:
arr = _to_f64(real)
return np.asarray(_rust_rolling_sum(arr, timeperiod))
except ValueError as e:
_normalize_rust_error(e)
def MAX(real: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Rolling maximum over *timeperiod* bars.
Parameters
----------
real : array-like
timeperiod : int, default 30
Returns
-------
numpy.ndarray[float64]
NaN for the first ``timeperiod - 1`` bars.
Notes
-----
Implemented in Rust using O(n) monotonic deque algorithm.
"""
try:
arr = _to_f64(real)
return np.asarray(_rust_rolling_max(arr, timeperiod))
except ValueError as e:
_normalize_rust_error(e)
def MIN(real: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Rolling minimum over *timeperiod* bars.
Parameters
----------
real : array-like
timeperiod : int, default 30
Returns
-------
numpy.ndarray[float64]
NaN for the first ``timeperiod - 1`` bars.
Notes
-----
Implemented in Rust using O(n) monotonic deque algorithm.
"""
try:
arr = _to_f64(real)
return np.asarray(_rust_rolling_min(arr, timeperiod))
except ValueError as e:
_normalize_rust_error(e)
def MAXINDEX(real: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Index of the rolling maximum over *timeperiod* bars.
The index is the absolute position in the input array.
Parameters
----------
real : array-like
timeperiod : int, default 30
Returns
-------
numpy.ndarray[int64]
-1 for the first ``timeperiod - 1`` bars (warmup period).
Notes
-----
Implemented in Rust using O(n) monotonic deque algorithm.
"""
try:
arr = _to_f64(real)
return np.asarray(_rust_rolling_maxindex(arr, timeperiod))
except ValueError as e:
_normalize_rust_error(e)
def MININDEX(real: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Index of the rolling minimum over *timeperiod* bars.
The index is the absolute position in the input array.
Parameters
----------
real : array-like
timeperiod : int, default 30
Returns
-------
numpy.ndarray[int64]
-1 for the first ``timeperiod - 1`` bars (warmup period).
Notes
-----
Implemented in Rust using O(n) monotonic deque algorithm.
"""
try:
arr = _to_f64(real)
return np.asarray(_rust_rolling_minindex(arr, timeperiod))
except ValueError as e:
_normalize_rust_error(e)
# ---------------------------------------------------------------------------
# Math Transforms (element-wise)
# ---------------------------------------------------------------------------
def ACOS(real: ArrayLike) -> np.ndarray:
"""Arc cosine (element-wise). Returns NaN outside [-1, 1]."""
with np.errstate(invalid="ignore"):
return np.arccos(_to_f64(real))
def ASIN(real: ArrayLike) -> np.ndarray:
"""Arc sine (element-wise). Returns NaN outside [-1, 1]."""
with np.errstate(invalid="ignore"):
return np.arcsin(_to_f64(real))
def ATAN(real: ArrayLike) -> np.ndarray:
"""Arc tangent (element-wise)."""
return np.arctan(_to_f64(real))
def CEIL(real: ArrayLike) -> np.ndarray:
"""Ceiling (element-wise)."""
return np.ceil(_to_f64(real))
def COS(real: ArrayLike) -> np.ndarray:
"""Cosine (element-wise)."""
return np.cos(_to_f64(real))
def COSH(real: ArrayLike) -> np.ndarray:
"""Hyperbolic cosine (element-wise)."""
return np.cosh(_to_f64(real))
def EXP(real: ArrayLike) -> np.ndarray:
"""Exponential (element-wise)."""
return np.exp(_to_f64(real))
def FLOOR(real: ArrayLike) -> np.ndarray:
"""Floor (element-wise)."""
return np.floor(_to_f64(real))
def LN(real: ArrayLike) -> np.ndarray:
"""Natural logarithm (element-wise). Returns NaN for non-positive inputs."""
with np.errstate(divide="ignore", invalid="ignore"):
return np.log(_to_f64(real))
def LOG10(real: ArrayLike) -> np.ndarray:
"""Base-10 logarithm (element-wise). Returns NaN for non-positive inputs."""
with np.errstate(divide="ignore", invalid="ignore"):
return np.log10(_to_f64(real))
def SIN(real: ArrayLike) -> np.ndarray:
"""Sine (element-wise)."""
return np.sin(_to_f64(real))
def SINH(real: ArrayLike) -> np.ndarray:
"""Hyperbolic sine (element-wise)."""
return np.sinh(_to_f64(real))
def SQRT(real: ArrayLike) -> np.ndarray:
"""Square root (element-wise). Returns NaN for negative inputs."""
with np.errstate(invalid="ignore"):
return np.sqrt(_to_f64(real))
def TAN(real: ArrayLike) -> np.ndarray:
"""Tangent (element-wise)."""
return np.tan(_to_f64(real))
def TANH(real: ArrayLike) -> np.ndarray:
"""Hyperbolic tangent (element-wise)."""
return np.tanh(_to_f64(real))
__all__ = [
# 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",
]
@@ -0,0 +1,908 @@
"""
Momentum Indicators — Oscillators measuring speed and change of price movements.
Functions
---------
RSI — Relative Strength Index
MOM — Momentum
ROC — Rate of Change: ((price/prevPrice)-1)*100
ROCP — Rate of Change Percentage: (price-prevPrice)/prevPrice
ROCR — Rate of Change Ratio: price/prevPrice
ROCR100 — Rate of Change Ratio 100 scale: (price/prevPrice)*100
WILLR — Williams' %R
AROON — Aroon (returns aroon_down, aroon_up)
AROONOSC — Aroon Oscillator
CCI — Commodity Channel Index
MFI — Money Flow Index
BOP — Balance Of Power
STOCHF — Stochastic Fast
STOCH — Stochastic
STOCHRSI — Stochastic Relative Strength Index
APO — Absolute Price Oscillator
PPO — Percentage Price Oscillator
CMO — Chande Momentum Oscillator
PLUS_DM — Plus Directional Movement
MINUS_DM — Minus Directional Movement
PLUS_DI — Plus Directional Indicator
MINUS_DI — Minus Directional Indicator
DX — Directional Movement Index
ADX — Average Directional Movement Index
ADXR — Average Directional Movement Index Rating
TRIX — 1-day Rate-Of-Change of Triple Smooth EMA
ULTOSC — Ultimate Oscillator
TRANGE — True Range (also in volatility)
"""
from __future__ import annotations
import numpy as np
from numpy.typing import ArrayLike
from ferro_ta._ferro_ta import (
adx as _adx,
)
from ferro_ta._ferro_ta import (
adxr as _adxr,
)
from ferro_ta._ferro_ta import (
apo as _apo,
)
from ferro_ta._ferro_ta import (
aroon as _aroon,
)
from ferro_ta._ferro_ta import (
aroonosc as _aroonosc,
)
from ferro_ta._ferro_ta import (
bop as _bop,
)
from ferro_ta._ferro_ta import (
cci as _cci,
)
from ferro_ta._ferro_ta import (
cmo as _cmo,
)
from ferro_ta._ferro_ta import (
dx as _dx,
)
from ferro_ta._ferro_ta import (
mfi as _mfi,
)
from ferro_ta._ferro_ta import (
minus_di as _minus_di,
)
from ferro_ta._ferro_ta import (
minus_dm as _minus_dm,
)
from ferro_ta._ferro_ta import (
mom as _mom,
)
from ferro_ta._ferro_ta import (
plus_di as _plus_di,
)
from ferro_ta._ferro_ta import (
plus_dm as _plus_dm,
)
from ferro_ta._ferro_ta import (
ppo as _ppo,
)
from ferro_ta._ferro_ta import (
roc as _roc,
)
from ferro_ta._ferro_ta import (
rocp as _rocp,
)
from ferro_ta._ferro_ta import (
rocr as _rocr,
)
from ferro_ta._ferro_ta import (
rocr100 as _rocr100,
)
from ferro_ta._ferro_ta import (
rsi as _rsi,
)
from ferro_ta._ferro_ta import (
stoch as _stoch,
)
from ferro_ta._ferro_ta import (
stochf as _stochf,
)
from ferro_ta._ferro_ta import (
stochrsi as _stochrsi,
)
from ferro_ta._ferro_ta import (
trix as _trix,
)
from ferro_ta._ferro_ta import (
ultosc as _ultosc,
)
from ferro_ta._ferro_ta import (
willr as _willr,
)
from ferro_ta._utils import _to_f64
from ferro_ta.core.exceptions import _normalize_rust_error
from ferro_ta.indicators.volatility import TRANGE
def RSI(close: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""Relative Strength Index.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 14).
Returns
-------
numpy.ndarray
Array of RSI values (0100); leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _rsi(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def MOM(close: ArrayLike, timeperiod: int = 10) -> np.ndarray:
"""Momentum.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 10).
Returns
-------
numpy.ndarray
Array of MOM values; leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _mom(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def ROC(close: ArrayLike, timeperiod: int = 10) -> np.ndarray:
"""Rate of Change: ((price/prevPrice)-1)*100.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 10).
Returns
-------
numpy.ndarray
Array of ROC values; leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _roc(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def ROCP(close: ArrayLike, timeperiod: int = 10) -> np.ndarray:
"""Rate of Change Percentage: (price-prevPrice)/prevPrice.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 10).
Returns
-------
numpy.ndarray
Array of ROCP values; leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _rocp(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def ROCR(close: ArrayLike, timeperiod: int = 10) -> np.ndarray:
"""Rate of Change Ratio: price/prevPrice.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 10).
Returns
-------
numpy.ndarray
Array of ROCR values; leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _rocr(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def ROCR100(close: ArrayLike, timeperiod: int = 10) -> np.ndarray:
"""Rate of Change Ratio 100 scale: (price/prevPrice)*100.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 10).
Returns
-------
numpy.ndarray
Array of ROCR100 values; leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _rocr100(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def WILLR(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Williams' %R.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 14).
Returns
-------
numpy.ndarray
Array of WILLR values (-100 to 0); leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _willr(_to_f64(high), _to_f64(low), _to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def AROON(
high: ArrayLike,
low: ArrayLike,
timeperiod: int = 14,
) -> tuple[np.ndarray, np.ndarray]:
"""Aroon.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
timeperiod : int, optional
Number of periods (default 14).
Returns
-------
tuple[numpy.ndarray, numpy.ndarray]
``(aroondown, aroonup)`` — two arrays of equal length.
Leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _aroon(_to_f64(high), _to_f64(low), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def AROONOSC(
high: ArrayLike,
low: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Aroon Oscillator.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
timeperiod : int, optional
Number of periods (default 14).
Returns
-------
numpy.ndarray
Array of AROONOSC values; leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _aroonosc(_to_f64(high), _to_f64(low), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def CCI(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Commodity Channel Index.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 14).
Returns
-------
numpy.ndarray
Array of CCI values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _cci(_to_f64(high), _to_f64(low), _to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def MFI(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
volume: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Money Flow Index.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
volume : array-like
Sequence of volume values.
timeperiod : int, optional
Number of periods (default 14).
Returns
-------
numpy.ndarray
Array of MFI values (0100); leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _mfi(
_to_f64(high), _to_f64(low), _to_f64(close), _to_f64(volume), timeperiod
)
except ValueError as e:
_normalize_rust_error(e)
def BOP(
open: ArrayLike,
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
) -> np.ndarray:
"""Balance Of Power.
Parameters
----------
open : array-like
Sequence of open prices.
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
Returns
-------
numpy.ndarray
Array of BOP values (-1 to 1).
"""
try:
return _bop(_to_f64(open), _to_f64(high), _to_f64(low), _to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
def STOCHF(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
fastk_period: int = 5,
fastd_period: int = 3,
) -> tuple[np.ndarray, np.ndarray]:
"""Stochastic Fast.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
fastk_period : int, optional
%K period (default 5).
fastd_period : int, optional
%D smoothing period (default 3).
Returns
-------
tuple[numpy.ndarray, numpy.ndarray]
``(fastk, fastd)`` — two arrays of equal length.
"""
try:
return _stochf(
_to_f64(high), _to_f64(low), _to_f64(close), fastk_period, fastd_period
)
except ValueError as e:
_normalize_rust_error(e)
def STOCH(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
fastk_period: int = 5,
slowk_period: int = 3,
slowd_period: int = 3,
) -> tuple[np.ndarray, np.ndarray]:
"""Stochastic.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
fastk_period : int, optional
Fast %K period (default 5).
slowk_period : int, optional
Slow %K smoothing period (default 3).
slowd_period : int, optional
Slow %D smoothing period (default 3).
Returns
-------
tuple[numpy.ndarray, numpy.ndarray]
``(slowk, slowd)`` — two arrays of equal length.
"""
try:
return _stoch(
_to_f64(high),
_to_f64(low),
_to_f64(close),
fastk_period,
slowk_period,
slowd_period,
)
except ValueError as e:
_normalize_rust_error(e)
def STOCHRSI(
close: ArrayLike,
timeperiod: int = 14,
fastk_period: int = 5,
fastd_period: int = 3,
) -> tuple[np.ndarray, np.ndarray]:
"""Stochastic Relative Strength Index.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
RSI period (default 14).
fastk_period : int, optional
Stochastic %K period (default 5).
fastd_period : int, optional
Stochastic %D smoothing period (default 3).
Returns
-------
tuple[numpy.ndarray, numpy.ndarray]
``(fastk, fastd)`` — two arrays of equal length.
"""
try:
return _stochrsi(_to_f64(close), timeperiod, fastk_period, fastd_period)
except ValueError as e:
_normalize_rust_error(e)
def APO(
close: ArrayLike,
fastperiod: int = 12,
slowperiod: int = 26,
) -> np.ndarray:
"""Absolute Price Oscillator.
Parameters
----------
close : array-like
Sequence of closing prices.
fastperiod : int, optional
Fast EMA period (default 12).
slowperiod : int, optional
Slow EMA period (default 26).
Returns
-------
numpy.ndarray
Array of APO values; leading ``slowperiod - 1`` entries are ``NaN``.
"""
try:
return _apo(_to_f64(close), fastperiod, slowperiod)
except ValueError as e:
_normalize_rust_error(e)
def PPO(
close: ArrayLike,
fastperiod: int = 12,
slowperiod: int = 26,
signalperiod: int = 9,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Percentage Price Oscillator.
Parameters
----------
close : array-like
Sequence of closing prices.
fastperiod : int, optional
Fast EMA period (default 12).
slowperiod : int, optional
Slow EMA period (default 26).
signalperiod : int, optional
Signal EMA period (default 9).
Returns
-------
tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
``(ppo, signal, histogram)`` — three arrays of equal length.
"""
try:
return _ppo(_to_f64(close), fastperiod, slowperiod, signalperiod)
except ValueError as e:
_normalize_rust_error(e)
def CMO(close: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""Chande Momentum Oscillator.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 14).
Returns
-------
numpy.ndarray
Array of CMO values (-100 to 100); leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _cmo(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def PLUS_DM(high: ArrayLike, low: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""Plus Directional Movement.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
timeperiod : int, optional
Smoothing period (default 14).
Returns
-------
numpy.ndarray
Array of +DM values.
"""
try:
return _plus_dm(_to_f64(high), _to_f64(low), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def MINUS_DM(high: ArrayLike, low: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""Minus Directional Movement.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
timeperiod : int, optional
Smoothing period (default 14).
Returns
-------
numpy.ndarray
Array of -DM values.
"""
try:
return _minus_dm(_to_f64(high), _to_f64(low), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def PLUS_DI(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Plus Directional Indicator.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Smoothing period (default 14).
Returns
-------
numpy.ndarray
Array of +DI values.
"""
try:
return _plus_di(_to_f64(high), _to_f64(low), _to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def MINUS_DI(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Minus Directional Indicator.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Smoothing period (default 14).
Returns
-------
numpy.ndarray
Array of -DI values.
"""
try:
return _minus_di(_to_f64(high), _to_f64(low), _to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def DX(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Directional Movement Index.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Smoothing period (default 14).
Returns
-------
numpy.ndarray
Array of DX values (0100).
"""
try:
return _dx(_to_f64(high), _to_f64(low), _to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def ADX(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Average Directional Movement Index.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Smoothing period (default 14).
Returns
-------
numpy.ndarray
Array of ADX values (0100).
"""
try:
return _adx(_to_f64(high), _to_f64(low), _to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def ADXR(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Average Directional Movement Index Rating.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Smoothing period (default 14).
Returns
-------
numpy.ndarray
Array of ADXR values (0100).
"""
try:
return _adxr(_to_f64(high), _to_f64(low), _to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def TRIX(close: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""1-day Rate-Of-Change of a Triple Smooth EMA.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
EMA period (default 30).
Returns
-------
numpy.ndarray
Array of TRIX values.
"""
try:
return _trix(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def ULTOSC(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod1: int = 7,
timeperiod2: int = 14,
timeperiod3: int = 28,
) -> np.ndarray:
"""Ultimate Oscillator.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod1 : int, optional
First period (default 7).
timeperiod2 : int, optional
Second period (default 14).
timeperiod3 : int, optional
Third period (default 28).
Returns
-------
numpy.ndarray
Array of ULTOSC values (0100).
"""
try:
return _ultosc(
_to_f64(high),
_to_f64(low),
_to_f64(close),
timeperiod1,
timeperiod2,
timeperiod3,
)
except ValueError as e:
_normalize_rust_error(e)
__all__ = [
"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",
]
@@ -0,0 +1,656 @@
"""
Overlap Studies — Moving averages and bands that overlay directly on the price chart.
Functions
---------
SMA — Simple Moving Average
EMA — Exponential Moving Average
WMA — Weighted Moving Average
DEMA — Double Exponential Moving Average
TEMA — Triple Exponential Moving Average
TRIMA — Triangular Moving Average
KAMA — Kaufman Adaptive Moving Average
T3 — Triple Exponential Moving Average (Tillson T3)
BBANDS — Bollinger Bands
MACD — Moving Average Convergence/Divergence
MACDFIX — MACD with fixed 12/26 periods
MACDEXT — MACD with controllable MA types
SAR — Parabolic SAR
SAREXT — Parabolic SAR Extended
MA — Generic Moving Average (dispatches on matype)
MAVP — Moving Average with Variable Period
MAMA — MESA Adaptive Moving Average
MIDPOINT — MidPoint over period
MIDPRICE — MidPrice over period (High/Low)
"""
from __future__ import annotations
import numpy as np
from numpy.typing import ArrayLike
from ferro_ta._ferro_ta import (
bbands as _bbands,
)
from ferro_ta._ferro_ta import (
dema as _dema,
)
from ferro_ta._ferro_ta import (
ema as _ema,
)
from ferro_ta._ferro_ta import (
kama as _kama,
)
from ferro_ta._ferro_ta import (
ma as _ma,
)
from ferro_ta._ferro_ta import (
macd as _macd,
)
from ferro_ta._ferro_ta import (
macdext as _macdext,
)
from ferro_ta._ferro_ta import (
macdfix as _macdfix,
)
from ferro_ta._ferro_ta import (
mama as _mama,
)
from ferro_ta._ferro_ta import (
mavp as _mavp,
)
from ferro_ta._ferro_ta import (
midpoint as _midpoint,
)
from ferro_ta._ferro_ta import (
midprice as _midprice,
)
from ferro_ta._ferro_ta import (
sar as _sar,
)
from ferro_ta._ferro_ta import (
sarext as _sarext,
)
from ferro_ta._ferro_ta import (
sma as _sma,
)
from ferro_ta._ferro_ta import (
t3 as _t3,
)
from ferro_ta._ferro_ta import (
tema as _tema,
)
from ferro_ta._ferro_ta import (
trima as _trima,
)
from ferro_ta._ferro_ta import (
wma as _wma,
)
from ferro_ta._utils import _to_f64
from ferro_ta.core.exceptions import _normalize_rust_error
def SMA(close: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Simple Moving Average.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 30).
Returns
-------
numpy.ndarray
Array of SMA values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _sma(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def EMA(close: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Exponential Moving Average.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 30).
Returns
-------
numpy.ndarray
Array of EMA values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _ema(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def WMA(close: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Weighted Moving Average.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 30).
Returns
-------
numpy.ndarray
Array of WMA values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _wma(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def DEMA(close: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Double Exponential Moving Average.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 30).
Returns
-------
numpy.ndarray
Array of DEMA values; leading ``2 * (timeperiod - 1)`` entries are ``NaN``.
"""
try:
return _dema(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def TEMA(close: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Triple Exponential Moving Average.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 30).
Returns
-------
numpy.ndarray
Array of TEMA values; leading ``3 * (timeperiod - 1)`` entries are ``NaN``.
"""
try:
return _tema(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def TRIMA(close: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Triangular Moving Average.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 30).
Returns
-------
numpy.ndarray
Array of TRIMA values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _trima(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def KAMA(close: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Kaufman Adaptive Moving Average.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Efficiency Ratio lookback period (default 30).
Returns
-------
numpy.ndarray
Array of KAMA values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _kama(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def T3(close: ArrayLike, timeperiod: int = 5, vfactor: float = 0.7) -> np.ndarray:
"""Triple Exponential Moving Average (Tillson T3).
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 5).
vfactor : float, optional
Volume factor (default 0.7).
Returns
-------
numpy.ndarray
Array of T3 values.
"""
try:
return _t3(_to_f64(close), timeperiod, vfactor)
except ValueError as e:
_normalize_rust_error(e)
def BBANDS(
close: ArrayLike,
timeperiod: int = 5,
nbdevup: float = 2.0,
nbdevdn: float = 2.0,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Bollinger Bands.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Moving average window (default 5).
nbdevup : float, optional
Number of standard deviations above the middle band (default 2.0).
nbdevdn : float, optional
Number of standard deviations below the middle band (default 2.0).
Returns
-------
tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
``(upperband, middleband, lowerband)`` — three arrays of equal length.
Leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _bbands(_to_f64(close), timeperiod, nbdevup, nbdevdn)
except ValueError as e:
_normalize_rust_error(e)
def MACD(
close: ArrayLike,
fastperiod: int = 12,
slowperiod: int = 26,
signalperiod: int = 9,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Moving Average Convergence/Divergence.
Parameters
----------
close : array-like
Sequence of closing prices.
fastperiod : int, optional
Fast EMA period (default 12).
slowperiod : int, optional
Slow EMA period (default 26).
signalperiod : int, optional
Signal EMA period (default 9).
Returns
-------
tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
``(macd, signal, histogram)`` — three arrays of equal length.
Leading values that cannot be computed are ``NaN``.
"""
try:
return _macd(_to_f64(close), fastperiod, slowperiod, signalperiod)
except ValueError as e:
_normalize_rust_error(e)
def MACDFIX(
close: ArrayLike,
signalperiod: int = 9,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Moving Average Convergence/Divergence Fix 12/26.
Parameters
----------
close : array-like
Sequence of closing prices.
signalperiod : int, optional
Signal EMA period (default 9).
Returns
-------
tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
``(macd, signal, histogram)`` — three arrays of equal length.
"""
try:
return _macdfix(_to_f64(close), signalperiod)
except ValueError as e:
_normalize_rust_error(e)
def SAR(
high: ArrayLike,
low: ArrayLike,
acceleration: float = 0.02,
maximum: float = 0.2,
) -> np.ndarray:
"""Parabolic SAR.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
acceleration : float, optional
Acceleration factor step (default 0.02).
maximum : float, optional
Maximum acceleration factor (default 0.2).
Returns
-------
numpy.ndarray
Array of SAR values; first entry is ``NaN``.
"""
try:
return _sar(_to_f64(high), _to_f64(low), acceleration, maximum)
except ValueError as e:
_normalize_rust_error(e)
def MIDPOINT(close: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""MidPoint over period — (max + min) / 2 of close.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 14).
Returns
-------
numpy.ndarray
Array of MIDPOINT values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _midpoint(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def MIDPRICE(high: ArrayLike, low: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""MidPrice over period — (highest high + lowest low) / 2.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
timeperiod : int, optional
Number of periods (default 14).
Returns
-------
numpy.ndarray
Array of MIDPRICE values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _midprice(_to_f64(high), _to_f64(low), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def MA(close: ArrayLike, timeperiod: int = 30, matype: int = 0) -> np.ndarray:
"""Generic Moving Average.
Dispatches to the appropriate MA implementation based on *matype*.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Number of periods (default 30).
matype : int, optional
Moving average type (default 0):
* 0 = SMA (Simple)
* 1 = EMA (Exponential)
* 2 = WMA (Weighted)
* 3 = DEMA (Double EMA)
* 4 = TEMA (Triple EMA)
* 5 = TRIMA (Triangular)
* 6 = KAMA (Kaufman Adaptive)
* 7 = T3 (Tillson)
Returns
-------
numpy.ndarray
Array of MA values.
"""
try:
return _ma(_to_f64(close), timeperiod, matype)
except ValueError as e:
_normalize_rust_error(e)
def MAVP(
close: ArrayLike,
periods: ArrayLike,
minperiod: int = 2,
maxperiod: int = 30,
) -> np.ndarray:
"""Moving Average with Variable Period.
Computes a simple moving average at each bar using the period given by the
corresponding element of *periods*. Periods are clamped to
``[minperiod, maxperiod]``.
Parameters
----------
close : array-like
Sequence of closing prices.
periods : array-like
Sequence of period values (one per bar, same length as *close*).
minperiod : int, optional
Minimum allowed period (default 2).
maxperiod : int, optional
Maximum allowed period (default 30).
Returns
-------
numpy.ndarray
Array of variable-period MA values.
"""
try:
return _mavp(_to_f64(close), _to_f64(periods), minperiod, maxperiod)
except ValueError as e:
_normalize_rust_error(e)
def MAMA(
close: ArrayLike,
fastlimit: float = 0.5,
slowlimit: float = 0.05,
) -> tuple[np.ndarray, np.ndarray]:
"""MESA Adaptive Moving Average.
Returns the MAMA and FAMA (Following Adaptive MA) lines. The adaptive
alpha is derived from the rate of phase change of the Hilbert Transform.
Parameters
----------
close : array-like
Sequence of closing prices.
fastlimit : float, optional
Upper bound on the adaptive smoothing factor (default 0.5).
slowlimit : float, optional
Lower bound on the adaptive smoothing factor (default 0.05).
Returns
-------
tuple[numpy.ndarray, numpy.ndarray]
``(mama, fama)`` — two arrays; first 32 entries are ``NaN``.
"""
try:
return _mama(_to_f64(close), fastlimit, slowlimit)
except ValueError as e:
_normalize_rust_error(e)
def SAREXT(
high: ArrayLike,
low: ArrayLike,
startvalue: float = 0.0,
offsetonreverse: float = 0.0,
accelerationinitlong: float = 0.02,
accelerationlong: float = 0.02,
accelerationmaxlong: float = 0.2,
accelerationinitshort: float = 0.02,
accelerationshort: float = 0.02,
accelerationmaxshort: float = 0.2,
) -> np.ndarray:
"""Parabolic SAR Extended.
An extended version of the Parabolic SAR that allows independent
acceleration parameters for long and short positions, plus an optional
fixed start value and a gap-on-reverse offset.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
startvalue : float, optional
Fixed initial SAR value (0 = auto-detect, default 0.0).
offsetonreverse : float, optional
Multiplier applied to the SAR on trend reversal (default 0.0).
accelerationinitlong : float, optional
Initial acceleration factor for long positions (default 0.02).
accelerationlong : float, optional
Acceleration step for long positions (default 0.02).
accelerationmaxlong : float, optional
Maximum acceleration for long positions (default 0.2).
accelerationinitshort : float, optional
Initial acceleration factor for short positions (default 0.02).
accelerationshort : float, optional
Acceleration step for short positions (default 0.02).
accelerationmaxshort : float, optional
Maximum acceleration for short positions (default 0.2).
Returns
-------
numpy.ndarray
Array of SAREXT values; first entry is ``NaN``.
"""
try:
return _sarext(
_to_f64(high),
_to_f64(low),
startvalue,
offsetonreverse,
accelerationinitlong,
accelerationlong,
accelerationmaxlong,
accelerationinitshort,
accelerationshort,
accelerationmaxshort,
)
except ValueError as e:
_normalize_rust_error(e)
def MACDEXT(
close: ArrayLike,
fastperiod: int = 12,
fastmatype: int = 1,
slowperiod: int = 26,
slowmatype: int = 1,
signalperiod: int = 9,
signalmatype: int = 1,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""MACD with Controllable MA Types.
Like :func:`MACD` but allows specifying the moving average type for each
of the fast, slow, and signal lines independently.
Parameters
----------
close : array-like
Sequence of closing prices.
fastperiod : int, optional
Fast MA period (default 12).
fastmatype : int, optional
MA type for the fast line (default 1 = EMA).
slowperiod : int, optional
Slow MA period (default 26).
slowmatype : int, optional
MA type for the slow line (default 1 = EMA).
signalperiod : int, optional
Signal MA period (default 9).
signalmatype : int, optional
MA type for the signal line (default 1 = EMA).
MA type codes: 0=SMA, 1=EMA, 2=WMA.
Returns
-------
tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
``(macd, signal, histogram)`` — three arrays of equal length.
"""
try:
return _macdext(
_to_f64(close),
fastperiod,
fastmatype,
slowperiod,
slowmatype,
signalperiod,
signalmatype,
)
except ValueError as e:
_normalize_rust_error(e)
__all__ = [
"SMA",
"EMA",
"WMA",
"DEMA",
"TEMA",
"TRIMA",
"KAMA",
"T3",
"BBANDS",
"MACD",
"MACDFIX",
"MACDEXT",
"SAR",
"SAREXT",
"MA",
"MAVP",
"MAMA",
"MIDPOINT",
"MIDPRICE",
]
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,130 @@
"""
Price Transformations — Helper functions to synthesize OHLC arrays into single arrays.
Functions
---------
AVGPRICE — Average Price: (Open + High + Low + Close) / 4
MEDPRICE — Median Price: (High + Low) / 2
TYPPRICE — Typical Price: (High + Low + Close) / 3
WCLPRICE — Weighted Close Price: (High + Low + Close * 2) / 4
"""
from __future__ import annotations
import numpy as np
from numpy.typing import ArrayLike
from ferro_ta._ferro_ta import (
avgprice as _avgprice,
)
from ferro_ta._ferro_ta import (
medprice as _medprice,
)
from ferro_ta._ferro_ta import (
typprice as _typprice,
)
from ferro_ta._ferro_ta import (
wclprice as _wclprice,
)
from ferro_ta._utils import _to_f64
from ferro_ta.core.exceptions import _normalize_rust_error
def AVGPRICE(
open: ArrayLike,
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
) -> np.ndarray:
"""Average Price: (Open + High + Low + Close) / 4.
Parameters
----------
open : array-like
Sequence of open prices.
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
Returns
-------
numpy.ndarray
Array of AVGPRICE values.
"""
try:
return _avgprice(_to_f64(open), _to_f64(high), _to_f64(low), _to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
def MEDPRICE(high: ArrayLike, low: ArrayLike) -> np.ndarray:
"""Median Price: (High + Low) / 2.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
Returns
-------
numpy.ndarray
Array of MEDPRICE values.
"""
try:
return _medprice(_to_f64(high), _to_f64(low))
except ValueError as e:
_normalize_rust_error(e)
def TYPPRICE(high: ArrayLike, low: ArrayLike, close: ArrayLike) -> np.ndarray:
"""Typical Price: (High + Low + Close) / 3.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
Returns
-------
numpy.ndarray
Array of TYPPRICE values.
"""
try:
return _typprice(_to_f64(high), _to_f64(low), _to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
def WCLPRICE(high: ArrayLike, low: ArrayLike, close: ArrayLike) -> np.ndarray:
"""Weighted Close Price: (High + Low + Close * 2) / 4.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
Returns
-------
numpy.ndarray
Array of WCLPRICE values.
"""
try:
return _wclprice(_to_f64(high), _to_f64(low), _to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
__all__ = ["AVGPRICE", "MEDPRICE", "TYPPRICE", "WCLPRICE"]
@@ -0,0 +1,369 @@
"""
Statistic Functions — Standard statistical math applied to rolling windows of price data.
Functions
---------
STDDEV — Standard Deviation
VAR — Variance
LINEARREG — Linear Regression
LINEARREG_SLOPE — Linear Regression Slope
LINEARREG_INTERCEPT — Linear Regression Intercept
LINEARREG_ANGLE — Linear Regression Angle (degrees)
TSF — Time Series Forecast
BETA — Beta
CORREL — Pearson's Correlation Coefficient (r)
DTW — Dynamic Time Warping (distance + warping path)
DTW_DISTANCE — Dynamic Time Warping distance only (faster)
BATCH_DTW — Batch DTW: N series vs 1 reference, in parallel
"""
from __future__ import annotations
from typing import Optional
import numpy as np
from numpy.typing import ArrayLike
from ferro_ta._ferro_ta import (
batch_dtw as _batch_dtw,
)
from ferro_ta._ferro_ta import (
beta as _beta,
)
from ferro_ta._ferro_ta import (
correl as _correl,
)
from ferro_ta._ferro_ta import (
dtw as _dtw,
)
from ferro_ta._ferro_ta import (
dtw_distance as _dtw_distance,
)
from ferro_ta._ferro_ta import (
linearreg as _linearreg,
)
from ferro_ta._ferro_ta import (
linearreg_angle as _linearreg_angle,
)
from ferro_ta._ferro_ta import (
linearreg_intercept as _linearreg_intercept,
)
from ferro_ta._ferro_ta import (
linearreg_slope as _linearreg_slope,
)
from ferro_ta._ferro_ta import (
stddev as _stddev,
)
from ferro_ta._ferro_ta import (
tsf as _tsf,
)
from ferro_ta._ferro_ta import (
var as _var,
)
from ferro_ta._utils import _to_f64
from ferro_ta.core.exceptions import _normalize_rust_error
def STDDEV(close: ArrayLike, timeperiod: int = 5, nbdev: float = 1.0) -> np.ndarray:
"""Standard Deviation.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Rolling window size (default 5).
nbdev : float, optional
Number of standard deviations (default 1.0).
Returns
-------
numpy.ndarray
Array of STDDEV values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _stddev(_to_f64(close), timeperiod, nbdev)
except ValueError as e:
_normalize_rust_error(e)
def VAR(close: ArrayLike, timeperiod: int = 5, nbdev: float = 1.0) -> np.ndarray:
"""Variance.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Rolling window size (default 5).
nbdev : float, optional
Number of deviations (default 1.0).
Returns
-------
numpy.ndarray
Array of VAR values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _var(_to_f64(close), timeperiod, nbdev)
except ValueError as e:
_normalize_rust_error(e)
def LINEARREG(close: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""Linear Regression.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Regression window (default 14).
Returns
-------
numpy.ndarray
Array of linear regression end-point values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _linearreg(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def LINEARREG_SLOPE(close: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""Linear Regression Slope.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Regression window (default 14).
Returns
-------
numpy.ndarray
Array of slope values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _linearreg_slope(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def LINEARREG_INTERCEPT(close: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""Linear Regression Intercept.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Regression window (default 14).
Returns
-------
numpy.ndarray
Array of intercept values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _linearreg_intercept(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def LINEARREG_ANGLE(close: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""Linear Regression Angle (in degrees).
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Regression window (default 14).
Returns
-------
numpy.ndarray
Array of angle values in degrees; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _linearreg_angle(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def TSF(close: ArrayLike, timeperiod: int = 14) -> np.ndarray:
"""Time Series Forecast — linear regression extrapolated one period ahead.
Parameters
----------
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Regression window (default 14).
Returns
-------
numpy.ndarray
Array of TSF values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _tsf(_to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def BETA(real0: ArrayLike, real1: ArrayLike, timeperiod: int = 5) -> np.ndarray:
"""Beta — regression slope of real0 relative to real1.
Parameters
----------
real0 : array-like
Sequence of prices for asset 0 (dependent variable).
real1 : array-like
Sequence of prices for asset 1 (independent variable).
timeperiod : int, optional
Rolling window (default 5).
Returns
-------
numpy.ndarray
Array of BETA values; leading ``timeperiod`` entries are ``NaN``.
"""
try:
return _beta(_to_f64(real0), _to_f64(real1), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def CORREL(real0: ArrayLike, real1: ArrayLike, timeperiod: int = 30) -> np.ndarray:
"""Pearson's Correlation Coefficient (r).
Parameters
----------
real0 : array-like
First data series.
real1 : array-like
Second data series.
timeperiod : int, optional
Rolling window (default 30).
Returns
-------
numpy.ndarray
Array of CORREL values (-1 to 1); leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _correl(_to_f64(real0), _to_f64(real1), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def DTW(
series1: ArrayLike,
series2: ArrayLike,
window: Optional[int] = None,
) -> tuple[float, np.ndarray]:
"""Dynamic Time Warping — distance and optimal warping path.
Parameters
----------
series1 : array-like
First time series.
series2 : array-like
Second time series (may differ in length from series1).
window : int, optional
Sakoe-Chiba band width. ``None`` (default) = unconstrained.
Returns
-------
distance : float
DTW distance (accumulated Euclidean cost along the optimal path).
path : numpy.ndarray, shape (N, 2)
Warping path as ``(i, j)`` index pairs from ``(0, 0)`` to
``(len(series1)-1, len(series2)-1)``.
"""
try:
return _dtw(_to_f64(series1), _to_f64(series2), window)
except ValueError as e:
_normalize_rust_error(e)
def DTW_DISTANCE(
series1: ArrayLike,
series2: ArrayLike,
window: Optional[int] = None,
) -> float:
"""Dynamic Time Warping distance only (faster — no path reconstruction).
Parameters
----------
series1 : array-like
First time series.
series2 : array-like
Second time series (may differ in length from series1).
window : int, optional
Sakoe-Chiba band width. ``None`` (default) = unconstrained.
Returns
-------
float
DTW distance (accumulated Euclidean cost along the optimal path).
"""
try:
return _dtw_distance(_to_f64(series1), _to_f64(series2), window)
except ValueError as e:
_normalize_rust_error(e)
def BATCH_DTW(
matrix: ArrayLike,
reference: ArrayLike,
window: Optional[int] = None,
) -> np.ndarray:
"""Batch Dynamic Time Warping — N series vs 1 reference, computed in parallel.
Parameters
----------
matrix : array-like, shape (N, L)
N time series of length L. Each row is compared against ``reference``.
reference : array-like, shape (L,)
The reference series.
window : int, optional
Sakoe-Chiba band width. ``None`` (default) = unconstrained.
Returns
-------
numpy.ndarray, shape (N,)
DTW distance from each row of ``matrix`` to ``reference``.
"""
try:
mat = np.ascontiguousarray(matrix, dtype=np.float64)
if mat.ndim != 2:
from ferro_ta.core.exceptions import FerroTAInputError
raise FerroTAInputError(
f"matrix must be a 2-D array, got {mat.ndim}-D.",
suggestion="Pass a 2-D NumPy array of shape (N, L).",
)
return _batch_dtw(mat, _to_f64(reference), window)
except ValueError as e:
_normalize_rust_error(e)
__all__ = [
"STDDEV",
"VAR",
"LINEARREG",
"LINEARREG_SLOPE",
"LINEARREG_INTERCEPT",
"LINEARREG_ANGLE",
"TSF",
"BETA",
"CORREL",
"DTW",
"DTW_DISTANCE",
"BATCH_DTW",
]
@@ -0,0 +1,116 @@
"""
Volatility Indicators — Measure the magnitude of price fluctuations.
Functions
---------
ATR — Average True Range
NATR — Normalized Average True Range
TRANGE — True Range
"""
from __future__ import annotations
import numpy as np
from numpy.typing import ArrayLike
from ferro_ta._ferro_ta import (
atr as _atr,
)
from ferro_ta._ferro_ta import (
natr as _natr,
)
from ferro_ta._ferro_ta import (
trange as _trange,
)
from ferro_ta._utils import _to_f64
from ferro_ta.core.exceptions import _normalize_rust_error
def ATR(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Average True Range.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Smoothing period (default 14).
Returns
-------
numpy.ndarray
Array of ATR values; leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _atr(_to_f64(high), _to_f64(low), _to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def NATR(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
timeperiod: int = 14,
) -> np.ndarray:
"""Normalized Average True Range.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
timeperiod : int, optional
Smoothing period (default 14).
Returns
-------
numpy.ndarray
Array of NATR values (percentage); leading ``timeperiod - 1`` entries are ``NaN``.
"""
try:
return _natr(_to_f64(high), _to_f64(low), _to_f64(close), timeperiod)
except ValueError as e:
_normalize_rust_error(e)
def TRANGE(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
) -> np.ndarray:
"""True Range.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
Returns
-------
numpy.ndarray
Array of True Range values.
"""
try:
return _trange(_to_f64(high), _to_f64(low), _to_f64(close))
except ValueError as e:
_normalize_rust_error(e)
__all__ = ["ATR", "NATR", "TRANGE"]
@@ -0,0 +1,123 @@
"""
Volume Indicators — Require volume data to measure buying and selling pressure.
Functions
---------
AD — Chaikin A/D Line
ADOSC — Chaikin A/D Oscillator
OBV — On Balance Volume
"""
from __future__ import annotations
import numpy as np
from numpy.typing import ArrayLike
from ferro_ta._ferro_ta import (
ad as _ad,
)
from ferro_ta._ferro_ta import (
adosc as _adosc,
)
from ferro_ta._ferro_ta import (
obv as _obv,
)
from ferro_ta._utils import _to_f64
from ferro_ta.core.exceptions import _normalize_rust_error
def AD(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
volume: ArrayLike,
) -> np.ndarray:
"""Chaikin A/D Line.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
volume : array-like
Sequence of volume values.
Returns
-------
numpy.ndarray
Cumulative A/D Line values.
"""
try:
return _ad(_to_f64(high), _to_f64(low), _to_f64(close), _to_f64(volume))
except ValueError as e:
_normalize_rust_error(e)
def ADOSC(
high: ArrayLike,
low: ArrayLike,
close: ArrayLike,
volume: ArrayLike,
fastperiod: int = 3,
slowperiod: int = 10,
) -> np.ndarray:
"""Chaikin A/D Oscillator.
Parameters
----------
high : array-like
Sequence of high prices.
low : array-like
Sequence of low prices.
close : array-like
Sequence of closing prices.
volume : array-like
Sequence of volume values.
fastperiod : int, optional
Fast EMA period (default 3).
slowperiod : int, optional
Slow EMA period (default 10).
Returns
-------
numpy.ndarray
Array of ADOSC values; leading ``slowperiod - 1`` entries are ``NaN``.
"""
try:
return _adosc(
_to_f64(high),
_to_f64(low),
_to_f64(close),
_to_f64(volume),
fastperiod,
slowperiod,
)
except ValueError as e:
_normalize_rust_error(e)
def OBV(close: ArrayLike, volume: ArrayLike) -> np.ndarray:
"""On Balance Volume.
Parameters
----------
close : array-like
Sequence of closing prices.
volume : array-like
Sequence of volume values.
Returns
-------
numpy.ndarray
Cumulative OBV values.
"""
try:
return _obv(_to_f64(close), _to_f64(volume))
except ValueError as e:
_normalize_rust_error(e)
__all__ = ["AD", "ADOSC", "OBV"]