From aff07b9cbb2d2636aaa842eeb99f280759a47d3c Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 14:59:47 +0200 Subject: [PATCH 01/18] supertrend in trend.py --- .github/FUNDING.yml | 2 +- docs/conf.py | 7 - docs/index.rst | 6 +- ta/momentum.py | 287 ++++++++++++----------- ta/others.py | 4 +- ta/trend.py | 444 +++++++++++++++++++++++------------- ta/utils.py | 2 +- ta/volatility.py | 80 +++---- ta/volume.py | 106 ++++----- ta/wrapper.py | 70 +++--- test/__init__.py | 38 --- test/integration/wrapper.py | 10 +- test/unit/momentum.py | 1 - test/unit/trend.py | 2 - test/unit/volatility.py | 1 - test/unit/volume.py | 1 - 16 files changed, 572 insertions(+), 489 deletions(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 0c004d8b..bb487093 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,2 @@ -github: [bukosabino] +github: [ bukosabino ] tidelift: pypi/ta diff --git a/docs/conf.py b/docs/conf.py index cbb8ecee..3e76c0ff 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,7 +19,6 @@ import sys sys.path.append("..") # Adds higher directory to python modules path. -from ta import * # -- Project information ----------------------------------------------------- @@ -32,7 +31,6 @@ # The full version, including alpha/beta/rc tags release = "0.1.4" - # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -78,7 +76,6 @@ # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" - # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for @@ -113,7 +110,6 @@ # Output file base name for HTML help builder. htmlhelp_basename = "TechnicalAnalysisLibraryinPythondoc" - # -- Options for LaTeX output ------------------------------------------------ latex_elements = { @@ -144,7 +140,6 @@ ), ] - # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples @@ -159,7 +154,6 @@ ) ] - # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples @@ -177,5 +171,4 @@ ), ] - # -- Extension configuration ------------------------------------------------- diff --git a/docs/index.rst b/docs/index.rst index 2eb5b8cb..95d03afb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,7 +1,7 @@ .. Technical Analysis Library in Python documentation master file, created by - sphinx-quickstart on Tue Apr 10 15:47:09 2018. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +sphinx-quickstart on Tue Apr 10 15:47:09 2018. +You can adapt this file completely to your liking, but it should at least +contain the root `toctree` directive. Welcome to Technical Analysis Library in Python's documentation! ================================================================ diff --git a/ta/momentum.py b/ta/momentum.py index b86d974b..c0122908 100644 --- a/ta/momentum.py +++ b/ta/momentum.py @@ -26,7 +26,6 @@ class RSIIndicator(IndicatorMixin): window(int): n period. fillna(bool): if True, fill nan values. """ - def __init__(self, close: pd.Series, window: int = 14, fillna: bool = False): self._close = close self._window = window @@ -75,11 +74,11 @@ class TSIIndicator(IndicatorMixin): """ def __init__( - self, - close: pd.Series, - window_slow: int = 25, - window_fast: int = 13, - fillna: bool = False, + self, + close: pd.Series, + window_slow: int = 25, + window_fast: int = 13, + fillna: bool = False, ): self._close = close self._window_slow = window_slow @@ -95,16 +94,16 @@ def _run(self): diff_close.ewm( span=self._window_slow, min_periods=min_periods_r, adjust=False ) - .mean() - .ewm(span=self._window_fast, min_periods=min_periods_s, adjust=False) - .mean() + .mean() + .ewm(span=self._window_fast, min_periods=min_periods_s, adjust=False) + .mean() ) smoothed_abs = ( abs(diff_close) - .ewm(span=self._window_slow, min_periods=min_periods_r, adjust=False) - .mean() - .ewm(span=self._window_fast, min_periods=min_periods_s, adjust=False) - .mean() + .ewm(span=self._window_slow, min_periods=min_periods_r, adjust=False) + .mean() + .ewm(span=self._window_fast, min_periods=min_periods_s, adjust=False) + .mean() ) self._tsi = smoothed / smoothed_abs self._tsi *= 100 @@ -149,17 +148,17 @@ class UltimateOscillator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - window1: int = 7, - window2: int = 14, - window3: int = 28, - weight1: float = 4.0, - weight2: float = 2.0, - weight3: float = 1.0, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + window1: int = 7, + window2: int = 14, + window3: int = 28, + weight1: float = 4.0, + weight2: float = 2.0, + weight3: float = 1.0, + fillna: bool = False, ): self._high = high self._low = low @@ -183,25 +182,25 @@ def _run(self): min_periods_m = 0 if self._fillna else self._window2 min_periods_len = 0 if self._fillna else self._window3 avg_s = ( - buying_pressure.rolling(self._window1, min_periods=min_periods_s).sum() - / true_range.rolling(self._window1, min_periods=min_periods_s).sum() + buying_pressure.rolling(self._window1, min_periods=min_periods_s).sum() + / true_range.rolling(self._window1, min_periods=min_periods_s).sum() ) avg_m = ( - buying_pressure.rolling(self._window2, min_periods=min_periods_m).sum() - / true_range.rolling(self._window2, min_periods=min_periods_m).sum() + buying_pressure.rolling(self._window2, min_periods=min_periods_m).sum() + / true_range.rolling(self._window2, min_periods=min_periods_m).sum() ) avg_l = ( - buying_pressure.rolling(self._window3, min_periods=min_periods_len).sum() - / true_range.rolling(self._window3, min_periods=min_periods_len).sum() + buying_pressure.rolling(self._window3, min_periods=min_periods_len).sum() + / true_range.rolling(self._window3, min_periods=min_periods_len).sum() ) self._uo = ( - 100.0 - * ( - (self._weight1 * avg_s) - + (self._weight2 * avg_m) - + (self._weight3 * avg_l) - ) - / (self._weight1 + self._weight2 + self._weight3) + 100.0 + * ( + (self._weight1 * avg_s) + + (self._weight2 * avg_m) + + (self._weight3 * avg_l) + ) + / (self._weight1 + self._weight2 + self._weight3) ) def ultimate_oscillator(self) -> pd.Series: @@ -234,13 +233,13 @@ class StochasticOscillator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - window: int = 14, - smooth_window: int = 3, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + window: int = 14, + smooth_window: int = 3, + fillna: bool = False, ): self._close = close self._high = high @@ -300,12 +299,12 @@ class KAMAIndicator(IndicatorMixin): """ def __init__( - self, - close: pd.Series, - window: int = 10, - pow1: int = 2, - pow2: int = 30, - fillna: bool = False, + self, + close: pd.Series, + window: int = 10, + pow1: int = 2, + pow2: int = 30, + fillna: bool = False, ): self._close = close self._window = window @@ -324,11 +323,11 @@ def _run(self): efficiency_ratio = er_num / er_den smoothing_constant = ( - ( - efficiency_ratio * (2.0 / (self._pow1 + 1) - 2.0 / (self._pow2 + 1.0)) - + 2 / (self._pow2 + 1.0) - ) - ** 2.0 + ( + efficiency_ratio * (2.0 / (self._pow1 + 1) - 2.0 / (self._pow2 + 1.0)) + + 2 / (self._pow2 + 1.0) + ) + ** 2.0 ).values self._kama = np.zeros(smoothing_constant.size) @@ -343,7 +342,7 @@ def _run(self): first_value = False else: self._kama[i] = self._kama[i - 1] + smoothing_constant[i] * ( - close_values[i] - self._kama[i - 1] + close_values[i] - self._kama[i - 1] ) def kama(self) -> pd.Series: @@ -389,9 +388,9 @@ def __init__(self, close: pd.Series, window: int = 12, fillna: bool = False): def _run(self): self._roc = ( - (self._close - self._close.shift(self._window)) - / self._close.shift(self._window) - ) * 100 + (self._close - self._close.shift(self._window)) + / self._close.shift(self._window) + ) * 100 def roc(self) -> pd.Series: """Rate of Change (ROC) @@ -438,12 +437,12 @@ class AwesomeOscillatorIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - window1: int = 5, - window2: int = 34, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + window1: int = 5, + window2: int = 34, + fillna: bool = False, ): self._high = high self._low = low @@ -457,8 +456,8 @@ def _run(self): min_periods_s = 0 if self._fillna else self._window1 min_periods_len = 0 if self._fillna else self._window2 self._ao = ( - median_price.rolling(self._window1, min_periods=min_periods_s).mean() - - median_price.rolling(self._window2, min_periods=min_periods_len).mean() + median_price.rolling(self._window1, min_periods=min_periods_s).mean() + - median_price.rolling(self._window2, min_periods=min_periods_len).mean() ) def awesome_oscillator(self) -> pd.Series: @@ -510,12 +509,12 @@ class WilliamsRIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - lbp: int = 14, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + lbp: int = 14, + fillna: bool = False, ): self._high = high self._low = low @@ -564,12 +563,12 @@ class StochRSIIndicator(IndicatorMixin): """ def __init__( - self, - close: pd.Series, - window: int = 14, - smooth1: int = 3, - smooth2: int = 3, - fillna: bool = False, + self, + close: pd.Series, + window: int = 14, + smooth1: int = 3, + smooth2: int = 3, + fillna: bool = False, ): self._close = close self._window = window @@ -584,7 +583,7 @@ def _run(self): ).rsi() lowest_low_rsi = self._rsi.rolling(self._window).min() self._stochrsi = (self._rsi - lowest_low_rsi) / ( - self._rsi.rolling(self._window).max() - lowest_low_rsi + self._rsi.rolling(self._window).max() - lowest_low_rsi ) self._stochrsi_k = self._stochrsi.rolling(self._smooth1).mean() @@ -633,12 +632,12 @@ class PercentagePriceOscillator(IndicatorMixin): """ def __init__( - self, - close: pd.Series, - window_slow: int = 26, - window_fast: int = 12, - window_sign: int = 9, - fillna: bool = False, + self, + close: pd.Series, + window_slow: int = 26, + window_fast: int = 12, + window_sign: int = 9, + fillna: bool = False, ): self._close = close self._window_slow = window_slow @@ -707,12 +706,12 @@ class PercentageVolumeOscillator(IndicatorMixin): """ def __init__( - self, - volume: pd.Series, - window_slow: int = 26, - window_fast: int = 12, - window_sign: int = 9, - fillna: bool = False, + self, + volume: pd.Series, + window_slow: int = 26, + window_fast: int = 12, + window_sign: int = 9, + fillna: bool = False, ): self._volume = volume self._window_slow = window_slow @@ -807,16 +806,16 @@ def tsi(close, window_slow=25, window_fast=13, fillna=False) -> pd.Series: def ultimate_oscillator( - high, - low, - close, - window1=7, - window2=14, - window3=28, - weight1=4.0, - weight2=2.0, - weight3=1.0, - fillna=False, + high, + low, + close, + window1=7, + window2=14, + window3=28, + weight1=4.0, + weight2=2.0, + weight3=1.0, + fillna=False, ) -> pd.Series: """Ultimate Oscillator @@ -896,7 +895,7 @@ def stoch(high, low, close, window=14, smooth_window=3, fillna=False) -> pd.Seri def stoch_signal( - high, low, close, window=14, smooth_window=3, fillna=False + high, low, close, window=14, smooth_window=3, fillna=False ) -> pd.Series: """Stochastic Oscillator Signal @@ -1070,11 +1069,11 @@ def roc(close: pd.Series, window: int = 12, fillna: bool = False) -> pd.Series: def stochrsi( - close: pd.Series, - window: int = 14, - smooth1: int = 3, - smooth2: int = 3, - fillna: bool = False, + close: pd.Series, + window: int = 14, + smooth1: int = 3, + smooth2: int = 3, + fillna: bool = False, ) -> pd.Series: """Stochastic RSI @@ -1100,11 +1099,11 @@ def stochrsi( def stochrsi_k( - close: pd.Series, - window: int = 14, - smooth1: int = 3, - smooth2: int = 3, - fillna: bool = False, + close: pd.Series, + window: int = 14, + smooth1: int = 3, + smooth2: int = 3, + fillna: bool = False, ) -> pd.Series: """Stochastic RSI %k @@ -1130,11 +1129,11 @@ def stochrsi_k( def stochrsi_d( - close: pd.Series, - window: int = 14, - smooth1: int = 3, - smooth2: int = 3, - fillna: bool = False, + close: pd.Series, + window: int = 14, + smooth1: int = 3, + smooth2: int = 3, + fillna: bool = False, ) -> pd.Series: """Stochastic RSI %d @@ -1160,11 +1159,11 @@ def stochrsi_d( def ppo( - close: pd.Series, - window_slow: int = 26, - window_fast: int = 12, - window_sign: int = 9, - fillna: bool = False, + close: pd.Series, + window_slow: int = 26, + window_fast: int = 12, + window_sign: int = 9, + fillna: bool = False, ) -> pd.Series: """ The Percentage Price Oscillator (PPO) is a momentum oscillator that measures @@ -1191,7 +1190,7 @@ def ppo( def ppo_signal( - close: pd.Series, window_slow=26, window_fast=12, window_sign=9, fillna=False + close: pd.Series, window_slow=26, window_fast=12, window_sign=9, fillna=False ) -> pd.Series: """ The Percentage Price Oscillator (PPO) is a momentum oscillator that measures @@ -1218,11 +1217,11 @@ def ppo_signal( def ppo_hist( - close: pd.Series, - window_slow: int = 26, - window_fast: int = 12, - window_sign: int = 9, - fillna: bool = False, + close: pd.Series, + window_slow: int = 26, + window_fast: int = 12, + window_sign: int = 9, + fillna: bool = False, ) -> pd.Series: """ The Percentage Price Oscillator (PPO) is a momentum oscillator that measures @@ -1249,11 +1248,11 @@ def ppo_hist( def pvo( - volume: pd.Series, - window_slow: int = 26, - window_fast: int = 12, - window_sign: int = 9, - fillna: bool = False, + volume: pd.Series, + window_slow: int = 26, + window_fast: int = 12, + window_sign: int = 9, + fillna: bool = False, ) -> pd.Series: """ The Percentage Volume Oscillator (PVO) is a momentum oscillator for volume. @@ -1283,11 +1282,11 @@ def pvo( def pvo_signal( - volume: pd.Series, - window_slow: int = 26, - window_fast: int = 12, - window_sign: int = 9, - fillna: bool = False, + volume: pd.Series, + window_slow: int = 26, + window_fast: int = 12, + window_sign: int = 9, + fillna: bool = False, ) -> pd.Series: """ The Percentage Volume Oscillator (PVO) is a momentum oscillator for volume. @@ -1317,11 +1316,11 @@ def pvo_signal( def pvo_hist( - volume: pd.Series, - window_slow: int = 26, - window_fast: int = 12, - window_sign: int = 9, - fillna: bool = False, + volume: pd.Series, + window_slow: int = 26, + window_fast: int = 12, + window_sign: int = 9, + fillna: bool = False, ) -> pd.Series: """ The Percentage Volume Oscillator (PVO) is a momentum oscillator for volume. diff --git a/ta/others.py b/ta/others.py index 0cb43a57..a8e37d8c 100644 --- a/ta/others.py +++ b/ta/others.py @@ -26,8 +26,8 @@ def __init__(self, close: pd.Series, fillna: bool = False): def _run(self): self._dr = ( - self._close / self._close.shift(1, fill_value=self._close.mean()) - ) - 1 + self._close / self._close.shift(1, fill_value=self._close.mean()) + ) - 1 self._dr *= 100 def daily_return(self) -> pd.Series: diff --git a/ta/trend.py b/ta/trend.py index 4c596939..d07d7462 100644 --- a/ta/trend.py +++ b/ta/trend.py @@ -9,6 +9,7 @@ import pandas as pd from ta.utils import IndicatorMixin, _ema, _get_min_max, _sma +from ta.volatility import AverageTrueRange class AroonIndicator(IndicatorMixin): @@ -90,12 +91,12 @@ class MACD(IndicatorMixin): """ def __init__( - self, - close: pd.Series, - window_slow: int = 26, - window_fast: int = 12, - window_sign: int = 9, - fillna: bool = False, + self, + close: pd.Series, + window_slow: int = 26, + window_fast: int = 12, + window_sign: int = 9, + fillna: bool = False, ): self._close = close self._window_slow = window_slow @@ -295,12 +296,12 @@ class MassIndex(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - window_fast: int = 9, - window_slow: int = 25, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + window_fast: int = 9, + window_slow: int = 25, + fillna: bool = False, ): self._high = high self._low = low @@ -345,14 +346,14 @@ class IchimokuIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - window1: int = 9, - window2: int = 26, - window3: int = 52, - visual: bool = False, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + window1: int = 9, + window2: int = 26, + window3: int = 52, + visual: bool = False, + fillna: bool = False, ): self._high = high self._low = low @@ -367,12 +368,12 @@ def _run(self): min_periods_n1 = 0 if self._fillna else self._window1 min_periods_n2 = 0 if self._fillna else self._window2 self._conv = 0.5 * ( - self._high.rolling(self._window1, min_periods=min_periods_n1).max() - + self._low.rolling(self._window1, min_periods=min_periods_n1).min() + self._high.rolling(self._window1, min_periods=min_periods_n1).max() + + self._low.rolling(self._window1, min_periods=min_periods_n1).min() ) self._base = 0.5 * ( - self._high.rolling(self._window2, min_periods=min_periods_n2).max() - + self._low.rolling(self._window2, min_periods=min_periods_n2).min() + self._high.rolling(self._window2, min_periods=min_periods_n2).max() + + self._low.rolling(self._window2, min_periods=min_periods_n2).min() ) def ichimoku_conversion_line(self) -> pd.Series: @@ -417,8 +418,8 @@ def ichimoku_b(self) -> pd.Series: pandas.Series: New feature generated. """ spanb = 0.5 * ( - self._high.rolling(self._window3, min_periods=0).max() - + self._low.rolling(self._window3, min_periods=0).min() + self._high.rolling(self._window3, min_periods=0).max() + + self._low.rolling(self._window3, min_periods=0).min() ) spanb = ( spanb.shift(self._window2, fill_value=spanb.mean()) @@ -454,18 +455,18 @@ class KSTIndicator(IndicatorMixin): """ def __init__( - self, - close: pd.Series, - roc1: int = 10, - roc2: int = 15, - roc3: int = 20, - roc4: int = 30, - window1: int = 10, - window2: int = 10, - window3: int = 10, - window4: int = 15, - nsig: int = 9, - fillna: bool = False, + self, + close: pd.Series, + roc1: int = 10, + roc2: int = 15, + roc3: int = 20, + roc4: int = 30, + window1: int = 10, + window2: int = 10, + window3: int = 10, + window4: int = 15, + nsig: int = 9, + fillna: bool = False, ): self._close = close self._r1 = roc1 @@ -487,47 +488,47 @@ def _run(self): min_periods_n4 = 0 if self._fillna else self._window4 rocma1 = ( ( - ( - self._close - - self._close.shift(self._r1, fill_value=self._close.mean()) - ) - / self._close.shift(self._r1, fill_value=self._close.mean()) + ( + self._close + - self._close.shift(self._r1, fill_value=self._close.mean()) + ) + / self._close.shift(self._r1, fill_value=self._close.mean()) ) - .rolling(self._window1, min_periods=min_periods_n1) - .mean() + .rolling(self._window1, min_periods=min_periods_n1) + .mean() ) rocma2 = ( ( - ( - self._close - - self._close.shift(self._r2, fill_value=self._close.mean()) - ) - / self._close.shift(self._r2, fill_value=self._close.mean()) + ( + self._close + - self._close.shift(self._r2, fill_value=self._close.mean()) + ) + / self._close.shift(self._r2, fill_value=self._close.mean()) ) - .rolling(self._window2, min_periods=min_periods_n2) - .mean() + .rolling(self._window2, min_periods=min_periods_n2) + .mean() ) rocma3 = ( ( - ( - self._close - - self._close.shift(self._r3, fill_value=self._close.mean()) - ) - / self._close.shift(self._r3, fill_value=self._close.mean()) + ( + self._close + - self._close.shift(self._r3, fill_value=self._close.mean()) + ) + / self._close.shift(self._r3, fill_value=self._close.mean()) ) - .rolling(self._window3, min_periods=min_periods_n3) - .mean() + .rolling(self._window3, min_periods=min_periods_n3) + .mean() ) rocma4 = ( ( - ( - self._close - - self._close.shift(self._r4, fill_value=self._close.mean()) - ) - / self._close.shift(self._r4, fill_value=self._close.mean()) + ( + self._close + - self._close.shift(self._r4, fill_value=self._close.mean()) + ) + / self._close.shift(self._r4, fill_value=self._close.mean()) ) - .rolling(self._window4, min_periods=min_periods_n4) - .mean() + .rolling(self._window4, min_periods=min_periods_n4) + .mean() ) self._kst = 100 * (rocma1 + 2 * rocma2 + 3 * rocma3 + 4 * rocma4) self._kst_sig = self._kst.rolling(self._nsig, min_periods=0).mean() @@ -588,10 +589,10 @@ def __init__(self, close: pd.Series, window: int = 20, fillna: bool = False): def _run(self): min_periods = 0 if self._fillna else self._window self._dpo = ( - self._close.shift( - int((0.5 * self._window) + 1), fill_value=self._close.mean() - ) - - self._close.rolling(self._window, min_periods=min_periods).mean() + self._close.shift( + int((0.5 * self._window) + 1), fill_value=self._close.mean() + ) + - self._close.rolling(self._window, min_periods=min_periods).mean() ) def dpo(self) -> pd.Series: @@ -625,13 +626,13 @@ class CCIIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - window: int = 20, - constant: float = 0.015, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + window: int = 20, + constant: float = 0.015, + fillna: bool = False, ): self._high = high self._low = low @@ -648,14 +649,14 @@ def _mad(x): min_periods = 0 if self._fillna else self._window typical_price = (self._high + self._low + self._close) / 3.0 self._cci = ( - typical_price - - typical_price.rolling(self._window, min_periods=min_periods).mean() - ) / ( - self._constant - * typical_price.rolling(self._window, min_periods=min_periods).apply( - _mad, True - ) - ) + typical_price + - typical_price.rolling(self._window, min_periods=min_periods).mean() + ) / ( + self._constant + * typical_price.rolling(self._window, min_periods=min_periods).apply( + _mad, True + ) + ) def cci(self) -> pd.Series: """Commodity Channel Index (CCI) @@ -693,12 +694,12 @@ class ADXIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - window: int = 14, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + window: int = 14, + fillna: bool = False, ): self._high = high self._low = low @@ -718,14 +719,14 @@ def _run(self): self._trs_initial = np.zeros(self._window - 1) self._trs = np.zeros(len(self._close) - (self._window - 1)) - self._trs[0] = diff_directional_movement.dropna()[0 : self._window].sum() + self._trs[0] = diff_directional_movement.dropna()[0: self._window].sum() diff_directional_movement = diff_directional_movement.reset_index(drop=True) for i in range(1, len(self._trs) - 1): self._trs[i] = ( - self._trs[i - 1] - - (self._trs[i - 1] / float(self._window)) - + diff_directional_movement[self._window + i] + self._trs[i - 1] + - (self._trs[i - 1] / float(self._window)) + + diff_directional_movement[self._window + i] ) diff_up = self._high - self._high.shift(1) @@ -734,27 +735,27 @@ def _run(self): neg = abs(((diff_down > diff_up) & (diff_down > 0)) * diff_down) self._dip = np.zeros(len(self._close) - (self._window - 1)) - self._dip[0] = pos.dropna()[0 : self._window].sum() + self._dip[0] = pos.dropna()[0: self._window].sum() pos = pos.reset_index(drop=True) for i in range(1, len(self._dip) - 1): self._dip[i] = ( - self._dip[i - 1] - - (self._dip[i - 1] / float(self._window)) - + pos[self._window + i] + self._dip[i - 1] + - (self._dip[i - 1] / float(self._window)) + + pos[self._window + i] ) self._din = np.zeros(len(self._close) - (self._window - 1)) - self._din[0] = neg.dropna()[0 : self._window].sum() + self._din[0] = neg.dropna()[0: self._window].sum() neg = neg.reset_index(drop=True) for i in range(1, len(self._din) - 1): self._din[i] = ( - self._din[i - 1] - - (self._din[i - 1] / float(self._window)) - + neg[self._window + i] + self._din[i - 1] + - (self._din[i - 1] / float(self._window)) + + neg[self._window + i] ) def adx(self) -> pd.Series: @@ -774,12 +775,12 @@ def adx(self) -> pd.Series: directional_index = 100 * np.abs((dip - din) / (dip + din)) adx_series = np.zeros(len(self._trs)) - adx_series[self._window] = directional_index[0 : self._window].mean() + adx_series[self._window] = directional_index[0: self._window].mean() for i in range(self._window + 1, len(adx_series)): adx_series[i] = ( - (adx_series[i - 1] * (self._window - 1)) + directional_index[i - 1] - ) / float(self._window) + (adx_series[i - 1] * (self._window - 1)) + directional_index[i - 1] + ) / float(self._window) adx_series = np.concatenate((self._trs_initial, adx_series), axis=0) adx_series = pd.Series(data=adx_series, index=self._close.index) @@ -836,12 +837,12 @@ class VortexIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - window: int = 14, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + window: int = 14, + fillna: bool = False, ): self._high = high self._low = low @@ -910,13 +911,13 @@ class PSARIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - step: float = 0.02, - max_step: float = 0.20, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + step: float = 0.02, + max_step: float = 0.20, + fillna: bool = False, ): self._high = high self._low = low @@ -944,7 +945,7 @@ def _run(self): # noqa if up_trend: self._psar.iloc[i] = self._psar.iloc[i - 1] + ( - acceleration_factor * (up_trend_high - self._psar.iloc[i - 1]) + acceleration_factor * (up_trend_high - self._psar.iloc[i - 1]) ) if min_low < self._psar.iloc[i]: @@ -967,7 +968,7 @@ def _run(self): # noqa self._psar.iloc[i] = low1 else: self._psar.iloc[i] = self._psar.iloc[i - 1] - ( - acceleration_factor * (self._psar.iloc[i - 1] - down_trend_low) + acceleration_factor * (self._psar.iloc[i - 1] - down_trend_low) ) if max_high > self._psar.iloc[i]: @@ -1071,14 +1072,14 @@ class STCIndicator(IndicatorMixin): """ def __init__( - self, - close: pd.Series, - window_slow: int = 50, - window_fast: int = 23, - cycle: int = 10, - smooth1: int = 3, - smooth2: int = 3, - fillna: bool = False, + self, + close: pd.Series, + window_slow: int = 50, + window_fast: int = 23, + cycle: int = 10, + smooth1: int = 3, + smooth2: int = 3, + fillna: bool = False, ): self._close = close self._window_slow = window_slow @@ -1090,7 +1091,6 @@ def __init__( self._run() def _run(self): - _emafast = _ema(self._close, self._window_fast, self._fillna) _emaslow = _ema(self._close, self._window_slow, self._fillna) _macd = _emafast - _emaslow @@ -1460,16 +1460,16 @@ def dpo(close, window=20, fillna=False): def kst( - close, - roc1=10, - roc2=15, - roc3=20, - roc4=30, - window1=10, - window2=10, - window3=10, - window4=15, - fillna=False, + close, + roc1=10, + roc2=15, + roc3=20, + roc4=30, + window1=10, + window2=10, + window3=10, + window4=15, + fillna=False, ): """KST Oscillator (KST) @@ -1511,7 +1511,7 @@ def kst( def stc( - close, window_slow=50, window_fast=23, cycle=10, smooth1=3, smooth2=3, fillna=False + close, window_slow=50, window_fast=23, cycle=10, smooth1=3, smooth2=3, fillna=False ): """Schaff Trend Cycle (STC) @@ -1548,17 +1548,17 @@ def stc( def kst_sig( - close, - roc1=10, - roc2=15, - roc3=20, - roc4=30, - window1=10, - window2=10, - window3=10, - window4=15, - nsig=9, - fillna=False, + close, + roc1=10, + roc2=15, + roc3=20, + roc4=30, + window1=10, + window2=10, + window3=10, + window4=15, + nsig=9, + fillna=False, ): """KST Oscillator (KST Signal) @@ -1601,7 +1601,7 @@ def kst_sig( def ichimoku_conversion_line( - high, low, window1=9, window2=26, visual=False, fillna=False + high, low, window1=9, window2=26, visual=False, fillna=False ) -> pd.Series: """Tenkan-sen (Conversion Line) @@ -1632,7 +1632,7 @@ def ichimoku_conversion_line( def ichimoku_base_line( - high, low, window1=9, window2=26, visual=False, fillna=False + high, low, window1=9, window2=26, visual=False, fillna=False ) -> pd.Series: """Kijun-sen (Base Line) @@ -1855,3 +1855,139 @@ def psar_down_indicator(high, low, close, step=0.02, max_step=0.20, fillna=False high=high, low=low, close=close, step=step, max_step=max_step, fillna=fillna ) return indicator.psar_down_indicator() + + +class SuperTrendIndicator(object): + """ + + Supertrend (ST) + """ + # code from pandas-ta + close: pd.Series + high: pd.Series + low: pd.Series + + def __init__(self, + close: pd.Series, + high: pd.Series, + low: pd.Series, + multiplier: float = 3.0, + length: int = 10): + self.close = close + self.high = high + self.low = low + self.multiplier: float = float(multiplier) if multiplier and multiplier > 0 else 3.0 + self.length = int(length) if length and length > 0 else 7 + + def get_supertrend(self) -> pd.Series: + return self.get_all_ST()['ST'] + + def get_supertrend_upper(self) -> pd.Series: + return self.get_all_ST()['ST_upper'] + + def get_supertrend_lower(self) -> pd.Series: + return self.get_all_ST()['ST_lower'] + + def get_supertrend_strategy_returns(self) -> pd.Series: + """ + + :return: pd.Series with 1 or -1 (buy, sell) + """ + return self.get_all_ST()['ST_strategy'] + + def get_all_ST(self) -> pd.DataFrame: + """ + + ST Indicator, trading predictions, ST high/low + """ + m = self.close.size + dir_, trend = [1] * m, [0] * m + long, short = [np.NaN] * m, [np.NaN] * m + ATR = AverageTrueRange(self.high, self.low, self.close, self.length) + + hl2_ = (self.high + self.low) / 2 + matr = ATR.average_true_range() * self.multiplier + upperband = hl2_ + matr + lowerband = hl2_ - matr + + for i in range(1, m): + if self.close.iloc[i] > upperband.iloc[i - 1]: + dir_[i] = 1 + elif self.close.iloc[i] < lowerband.iloc[i - 1]: + dir_[i] = -1 + else: + dir_[i] = dir_[i - 1] + if dir_[i] > 0 and lowerband.iloc[i] < lowerband.iloc[i - 1]: + lowerband.iloc[i] = lowerband.iloc[i - 1] + if dir_[i] < 0 and upperband.iloc[i] > upperband.iloc[i - 1]: + upperband.iloc[i] = upperband.iloc[i - 1] + + if dir_[i] > 0: + trend[i] = long[i] = lowerband.iloc[i] + else: + trend[i] = short[i] = upperband.iloc[i] + + # Prepare DataFrame to return + df = pd.DataFrame( + { + f"ST": trend, + f"ST_strategy": dir_, + f"ST_lower": long, + f"ST_upper": short, + }, + index=self.close.index + ) + + return df + + +def supertrend_indicator(close: pd.Series, + high: pd.Series, + low: pd.Series, + multiplier: float = 3.0, + length: int = 10) -> pd.Series: + ST = SuperTrendIndicator(close=close, + high=high, + low=low, + multiplier=multiplier, + length=length) + return ST.get_supertrend() + + +def supertrend_strategy(close: pd.Series, + high: pd.Series, + low: pd.Series, + multiplier: float = 3.0, + length: int = 10) -> pd.Series: + ST = SuperTrendIndicator(close=close, + high=high, + low=low, + multiplier=multiplier, + length=length) + return ST.get_supertrend_strategy_returns() + + +def supertrend_lower(close: pd.Series, + high: pd.Series, + low: pd.Series, + multiplier: float = 3.0, + length: int = 10) -> pd.Series: + ST = SuperTrendIndicator(close=close, + high=high, + low=low, + multiplier=multiplier, + length=length) + return ST.get_supertrend_lower() + + +def supertrend_upper(close: pd.Series, + high: pd.Series, + low: pd.Series, + multiplier: float = 3.0, + length: int = 10) -> pd.Series: + ST = SuperTrendIndicator(close=close, + high=high, + low=low, + multiplier=multiplier, + length=length) + return ST.get_supertrend_upper() diff --git a/ta/utils.py b/ta/utils.py index 11dd4e8c..e0bf338f 100644 --- a/ta/utils.py +++ b/ta/utils.py @@ -37,7 +37,7 @@ def _check_fillna(self, series: pd.Series, value: int = 0) -> pd.Series: @staticmethod def _true_range( - high: pd.Series, low: pd.Series, prev_close: pd.Series + high: pd.Series, low: pd.Series, prev_close: pd.Series ) -> pd.Series: tr1 = high - low tr2 = (high - prev_close).abs() diff --git a/ta/volatility.py b/ta/volatility.py index 0506f90c..959c0b89 100644 --- a/ta/volatility.py +++ b/ta/volatility.py @@ -29,12 +29,12 @@ class AverageTrueRange(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - window: int = 14, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + window: int = 14, + fillna: bool = False, ): self._high = high self._low = low @@ -47,7 +47,7 @@ def _run(self): close_shift = self._close.shift(1) true_range = self._true_range(self._high, self._low, close_shift) atr = np.zeros(len(self._close)) - atr[self._window - 1] = true_range[0 : self._window].mean() + atr[self._window - 1] = true_range[0: self._window].mean() for i in range(self._window, len(atr)): atr[i] = (atr[i - 1] * (self._window - 1) + true_range.iloc[i]) / float( self._window @@ -77,11 +77,11 @@ class BollingerBands(IndicatorMixin): """ def __init__( - self, - close: pd.Series, - window: int = 20, - window_dev: int = 2, - fillna: bool = False, + self, + close: pd.Series, + window: int = 20, + window_dev: int = 2, + fillna: bool = False, ): self._close = close self._window = window @@ -200,14 +200,14 @@ class KeltnerChannel(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - window: int = 20, - window_atr: int = 10, - fillna: bool = False, - original_version: bool = True, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + window: int = 20, + window_atr: int = 10, + fillna: bool = False, + original_version: bool = True, ): self._high = high self._low = low @@ -223,18 +223,18 @@ def _run(self): if self._original_version: self._tp = ( ((self._high + self._low + self._close) / 3.0) - .rolling(self._window, min_periods=min_periods) - .mean() + .rolling(self._window, min_periods=min_periods) + .mean() ) self._tp_high = ( (((4 * self._high) - (2 * self._low) + self._close) / 3.0) - .rolling(self._window, min_periods=0) - .mean() + .rolling(self._window, min_periods=0) + .mean() ) self._tp_low = ( (((-2 * self._high) + (4 * self._low) + self._close) / 3.0) - .rolling(self._window, min_periods=0) - .mean() + .rolling(self._window, min_periods=0) + .mean() ) else: self._tp = self._close.ewm( @@ -340,13 +340,13 @@ class DonchianChannel(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - window: int = 20, - offset: int = 0, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + window: int = 20, + offset: int = 0, + fillna: bool = False, ): self._offset = offset self._close = close @@ -639,7 +639,7 @@ def bollinger_lband_indicator(close, window=20, window_dev=2, fillna=False): def keltner_channel_mband( - high, low, close, window=20, window_atr=10, fillna=False, original_version=True + high, low, close, window=20, window_atr=10, fillna=False, original_version=True ): """Keltner channel (KC) @@ -674,7 +674,7 @@ def keltner_channel_mband( def keltner_channel_hband( - high, low, close, window=20, window_atr=10, fillna=False, original_version=True + high, low, close, window=20, window_atr=10, fillna=False, original_version=True ): """Keltner channel (KC) @@ -709,7 +709,7 @@ def keltner_channel_hband( def keltner_channel_lband( - high, low, close, window=20, window_atr=10, fillna=False, original_version=True + high, low, close, window=20, window_atr=10, fillna=False, original_version=True ): """Keltner channel (KC) @@ -744,7 +744,7 @@ def keltner_channel_lband( def keltner_channel_wband( - high, low, close, window=20, window_atr=10, fillna=False, original_version=True + high, low, close, window=20, window_atr=10, fillna=False, original_version=True ): """Keltner Channel Band Width @@ -777,7 +777,7 @@ def keltner_channel_wband( def keltner_channel_pband( - high, low, close, window=20, window_atr=10, fillna=False, original_version=True + high, low, close, window=20, window_atr=10, fillna=False, original_version=True ): """Keltner Channel Percentage Band @@ -810,7 +810,7 @@ def keltner_channel_pband( def keltner_channel_hband_indicator( - high, low, close, window=20, window_atr=10, fillna=False, original_version=True + high, low, close, window=20, window_atr=10, fillna=False, original_version=True ): """Keltner Channel High Band Indicator (KC) @@ -846,7 +846,7 @@ def keltner_channel_hband_indicator( def keltner_channel_lband_indicator( - high, low, close, window=20, window_atr=10, fillna=False, original_version=True + high, low, close, window=20, window_atr=10, fillna=False, original_version=True ): """Keltner Channel Low Band Indicator (KC) diff --git a/ta/volume.py b/ta/volume.py index 7655ed79..8e4b3175 100644 --- a/ta/volume.py +++ b/ta/volume.py @@ -28,12 +28,12 @@ class AccDistIndexIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - volume: pd.Series, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + volume: pd.Series, + fillna: bool = False, ): self._high = high self._low = low @@ -44,7 +44,7 @@ def __init__( def _run(self): clv = ((self._close - self._low) - (self._high - self._close)) / ( - self._high - self._low + self._high - self._low ) clv = clv.fillna(0.0) # float division by zero adi = clv * self._volume @@ -111,13 +111,13 @@ class ChaikinMoneyFlowIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - volume: pd.Series, - window: int = 20, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + volume: pd.Series, + window: int = 20, + fillna: bool = False, ): self._high = high self._low = low @@ -129,14 +129,14 @@ def __init__( def _run(self): mfv = ((self._close - self._low) - (self._high - self._close)) / ( - self._high - self._low + self._high - self._low ) mfv = mfv.fillna(0.0) # float division by zero mfv *= self._volume min_periods = 0 if self._fillna else self._window self._cmf = ( - mfv.rolling(self._window, min_periods=min_periods).sum() - / self._volume.rolling(self._window, min_periods=min_periods).sum() + mfv.rolling(self._window, min_periods=min_periods).sum() + / self._volume.rolling(self._window, min_periods=min_periods).sum() ) def chaikin_money_flow(self) -> pd.Series: @@ -166,11 +166,11 @@ class ForceIndexIndicator(IndicatorMixin): """ def __init__( - self, - close: pd.Series, - volume: pd.Series, - window: int = 13, - fillna: bool = False, + self, + close: pd.Series, + volume: pd.Series, + window: int = 13, + fillna: bool = False, ): self._close = close self._volume = volume @@ -209,12 +209,12 @@ class EaseOfMovementIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - volume: pd.Series, - window: int = 14, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + volume: pd.Series, + window: int = 14, + fillna: bool = False, ): self._high = high self._low = low @@ -225,9 +225,9 @@ def __init__( def _run(self): self._emv = ( - (self._high.diff(1) + self._low.diff(1)) - * (self._high - self._low) - / (2 * self._volume) + (self._high.diff(1) + self._low.diff(1)) + * (self._high - self._low) + / (2 * self._volume) ) self._emv *= 100000000 @@ -275,8 +275,8 @@ def __init__(self, close: pd.Series, volume: pd.Series, fillna: bool = False): def _run(self): vpt = self._volume * ( - (self._close - self._close.shift(1, fill_value=self._close.mean())) - / self._close.shift(1, fill_value=self._close.mean()) + (self._close - self._close.shift(1, fill_value=self._close.mean())) + / self._close.shift(1, fill_value=self._close.mean()) ) self._vpt = vpt.shift(1, fill_value=vpt.mean()) + vpt @@ -352,13 +352,13 @@ class MFIIndicator(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - volume: pd.Series, - window: int = 14, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + volume: pd.Series, + window: int = 14, + fillna: bool = False, ): self._high = high self._low = low @@ -429,13 +429,13 @@ class VolumeWeightedAveragePrice(IndicatorMixin): """ def __init__( - self, - high: pd.Series, - low: pd.Series, - close: pd.Series, - volume: pd.Series, - window: int = 14, - fillna: bool = False, + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + volume: pd.Series, + window: int = 14, + fillna: bool = False, ): self._high = high self._low = low @@ -705,12 +705,12 @@ def money_flow_index(high, low, close, volume, window=14, fillna=False): def volume_weighted_average_price( - high: pd.Series, - low: pd.Series, - close: pd.Series, - volume: pd.Series, - window: int = 14, - fillna: bool = False, + high: pd.Series, + low: pd.Series, + close: pd.Series, + volume: pd.Series, + window: int = 14, + fillna: bool = False, ): """Volume Weighted Average Price (VWAP) diff --git a/ta/wrapper.py b/ta/wrapper.py index fefd8591..2a0fce79 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -62,13 +62,13 @@ def add_volume_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - volume: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + volume: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add volume technical analysis features to dataframe. @@ -146,12 +146,12 @@ def add_volume_ta( def add_volatility_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add volatility technical analysis features to dataframe. @@ -215,12 +215,12 @@ def add_volatility_ta( def add_trend_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add trend technical analysis features to dataframe. @@ -381,13 +381,13 @@ def add_trend_ta( def add_momentum_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - volume: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + volume: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add trend technical analysis features to dataframe. @@ -488,7 +488,7 @@ def add_momentum_ta( def add_others_ta( - df: pd.DataFrame, close: str, fillna: bool = False, colprefix: str = "" + df: pd.DataFrame, close: str, fillna: bool = False, colprefix: str = "" ) -> pd.DataFrame: """Add others analysis features to dataframe. @@ -520,14 +520,14 @@ def add_others_ta( def add_all_ta_features( - df: pd.DataFrame, - open: str, # noqa - high: str, - low: str, - close: str, - volume: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + open: str, # noqa + high: str, + low: str, + close: str, + volume: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add all technical analysis features to dataframe. diff --git a/test/__init__.py b/test/__init__.py index 2310ac1e..3d85297f 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,42 +1,4 @@ from test.integration.wrapper import TestWrapper -from test.unit.momentum import ( - TestKAMAIndicator, - TestPercentagePriceOscillator, - TestPercentageVolumeOscillator, - TestRateOfChangeIndicator, - TestRSIIndicator, - TestStochasticOscillator, - TestStochRSIIndicator, - TestTSIIndicator, - TestUltimateOscillator, - TestWilliamsRIndicator, -) -from test.unit.trend import ( - TestADXIndicator, - TestCCIIndicator, - TestMACDIndicator, - TestPSARIndicator, - TestSTCIndicator, - TestVortexIndicator, - TestWMAIndicator, -) -from test.unit.volatility import ( - TestAverageTrueRange, - TestAverageTrueRange2, - TestBollingerBands, - TestDonchianChannel, - TestDonchianChannel2, - TestKeltnerChannel, - TestUlcerIndex, -) -from test.unit.volume import ( - TestAccDistIndexIndicator, - TestEaseOfMovementIndicator, - TestForceIndexIndicator, - TestMFIIndicator, - TestOnBalanceVolumeIndicator, - TestVolumeWeightedAveragePrice, -) __all__ = [ "TestWrapper", diff --git a/test/integration/wrapper.py b/test/integration/wrapper.py index 0f1490cb..e5b16aa6 100644 --- a/test/integration/wrapper.py +++ b/test/integration/wrapper.py @@ -1,12 +1,10 @@ import unittest import pandas as pd - import ta class TestWrapper(unittest.TestCase): - _filename = "test/data/datas.csv" @classmethod @@ -57,10 +55,10 @@ def test_general(self): ta_cols = [c for c in df_with_ta.columns if c not in input_cols] self.assertTrue( df_with_ta[ta_cols] - .apply(lambda series: pd.to_numeric(series, errors="coerce")) - .notnull() - .all() - .all() + .apply(lambda series: pd.to_numeric(series, errors="coerce")) + .notnull() + .all() + .all() ) diff --git a/test/unit/momentum.py b/test/unit/momentum.py index e1a3c836..0a0bf294 100644 --- a/test/unit/momentum.py +++ b/test/unit/momentum.py @@ -1,7 +1,6 @@ import unittest import pandas as pd - from ta.momentum import ( KAMAIndicator, PercentagePriceOscillator, diff --git a/test/unit/trend.py b/test/unit/trend.py index 09ccae58..2aa128a8 100644 --- a/test/unit/trend.py +++ b/test/unit/trend.py @@ -1,7 +1,6 @@ import unittest import pandas as pd - from ta.trend import ( MACD, ADXIndicator, @@ -374,7 +373,6 @@ def test_stc2(self): class TestWMAIndicator(unittest.TestCase): - _filename = "test/data/cs-wma.csv" @classmethod diff --git a/test/unit/volatility.py b/test/unit/volatility.py index 92462c84..0849349e 100644 --- a/test/unit/volatility.py +++ b/test/unit/volatility.py @@ -1,7 +1,6 @@ import unittest import pandas as pd - from ta.volatility import ( AverageTrueRange, BollingerBands, diff --git a/test/unit/volume.py b/test/unit/volume.py index ad48fdde..51cc78fa 100644 --- a/test/unit/volume.py +++ b/test/unit/volume.py @@ -1,7 +1,6 @@ import unittest import pandas as pd - from ta.volume import ( AccDistIndexIndicator, EaseOfMovementIndicator, From 992da38acbd39d2701bd73ea7425749527ddb8d1 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 15:42:23 +0200 Subject: [PATCH 02/18] add all ta ST --- ta/wrapper.py | 80 +++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/ta/wrapper.py b/ta/wrapper.py index 2a0fce79..de59b0e8 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -40,6 +40,7 @@ STCIndicator, TRIXIndicator, VortexIndicator, + SuperTrendIndicator, ) from ta.volatility import ( AverageTrueRange, @@ -62,13 +63,13 @@ def add_volume_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - volume: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + volume: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add volume technical analysis features to dataframe. @@ -146,12 +147,12 @@ def add_volume_ta( def add_volatility_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add volatility technical analysis features to dataframe. @@ -215,12 +216,12 @@ def add_volatility_ta( def add_trend_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add trend technical analysis features to dataframe. @@ -237,6 +238,7 @@ def add_trend_ta( """ # MACD + indicator_macd = MACD( close=df[close], window_slow=26, window_fast=12, window_sign=9, fillna=fillna ) @@ -377,17 +379,25 @@ def add_trend_ta( fillna=fillna, ).stc() + ST = SuperTrendIndicator(close=df[close], + low=df[low], + high=df[high]) + df[f'{colprefix}ST'] = ST.get_supertrend() + df[f'{colprefix}ST_strategy'] = ST.get_supertrend_strategy_returns() + + + return df def add_momentum_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - volume: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + volume: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add trend technical analysis features to dataframe. @@ -488,7 +498,7 @@ def add_momentum_ta( def add_others_ta( - df: pd.DataFrame, close: str, fillna: bool = False, colprefix: str = "" + df: pd.DataFrame, close: str, fillna: bool = False, colprefix: str = "" ) -> pd.DataFrame: """Add others analysis features to dataframe. @@ -520,14 +530,14 @@ def add_others_ta( def add_all_ta_features( - df: pd.DataFrame, - open: str, # noqa - high: str, - low: str, - close: str, - volume: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + open: str, # noqa + high: str, + low: str, + close: str, + volume: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add all technical analysis features to dataframe. From 9a73aae4181e1d632ce3c3ed28d76a25509980e5 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 16:18:49 +0200 Subject: [PATCH 03/18] debug --- ta/wrapper.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ta/wrapper.py b/ta/wrapper.py index de59b0e8..7007476c 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -7,7 +7,7 @@ import pandas as pd -from ta.momentum import ( +from .momentum import ( AwesomeOscillatorIndicator, KAMAIndicator, PercentagePriceOscillator, @@ -20,12 +20,12 @@ UltimateOscillator, WilliamsRIndicator, ) -from ta.others import ( +from .others import ( CumulativeReturnIndicator, DailyLogReturnIndicator, DailyReturnIndicator, ) -from ta.trend import ( +from .trend import ( MACD, ADXIndicator, AroonIndicator, @@ -42,14 +42,14 @@ VortexIndicator, SuperTrendIndicator, ) -from ta.volatility import ( +from .volatility import ( AverageTrueRange, BollingerBands, DonchianChannel, KeltnerChannel, UlcerIndex, ) -from ta.volume import ( +from .volume import ( AccDistIndexIndicator, ChaikinMoneyFlowIndicator, EaseOfMovementIndicator, From 7ad3e54dce1c3c8a4b6ca8ef4e0cba342a1bf317 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 16:36:27 +0200 Subject: [PATCH 04/18] ema debug --- ta/volume.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ta/volume.py b/ta/volume.py index 8e4b3175..fa4ddc2a 100644 --- a/ta/volume.py +++ b/ta/volume.py @@ -9,7 +9,8 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin, _ema +from ta.utils import IndicatorMixin +from ta.utils import ema as _ema class AccDistIndexIndicator(IndicatorMixin): From 029ac865e7f18c04831852227216a11e03955a17 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 16:45:54 +0200 Subject: [PATCH 05/18] debug --- ta/trend.py | 4 ++-- ta/volume.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ta/trend.py b/ta/trend.py index d07d7462..5079970a 100644 --- a/ta/trend.py +++ b/ta/trend.py @@ -8,8 +8,8 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin, _ema, _get_min_max, _sma -from ta.volatility import AverageTrueRange +from .utils import IndicatorMixin, _ema, _get_min_max, _sma +from .volatility import AverageTrueRange class AroonIndicator(IndicatorMixin): diff --git a/ta/volume.py b/ta/volume.py index fa4ddc2a..eca14297 100644 --- a/ta/volume.py +++ b/ta/volume.py @@ -9,8 +9,8 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin -from ta.utils import ema as _ema +from .utils import IndicatorMixin +from .utils import _ema class AccDistIndexIndicator(IndicatorMixin): From c2e7cd528a808d48de0c918e3a3cc176696d767c Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 16:53:25 +0200 Subject: [PATCH 06/18] debug CI --- examples_to_use/all_features_example.py | 1 + .../bollinger_band_features_example.py | 1 + examples_to_use/roc.py | 1 + examples_to_use/volume_features_example.py | 1 + ta/__init__.py | 8 --- ta/momentum.py | 1 + ta/wrapper.py | 72 +++++++++---------- test/__init__.py | 2 - test/integration/wrapper.py | 1 + 9 files changed, 41 insertions(+), 47 deletions(-) diff --git a/examples_to_use/all_features_example.py b/examples_to_use/all_features_example.py index dafd15ed..87afe430 100644 --- a/examples_to_use/all_features_example.py +++ b/examples_to_use/all_features_example.py @@ -2,6 +2,7 @@ this library. """ import pandas as pd + import ta # Load data diff --git a/examples_to_use/bollinger_band_features_example.py b/examples_to_use/bollinger_band_features_example.py index 4a4c4a5c..c6bedfed 100644 --- a/examples_to_use/bollinger_band_features_example.py +++ b/examples_to_use/bollinger_band_features_example.py @@ -1,6 +1,7 @@ """This is a example adding bollinger band features. """ import pandas as pd + import ta # Load data diff --git a/examples_to_use/roc.py b/examples_to_use/roc.py index c6cd5c63..d4ebc79d 100644 --- a/examples_to_use/roc.py +++ b/examples_to_use/roc.py @@ -1,6 +1,7 @@ """This is a example adding volume features. """ import pandas as pd + import ta # Load data diff --git a/examples_to_use/volume_features_example.py b/examples_to_use/volume_features_example.py index e9f0ea04..fd344619 100644 --- a/examples_to_use/volume_features_example.py +++ b/examples_to_use/volume_features_example.py @@ -1,6 +1,7 @@ """This is a example adding volume features. """ import pandas as pd + import ta # Load data diff --git a/ta/__init__.py b/ta/__init__.py index ac190cc1..a2f5b628 100644 --- a/ta/__init__.py +++ b/ta/__init__.py @@ -5,14 +5,6 @@ .. moduleauthor:: Dario Lopez Padial (Bukosabino) """ -from ta.wrapper import ( - add_all_ta_features, - add_momentum_ta, - add_others_ta, - add_trend_ta, - add_volatility_ta, - add_volume_ta, -) __all__ = [ "add_all_ta_features", diff --git a/ta/momentum.py b/ta/momentum.py index c0122908..d9d04833 100644 --- a/ta/momentum.py +++ b/ta/momentum.py @@ -26,6 +26,7 @@ class RSIIndicator(IndicatorMixin): window(int): n period. fillna(bool): if True, fill nan values. """ + def __init__(self, close: pd.Series, window: int = 14, fillna: bool = False): self._close = close self._window = window diff --git a/ta/wrapper.py b/ta/wrapper.py index 7007476c..6bc73c81 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -63,13 +63,13 @@ def add_volume_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - volume: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + volume: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add volume technical analysis features to dataframe. @@ -147,12 +147,12 @@ def add_volume_ta( def add_volatility_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add volatility technical analysis features to dataframe. @@ -216,12 +216,12 @@ def add_volatility_ta( def add_trend_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add trend technical analysis features to dataframe. @@ -385,19 +385,17 @@ def add_trend_ta( df[f'{colprefix}ST'] = ST.get_supertrend() df[f'{colprefix}ST_strategy'] = ST.get_supertrend_strategy_returns() - - return df def add_momentum_ta( - df: pd.DataFrame, - high: str, - low: str, - close: str, - volume: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + high: str, + low: str, + close: str, + volume: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add trend technical analysis features to dataframe. @@ -498,7 +496,7 @@ def add_momentum_ta( def add_others_ta( - df: pd.DataFrame, close: str, fillna: bool = False, colprefix: str = "" + df: pd.DataFrame, close: str, fillna: bool = False, colprefix: str = "" ) -> pd.DataFrame: """Add others analysis features to dataframe. @@ -530,14 +528,14 @@ def add_others_ta( def add_all_ta_features( - df: pd.DataFrame, - open: str, # noqa - high: str, - low: str, - close: str, - volume: str, - fillna: bool = False, - colprefix: str = "", + df: pd.DataFrame, + open: str, # noqa + high: str, + low: str, + close: str, + volume: str, + fillna: bool = False, + colprefix: str = "", ) -> pd.DataFrame: """Add all technical analysis features to dataframe. diff --git a/test/__init__.py b/test/__init__.py index 3d85297f..9290be4b 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,5 +1,3 @@ -from test.integration.wrapper import TestWrapper - __all__ = [ "TestWrapper", "TestKAMAIndicator", diff --git a/test/integration/wrapper.py b/test/integration/wrapper.py index e5b16aa6..9a7be8bf 100644 --- a/test/integration/wrapper.py +++ b/test/integration/wrapper.py @@ -1,6 +1,7 @@ import unittest import pandas as pd + import ta From 69a72361202e912d70995f3cc0a47c51b1553125 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 22:38:10 +0200 Subject: [PATCH 07/18] test --- ta/trend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ta/trend.py b/ta/trend.py index 5079970a..d07d7462 100644 --- a/ta/trend.py +++ b/ta/trend.py @@ -8,8 +8,8 @@ import numpy as np import pandas as pd -from .utils import IndicatorMixin, _ema, _get_min_max, _sma -from .volatility import AverageTrueRange +from ta.utils import IndicatorMixin, _ema, _get_min_max, _sma +from ta.volatility import AverageTrueRange class AroonIndicator(IndicatorMixin): From 451139ac6712e399773d845dc409dc7ba6d55124 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 22:43:00 +0200 Subject: [PATCH 08/18] CI test --- ta/trend.py | 4 ++-- test/integration/wrapper.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ta/trend.py b/ta/trend.py index d07d7462..5079970a 100644 --- a/ta/trend.py +++ b/ta/trend.py @@ -8,8 +8,8 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin, _ema, _get_min_max, _sma -from ta.volatility import AverageTrueRange +from .utils import IndicatorMixin, _ema, _get_min_max, _sma +from .volatility import AverageTrueRange class AroonIndicator(IndicatorMixin): diff --git a/test/integration/wrapper.py b/test/integration/wrapper.py index 9a7be8bf..e5b16aa6 100644 --- a/test/integration/wrapper.py +++ b/test/integration/wrapper.py @@ -1,7 +1,6 @@ import unittest import pandas as pd - import ta From 0b7871e960a6b1ae7b50e1c756216f8b4ae62c3c Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 23:01:56 +0200 Subject: [PATCH 09/18] ta. add --- ta/trend.py | 4 ++-- ta/volume.py | 4 ++-- ta/wrapper.py | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ta/trend.py b/ta/trend.py index 5079970a..d07d7462 100644 --- a/ta/trend.py +++ b/ta/trend.py @@ -8,8 +8,8 @@ import numpy as np import pandas as pd -from .utils import IndicatorMixin, _ema, _get_min_max, _sma -from .volatility import AverageTrueRange +from ta.utils import IndicatorMixin, _ema, _get_min_max, _sma +from ta.volatility import AverageTrueRange class AroonIndicator(IndicatorMixin): diff --git a/ta/volume.py b/ta/volume.py index eca14297..310f0306 100644 --- a/ta/volume.py +++ b/ta/volume.py @@ -9,8 +9,8 @@ import numpy as np import pandas as pd -from .utils import IndicatorMixin -from .utils import _ema +from ta.utils import IndicatorMixin +from ta.utils import _ema class AccDistIndexIndicator(IndicatorMixin): diff --git a/ta/wrapper.py b/ta/wrapper.py index 6bc73c81..b8e343c1 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -7,7 +7,7 @@ import pandas as pd -from .momentum import ( +from ta.momentum import ( AwesomeOscillatorIndicator, KAMAIndicator, PercentagePriceOscillator, @@ -20,12 +20,12 @@ UltimateOscillator, WilliamsRIndicator, ) -from .others import ( +from ta.others import ( CumulativeReturnIndicator, DailyLogReturnIndicator, DailyReturnIndicator, ) -from .trend import ( +from ta.trend import ( MACD, ADXIndicator, AroonIndicator, @@ -42,14 +42,14 @@ VortexIndicator, SuperTrendIndicator, ) -from .volatility import ( +from ta.volatility import ( AverageTrueRange, BollingerBands, DonchianChannel, KeltnerChannel, UlcerIndex, ) -from .volume import ( +from ta.volume import ( AccDistIndexIndicator, ChaikinMoneyFlowIndicator, EaseOfMovementIndicator, From 4344ed9a0aa3c659a814e1b1972829a9685aab82 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Wed, 2 Dec 2020 23:20:52 +0200 Subject: [PATCH 10/18] ci built test --- ta/wrapper.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ta/wrapper.py b/ta/wrapper.py index b8e343c1..6bc73c81 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -7,7 +7,7 @@ import pandas as pd -from ta.momentum import ( +from .momentum import ( AwesomeOscillatorIndicator, KAMAIndicator, PercentagePriceOscillator, @@ -20,12 +20,12 @@ UltimateOscillator, WilliamsRIndicator, ) -from ta.others import ( +from .others import ( CumulativeReturnIndicator, DailyLogReturnIndicator, DailyReturnIndicator, ) -from ta.trend import ( +from .trend import ( MACD, ADXIndicator, AroonIndicator, @@ -42,14 +42,14 @@ VortexIndicator, SuperTrendIndicator, ) -from ta.volatility import ( +from .volatility import ( AverageTrueRange, BollingerBands, DonchianChannel, KeltnerChannel, UlcerIndex, ) -from ta.volume import ( +from .volume import ( AccDistIndexIndicator, ChaikinMoneyFlowIndicator, EaseOfMovementIndicator, From 017a062381acf05c16b9cb32cf145f4169969956 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Thu, 3 Dec 2020 02:06:56 +0200 Subject: [PATCH 11/18] imports debud --- ta/momentum.py | 2 +- ta/others.py | 2 +- ta/trend.py | 4 ++-- ta/volatility.py | 2 +- ta/volume.py | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ta/momentum.py b/ta/momentum.py index d9d04833..a724f3a7 100644 --- a/ta/momentum.py +++ b/ta/momentum.py @@ -8,7 +8,7 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin, _ema +from .utils import IndicatorMixin, _ema class RSIIndicator(IndicatorMixin): diff --git a/ta/others.py b/ta/others.py index a8e37d8c..8862598a 100644 --- a/ta/others.py +++ b/ta/others.py @@ -8,7 +8,7 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin +from .utils import IndicatorMixin class DailyReturnIndicator(IndicatorMixin): diff --git a/ta/trend.py b/ta/trend.py index d07d7462..fa859994 100644 --- a/ta/trend.py +++ b/ta/trend.py @@ -8,8 +8,8 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin, _ema, _get_min_max, _sma -from ta.volatility import AverageTrueRange +from .utils import IndicatorMixin, _ema, _sma, _get_min_max +from .volatility import AverageTrueRange class AroonIndicator(IndicatorMixin): diff --git a/ta/volatility.py b/ta/volatility.py index 959c0b89..7cb03877 100644 --- a/ta/volatility.py +++ b/ta/volatility.py @@ -8,7 +8,7 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin +from .utils import IndicatorMixin class AverageTrueRange(IndicatorMixin): diff --git a/ta/volume.py b/ta/volume.py index 310f0306..eca14297 100644 --- a/ta/volume.py +++ b/ta/volume.py @@ -9,8 +9,8 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin -from ta.utils import _ema +from .utils import IndicatorMixin +from .utils import _ema class AccDistIndexIndicator(IndicatorMixin): From 8077011a69fb2a9163b299e3e6903b010183b9e1 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Thu, 3 Dec 2020 02:09:04 +0200 Subject: [PATCH 12/18] debug imports for circle CI --- ta/volume.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ta/volume.py b/ta/volume.py index eca14297..8616a048 100644 --- a/ta/volume.py +++ b/ta/volume.py @@ -9,8 +9,7 @@ import numpy as np import pandas as pd -from .utils import IndicatorMixin -from .utils import _ema +from .utils import IndicatorMixin, _ema class AccDistIndexIndicator(IndicatorMixin): From 290e94e0ff87574d2409a453d3a5406418c53b3b Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Thu, 3 Dec 2020 02:17:01 +0200 Subject: [PATCH 13/18] imports + readme --- README.md | 1 + ta/wrapper.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 80dac080..acd2edac 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ The library has implemented 42 indicators: * Ichimoku Kinkō Hyō (Ichimoku) * Parabolic Stop And Reverse (Parabolic SAR) * Schaff Trend Cycle (STC) +* SuperTrend (ST) #### Momentum diff --git a/ta/wrapper.py b/ta/wrapper.py index 6bc73c81..22bfbe7d 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -7,7 +7,7 @@ import pandas as pd -from .momentum import ( +from ta.ta.momentum import ( AwesomeOscillatorIndicator, KAMAIndicator, PercentagePriceOscillator, @@ -20,12 +20,12 @@ UltimateOscillator, WilliamsRIndicator, ) -from .others import ( +from ta.ta.others import ( CumulativeReturnIndicator, DailyLogReturnIndicator, DailyReturnIndicator, ) -from .trend import ( +from ta.ta.trend import ( MACD, ADXIndicator, AroonIndicator, @@ -42,14 +42,14 @@ VortexIndicator, SuperTrendIndicator, ) -from .volatility import ( +from ta.ta.volatility import ( AverageTrueRange, BollingerBands, DonchianChannel, KeltnerChannel, UlcerIndex, ) -from .volume import ( +from ta.ta.volume import ( AccDistIndexIndicator, ChaikinMoneyFlowIndicator, EaseOfMovementIndicator, From 5675309d479a9bfea7d59d32bbad663b5ddd1019 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Thu, 3 Dec 2020 02:21:38 +0200 Subject: [PATCH 14/18] ci test --- test/integration/wrapper.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration/wrapper.py b/test/integration/wrapper.py index e5b16aa6..9a7be8bf 100644 --- a/test/integration/wrapper.py +++ b/test/integration/wrapper.py @@ -1,6 +1,7 @@ import unittest import pandas as pd + import ta From d8895804e20d17c585132f58be62510313dcb586 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Thu, 3 Dec 2020 02:24:14 +0200 Subject: [PATCH 15/18] test ci tests --- ta/momentum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ta/momentum.py b/ta/momentum.py index a724f3a7..9c1bd753 100644 --- a/ta/momentum.py +++ b/ta/momentum.py @@ -8,7 +8,7 @@ import numpy as np import pandas as pd -from .utils import IndicatorMixin, _ema +from ta.ta.utils import IndicatorMixin, _ema class RSIIndicator(IndicatorMixin): From ffecdad4299e7957edb9190f3a78a8650697b25f Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Thu, 3 Dec 2020 02:27:17 +0200 Subject: [PATCH 16/18] ci test debug --- ta/others.py | 2 +- ta/trend.py | 4 ++-- ta/volatility.py | 2 +- ta/volume.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ta/others.py b/ta/others.py index 8862598a..3e35627c 100644 --- a/ta/others.py +++ b/ta/others.py @@ -8,7 +8,7 @@ import numpy as np import pandas as pd -from .utils import IndicatorMixin +from ta.ta.utils import IndicatorMixin class DailyReturnIndicator(IndicatorMixin): diff --git a/ta/trend.py b/ta/trend.py index fa859994..7fe64c14 100644 --- a/ta/trend.py +++ b/ta/trend.py @@ -8,8 +8,8 @@ import numpy as np import pandas as pd -from .utils import IndicatorMixin, _ema, _sma, _get_min_max -from .volatility import AverageTrueRange +from ta.ta.utils import IndicatorMixin, _ema, _sma, _get_min_max +from ta.ta.volatility import AverageTrueRange class AroonIndicator(IndicatorMixin): diff --git a/ta/volatility.py b/ta/volatility.py index 7cb03877..8b00e611 100644 --- a/ta/volatility.py +++ b/ta/volatility.py @@ -8,7 +8,7 @@ import numpy as np import pandas as pd -from .utils import IndicatorMixin +from ta.ta.utils import IndicatorMixin class AverageTrueRange(IndicatorMixin): diff --git a/ta/volume.py b/ta/volume.py index 8616a048..87b57416 100644 --- a/ta/volume.py +++ b/ta/volume.py @@ -9,7 +9,7 @@ import numpy as np import pandas as pd -from .utils import IndicatorMixin, _ema +from ta.ta.utils import IndicatorMixin, _ema class AccDistIndexIndicator(IndicatorMixin): From b132440f2415aa668163e7a1fa053784dbba06f0 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Thu, 3 Dec 2020 02:29:39 +0200 Subject: [PATCH 17/18] tests --- ta/volume.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ta/volume.py b/ta/volume.py index 87b57416..8616a048 100644 --- a/ta/volume.py +++ b/ta/volume.py @@ -9,7 +9,7 @@ import numpy as np import pandas as pd -from ta.ta.utils import IndicatorMixin, _ema +from .utils import IndicatorMixin, _ema class AccDistIndexIndicator(IndicatorMixin): From 75d0acf9c1e3e8fc37e81483e2a04e1dfda2f022 Mon Sep 17 00:00:00 2001 From: VladKochetov007 Date: Tue, 15 Dec 2020 00:24:16 +0200 Subject: [PATCH 18/18] 3.8 + optimize --- ta/others.py | 2 +- ta/trend.py | 16 ++++++++++------ ta/volatility.py | 2 +- ta/wrapper.py | 10 +++++----- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/ta/others.py b/ta/others.py index 3e35627c..a8e37d8c 100644 --- a/ta/others.py +++ b/ta/others.py @@ -8,7 +8,7 @@ import numpy as np import pandas as pd -from ta.ta.utils import IndicatorMixin +from ta.utils import IndicatorMixin class DailyReturnIndicator(IndicatorMixin): diff --git a/ta/trend.py b/ta/trend.py index 7fe64c14..7cf0950c 100644 --- a/ta/trend.py +++ b/ta/trend.py @@ -8,8 +8,8 @@ import numpy as np import pandas as pd -from ta.ta.utils import IndicatorMixin, _ema, _sma, _get_min_max -from ta.ta.volatility import AverageTrueRange +from ta.utils import IndicatorMixin, _ema, _sma, _get_min_max +from ta.volatility import AverageTrueRange class AroonIndicator(IndicatorMixin): @@ -1878,24 +1878,28 @@ def __init__(self, self.low = low self.multiplier: float = float(multiplier) if multiplier and multiplier > 0 else 3.0 self.length = int(length) if length and length > 0 else 7 + self._all = self._get_all_ST() def get_supertrend(self) -> pd.Series: - return self.get_all_ST()['ST'] + return self._all['ST'] def get_supertrend_upper(self) -> pd.Series: - return self.get_all_ST()['ST_upper'] + return self._all['ST_upper'] def get_supertrend_lower(self) -> pd.Series: - return self.get_all_ST()['ST_lower'] + return self._all['ST_lower'] def get_supertrend_strategy_returns(self) -> pd.Series: """ :return: pd.Series with 1 or -1 (buy, sell) """ - return self.get_all_ST()['ST_strategy'] + return self._all['ST_strategy'] def get_all_ST(self) -> pd.DataFrame: + return self._all + + def _get_all_ST(self) -> pd.DataFrame: """ ST Indicator, trading predictions, ST high/low diff --git a/ta/volatility.py b/ta/volatility.py index 8b00e611..959c0b89 100644 --- a/ta/volatility.py +++ b/ta/volatility.py @@ -8,7 +8,7 @@ import numpy as np import pandas as pd -from ta.ta.utils import IndicatorMixin +from ta.utils import IndicatorMixin class AverageTrueRange(IndicatorMixin): diff --git a/ta/wrapper.py b/ta/wrapper.py index 22bfbe7d..b8e343c1 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -7,7 +7,7 @@ import pandas as pd -from ta.ta.momentum import ( +from ta.momentum import ( AwesomeOscillatorIndicator, KAMAIndicator, PercentagePriceOscillator, @@ -20,12 +20,12 @@ UltimateOscillator, WilliamsRIndicator, ) -from ta.ta.others import ( +from ta.others import ( CumulativeReturnIndicator, DailyLogReturnIndicator, DailyReturnIndicator, ) -from ta.ta.trend import ( +from ta.trend import ( MACD, ADXIndicator, AroonIndicator, @@ -42,14 +42,14 @@ VortexIndicator, SuperTrendIndicator, ) -from ta.ta.volatility import ( +from ta.volatility import ( AverageTrueRange, BollingerBands, DonchianChannel, KeltnerChannel, UlcerIndex, ) -from ta.ta.volume import ( +from ta.volume import ( AccDistIndexIndicator, ChaikinMoneyFlowIndicator, EaseOfMovementIndicator,