From 1cfe48545cee5df2d29e179a56b3b5710ff98caa Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Thu, 21 May 2020 13:30:57 -0700 Subject: [PATCH 1/3] BUG cci now correlated with talib, fixed default value --- README.md | 1 + pandas_ta/momentum/cci.py | 7 +++---- setup.py | 2 +- tests/test_indicator_momentum.py | 2 +- tests/test_indicator_momentum_ext.py | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index df57606..d06f4ed 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ All the indicators return a named Series or a DataFrame in uppercase underscore - __Aroon & Aroon Oscillator__ (aroon) * Fixed indicator and included oscillator in returned dataframe - __Bollinger Bands__ (bbands) + - __Commodity Channel Index__ (cci) - __Chande Momentum Oscillator__ (cmo) ## What is a Pandas DataFrame Extension? diff --git a/pandas_ta/momentum/cci.py b/pandas_ta/momentum/cci.py index adf0f67..1244032 100644 --- a/pandas_ta/momentum/cci.py +++ b/pandas_ta/momentum/cci.py @@ -10,9 +10,8 @@ def cci(high, low, close, length=None, c=None, offset=None, **kwargs): high = verify_series(high) low = verify_series(low) close = verify_series(close) - length = int(length) if length and length > 0 else 20 + length = int(length) if length and length > 0 else 14 c = float(c) if c and c > 0 else 0.015 - min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length offset = get_offset(offset) # Calculate Result @@ -52,7 +51,7 @@ Sources: Calculation: Default Inputs: - length=20, c=0.015 + length=14, c=0.015 SMA = Simple Moving Average MAD = Mean Absolute Deviation tp = typical_price = hlc3 = (high + low + close) / 3 @@ -64,7 +63,7 @@ Args: high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's - length (int): It's period. Default: 20 + length (int): It's period. Default: 14 c (float): Scaling Constant. Default: 0.015 offset (int): How many periods to offset the result. Default: 0 diff --git a/setup.py b/setup.py index 79613d6..e04213b 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ long_description = "An easy to use Python 3 Pandas Extension with 100+ Technical setup( name ="pandas_ta", packages =['pandas_ta', 'pandas_ta.momentum', 'pandas_ta.overlap', 'pandas_ta.performance', 'pandas_ta.statistics', 'pandas_ta.trend', 'pandas_ta.volatility', 'pandas_ta.volume'], - version ="0.1.52b", + version ="0.1.53b", description =long_description, long_description =long_description, author ="Kevin Johnson", diff --git a/tests/test_indicator_momentum.py b/tests/test_indicator_momentum.py index 9206d3a..5e40564 100644 --- a/tests/test_indicator_momentum.py +++ b/tests/test_indicator_momentum.py @@ -107,7 +107,7 @@ class TestMomentum(TestCase): def test_cci(self): result = pandas_ta.cci(self.high, self.low, self.close) self.assertIsInstance(result, Series) - self.assertEqual(result.name, 'CCI_20_0.015') + self.assertEqual(result.name, 'CCI_14_0.015') try: expected = tal.CCI(self.high, self.low, self.close) diff --git a/tests/test_indicator_momentum_ext.py b/tests/test_indicator_momentum_ext.py index 9c6ef44..1eaa045 100644 --- a/tests/test_indicator_momentum_ext.py +++ b/tests/test_indicator_momentum_ext.py @@ -51,7 +51,7 @@ class TestMomentumExtension(TestCase): def test_cci_ext(self): self.data.ta.cci(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(self.data.columns[-1], 'CCI_20_0.015') + self.assertEqual(self.data.columns[-1], 'CCI_14_0.015') def test_cg_ext(self): self.data.ta.cg(append=True) From 81e554a0040bb582a6fed4756b645cf7e2e65355 Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Thu, 21 May 2020 14:47:14 -0700 Subject: [PATCH 2/3] BUG apo correctly calculated and talib correlated --- README.md | 1 + pandas_ta/momentum/apo.py | 13 ++++++------- setup.py | 2 +- tests/test_indicator_momentum.py | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d06f4ed..5788eeb 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ All the indicators return a named Series or a DataFrame in uppercase underscore - __Aberration__ (aberration) - __BRAR__ (brar) * Corrected Indicators: + - __Absolute Price Oscillator__ (apo) - __Aroon & Aroon Oscillator__ (aroon) * Fixed indicator and included oscillator in returned dataframe - __Bollinger Bands__ (bbands) diff --git a/pandas_ta/momentum/apo.py b/pandas_ta/momentum/apo.py index ed05ec3..52a7b56 100644 --- a/pandas_ta/momentum/apo.py +++ b/pandas_ta/momentum/apo.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from ..overlap.ema import ema +from ..overlap.sma import sma from ..utils import get_offset, verify_series def apo(close, fast=None, slow=None, offset=None, **kwargs): @@ -14,9 +14,8 @@ def apo(close, fast=None, slow=None, offset=None, **kwargs): offset = get_offset(offset) # Calculate Result - fastma = ema(close, length=fast, **kwargs) - slowma = ema(close, length=slow, **kwargs) - # EMAs are equivalent with talib, only their difference is minutely off + fastma = sma(close, length=fast) + slowma = sma(close, length=slow) apo = fastma - slowma # Offset @@ -45,13 +44,13 @@ momentum. It is simply the difference of two Exponential Moving Averages (EMA) of two different periods. Note: APO and MACD lines are equivalent. Sources: - https://www.investopedia.com/terms/p/ppo.asp + https://www.tradingtechnologies.com/xtrader-help/x-study/technical-indicator-definitions/absolute-price-oscillator-apo/ Calculation: Default Inputs: fast=12, slow=26 - EMA = Exponential Moving Average - APO = EMA(close, fast) - EMA(close, slow) + SMA = Simple Moving Average + APO = SMA(close, fast) - SMA(close, slow) Args: close (pd.Series): Series of 'close's diff --git a/setup.py b/setup.py index e04213b..9d1b041 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ long_description = "An easy to use Python 3 Pandas Extension with 100+ Technical setup( name ="pandas_ta", packages =['pandas_ta', 'pandas_ta.momentum', 'pandas_ta.overlap', 'pandas_ta.performance', 'pandas_ta.statistics', 'pandas_ta.trend', 'pandas_ta.volatility', 'pandas_ta.volume'], - version ="0.1.53b", + version ="0.1.54b", description =long_description, long_description =long_description, author ="Kevin Johnson", diff --git a/tests/test_indicator_momentum.py b/tests/test_indicator_momentum.py index 5e40564..d50383b 100644 --- a/tests/test_indicator_momentum.py +++ b/tests/test_indicator_momentum.py @@ -70,7 +70,7 @@ class TestMomentum(TestCase): self.assertEqual(result.name, 'APO_12_26') try: - expected = tal.APO(self.close, 12, 26) + expected = tal.APO(self.close) pdt.assert_series_equal(result, expected, check_names=False) except AssertionError as ae: try: From 913d0d886b83a66f1ccc0c31dd43894e6ba70f03 Mon Sep 17 00:00:00 2001 From: Kevin Johnson Date: Thu, 21 May 2020 15:56:17 -0700 Subject: [PATCH 3/3] BUG stoch equal numerical arguments --- pandas_ta/momentum/stoch.py | 8 ++++---- pandas_ta/trend/adx.py | 11 ++++++----- setup.py | 2 +- tests/test_indicator_momentum.py | 5 +++++ tests/test_indicator_momentum_ext.py | 2 +- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/pandas_ta/momentum/stoch.py b/pandas_ta/momentum/stoch.py index eed2b26..4da6a0a 100644 --- a/pandas_ta/momentum/stoch.py +++ b/pandas_ta/momentum/stoch.py @@ -44,10 +44,10 @@ def stoch(high, low, close, fast_k=None, slow_k=None, slow_d=None, offset=None, slowd.fillna(method=kwargs['fill_method'], inplace=True) # Name and Categorize it - fastk.name = f"STOCHF_{fast_k}" - fastd.name = f"STOCHF_{slow_d}" - slowk.name = f"STOCH_{slow_k}" - slowd.name = f"STOCH_{slow_d}" + fastk.name = f"STOCHFk_{fast_k}" + fastd.name = f"STOCHFd_{slow_d}" + slowk.name = f"STOCHk_{slow_k}" + slowd.name = f"STOCHd_{slow_d}" fastk.category = fastd.category = slowk.category = slowd.category = 'momentum' # Prepare DataFrame to return diff --git a/pandas_ta/trend/adx.py b/pandas_ta/trend/adx.py index 096c86c..6ab9e42 100644 --- a/pandas_ta/trend/adx.py +++ b/pandas_ta/trend/adx.py @@ -15,10 +15,10 @@ def adx(high, low, close, length=None, drift=None, offset=None, **kwargs): offset = get_offset(offset) # Calculate Result - _atr = atr(high=high, low=low, close=close, length=length) + atr_ = atr(high=high, low=low, close=close, length=length) - up = high - high.shift(drift) - dn = low.shift(drift) - low + up = high - high.shift(drift) # high.diff(drift) + dn = low.shift(drift) - low # low.diff(-drift).shift(drift) pos = ((up > dn) & (up > 0)) * up neg = ((dn > up) & (dn > 0)) * dn @@ -26,8 +26,9 @@ def adx(high, low, close, length=None, drift=None, offset=None, **kwargs): pos = pos.apply(zero) neg = neg.apply(zero) - dmp = (100 / _atr) * rma(close=pos, length=length) - dmn = (100 / _atr) * rma(close=neg, length=length) + k = 100 / atr_ + dmp = k * rma(close=pos, length=length) + dmn = k * rma(close=neg, length=length) dx = 100 * (dmp - dmn).abs() / (dmp + dmn) adx = rma(close=dx, length=length) diff --git a/setup.py b/setup.py index 9d1b041..1dd2d4b 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ long_description = "An easy to use Python 3 Pandas Extension with 100+ Technical setup( name ="pandas_ta", packages =['pandas_ta', 'pandas_ta.momentum', 'pandas_ta.overlap', 'pandas_ta.performance', 'pandas_ta.statistics', 'pandas_ta.trend', 'pandas_ta.volatility', 'pandas_ta.volume'], - version ="0.1.54b", + version ="0.1.55b", description =long_description, long_description =long_description, author ="Kevin Johnson", diff --git a/tests/test_indicator_momentum.py b/tests/test_indicator_momentum.py index d50383b..b27fb26 100644 --- a/tests/test_indicator_momentum.py +++ b/tests/test_indicator_momentum.py @@ -273,6 +273,11 @@ class TestMomentum(TestCase): self.assertEqual(result.name, 'ANGLEd_1') def test_stoch(self): + result = pandas_ta.stoch(self.high, self.low, self.close, fast_k=14, slow_k=14, slow_d=14) + self.assertIsInstance(result, DataFrame) + self.assertEqual(result.name, 'STOCH_14_14_14') + self.assertEqual(len(result.columns), 4) + result = pandas_ta.stoch(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) self.assertEqual(result.name, 'STOCH_14_5_3') diff --git a/tests/test_indicator_momentum_ext.py b/tests/test_indicator_momentum_ext.py index 1eaa045..d5641ef 100644 --- a/tests/test_indicator_momentum_ext.py +++ b/tests/test_indicator_momentum_ext.py @@ -134,7 +134,7 @@ class TestMomentumExtension(TestCase): def test_stoch_ext(self): self.data.ta.stoch(append=True) self.assertIsInstance(self.data, DataFrame) - self.assertEqual(list(self.data.columns[-4:]), ['STOCHF_14', 'STOCHF_3', 'STOCH_5', 'STOCH_3']) + self.assertEqual(list(self.data.columns[-4:]), ['STOCHFk_14', 'STOCHFd_3', 'STOCHk_5', 'STOCHd_3']) def test_trix_ext(self): self.data.ta.trix(append=True)