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/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/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 89ecc1a9..c789e07f 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/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 b86d974b..9c1bd753 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 ta.ta.utils import IndicatorMixin, _ema class RSIIndicator(IndicatorMixin): @@ -75,11 +75,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 +95,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 +149,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 +183,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 +234,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 +300,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 +324,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 +343,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 +389,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 +438,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 +457,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 +510,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 +564,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 +584,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 +633,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 +707,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 +807,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 +896,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 +1070,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 +1100,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 +1130,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 +1160,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 +1191,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 +1218,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 +1249,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 +1283,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 +1317,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 edba1440..778ea4ac 100644 --- a/ta/trend.py +++ b/ta/trend.py @@ -8,7 +8,8 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin, _ema, _get_min_max, _sma +from ta.utils import IndicatorMixin, _ema, _sma, _get_min_max +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: @@ -776,12 +777,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) @@ -838,12 +839,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 @@ -912,13 +913,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 @@ -946,7 +947,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]: @@ -969,7 +970,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]: @@ -1073,14 +1074,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 @@ -1092,7 +1093,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 @@ -1462,16 +1462,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) @@ -1513,7 +1513,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) @@ -1550,17 +1550,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) @@ -1603,7 +1603,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) @@ -1634,7 +1634,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) @@ -1857,3 +1857,143 @@ 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 + self._all = self._get_all_ST() + + def get_supertrend(self) -> pd.Series: + return self._all['ST'] + + def get_supertrend_upper(self) -> pd.Series: + return self._all['ST_upper'] + + def get_supertrend_lower(self) -> pd.Series: + return self._all['ST_lower'] + + def get_supertrend_strategy_returns(self) -> pd.Series: + """ + + :return: pd.Series with 1 or -1 (buy, sell) + """ + 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 + """ + 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 e10a6bd4..452a1d57 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 a58764b2..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 @@ -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..8616a048 100644 --- a/ta/volume.py +++ b/ta/volume.py @@ -9,7 +9,7 @@ import numpy as np import pandas as pd -from ta.utils import IndicatorMixin, _ema +from .utils import IndicatorMixin, _ema class AccDistIndexIndicator(IndicatorMixin): @@ -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 afb19e63..87beab43 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -40,6 +40,7 @@ STCIndicator, TRIXIndicator, VortexIndicator, + SuperTrendIndicator, ) from ta.volatility import ( AverageTrueRange, @@ -245,6 +246,7 @@ def add_trend_ta( """ # MACD + indicator_macd = MACD( close=df[close], window_slow=26, window_fast=12, window_sign=9, fillna=fillna ) @@ -335,6 +337,11 @@ 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() if not vectorized: # Average Directional Movement Index (ADX) indicator_adx = ADXIndicator( diff --git a/test/__init__.py b/test/__init__.py index 2310ac1e..9290be4b 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,43 +1,3 @@ -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", "TestKAMAIndicator", diff --git a/test/integration/wrapper.py b/test/integration/wrapper.py index 1cd7c545..669629d6 100644 --- a/test/integration/wrapper.py +++ b/test/integration/wrapper.py @@ -6,7 +6,6 @@ class TestWrapper(unittest.TestCase): - _filename = "test/data/datas.csv" @classmethod @@ -57,10 +56,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() ) self.assertTrue(df_with_ta.shape[1] == 94) 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,