扩展指标
This commit is contained in:
@@ -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=2P−L; S1=2P−H; R2=P+(H−L); S2=P−(H−L)
|
||||
|
||||
**Fibonacci**: P=(H+L+C)/3; R1=P+0.382*(H−L); S1=P−0.382*(H−L);
|
||||
R2=P+0.618*(H−L); S2=P−0.618*(H−L)
|
||||
|
||||
**Camarilla**: P=(H+L+C)/3; R1=C+1.1*(H−L)/12; S1=C−1.1*(H−L)/12;
|
||||
R2=C+1.1*(H−L)/6; S2=C−1.1*(H−L)/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 (0–100); 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 (0–100); 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 (0–100).
|
||||
"""
|
||||
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 (0–100).
|
||||
"""
|
||||
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 (0–100).
|
||||
"""
|
||||
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 (0–100).
|
||||
"""
|
||||
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"]
|
||||
Reference in New Issue
Block a user