diff --git a/README.md b/README.md index 4722bd5..66e7c66 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ $ pip install pandas_ta Latest Version -------------- -Best choice! Version: *0.2.70b* +Best choice! Version: *0.2.71b* ```sh $ pip install -U git+https://github.com/twopirllc/pandas-ta ``` @@ -923,6 +923,7 @@ cascaded stochastic calculations with additional smoothing. See: ```help(ta.stc) * _ADX_ (**adx**): Added ```mamode``` with default "**RMA**" and with the same ```mamode``` options as TradingView. See ```help(ta.adx)```. * _Average True Range_ (**atr**): The default ```mamode``` is now "**RMA**" and with the same ```mamode``` options as TradingView. See ```help(ta.atr)```. * _Bollinger Bands_ (**bbands**): New argument ```ddoff``` to control the Degrees of Freedom. Default is 0. See ```help(ta.bbands)```. +* _Choppiness Index_ (**chop**): New argument ```ln``` to use Natural Logarithm (True) instead of the Standard Logarithm (False). Default is False. See ```help(ta.chop)```. * _Chande Kroll Stop_ (**cksp**): Added ```tvmode``` with default ```True```. When ```tvmode=False```, **cksp** implements “The New Technical Trader” with default values. See ```help(ta.cksp)```. * _Decreasing_ (**decreasing**): New argument ```strict``` checks if the series is continuously decreasing over period ```length```. Default: ```False```. See ```help(ta.decreasing)```. * _Increasing_ (**increasing**): New argument ```strict``` checks if the series is continuously increasing over period ```length```. Default: ```False```. See ```help(ta.increasing)```. diff --git a/pandas_ta/trend/chop.py b/pandas_ta/trend/chop.py index 8b24cd6..89cd7af 100644 --- a/pandas_ta/trend/chop.py +++ b/pandas_ta/trend/chop.py @@ -1,14 +1,16 @@ # -*- coding: utf-8 -*- from numpy import log10 as npLog10 +from numpy import log as npLn from pandas_ta.volatility import atr from pandas_ta.utils import get_offset, get_drift, verify_series -def chop(high, low, close, length=None, atr_length=None, scalar=None, drift=None, offset=None, **kwargs): +def chop(high, low, close, length=None, atr_length=None, ln=None, scalar=None, drift=None, offset=None, **kwargs): """Indicator: Choppiness Index (CHOP)""" # Validate Arguments length = int(length) if length and length > 0 else 14 atr_length = int(atr_length) if atr_length is not None and atr_length > 0 else 1 + ln = bool(ln) if isinstance(ln, bool) else False scalar = float(scalar) if scalar else 100 high = verify_series(high, length) low = verify_series(low, length) @@ -24,8 +26,11 @@ def chop(high, low, close, length=None, atr_length=None, scalar=None, drift=None atr_ = atr(high=high, low=low, close=close, length=atr_length) atr_sum = atr_.rolling(length).sum() - chop = scalar * (npLog10(atr_sum) - npLog10(diff)) - chop /= npLog10(length) + chop = scalar + if ln: + chop *= (npLn(atr_sum) - npLn(diff)) / npLn(length) + else: + chop *= (npLog10(atr_sum) - npLog10(diff)) / npLog10(length) # Offset if offset != 0: @@ -38,7 +43,7 @@ def chop(high, low, close, length=None, atr_length=None, scalar=None, drift=None chop.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it - chop.name = f"CHOP_{length}_{atr_length}_{scalar}" + chop.name = f"CHOP{'ln' if ln else ''}_{length}_{atr_length}_{scalar}" chop.category = "trend" return chop @@ -73,6 +78,7 @@ Args: close (pd.Series): Series of 'close's length (int): It's period. Default: 14 atr_length (int): Length for ATR. Default: 1 + ln (bool): If True, uses ln otherwise log10. Default: False scalar (float): How much to magnify. Default: 100 drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 diff --git a/setup.py b/setup.py index bb52713..415d2ee 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ setup( "pandas_ta.volatility", "pandas_ta.volume" ], - version=".".join(("0", "2", "70b")), + version=".".join(("0", "2", "71b")), description=long_description, long_description=long_description, author="Kevin Johnson", diff --git a/tests/test_ext_indicator_trend.py b/tests/test_ext_indicator_trend.py index 58567f7..990e97c 100644 --- a/tests/test_ext_indicator_trend.py +++ b/tests/test_ext_indicator_trend.py @@ -34,10 +34,14 @@ class TestTrendExtension(TestCase): self.assertEqual(list(self.data.columns[-3:]), ["AROOND_14", "AROONU_14", "AROONOSC_14"]) def test_chop_ext(self): - self.data.ta.chop(append=True) + self.data.ta.chop(append=True, ln=False) self.assertIsInstance(self.data, DataFrame) self.assertEqual(self.data.columns[-1], "CHOP_14_1_100") + self.data.ta.chop(append=True, ln=True) + self.assertIsInstance(self.data, DataFrame) + self.assertEqual(self.data.columns[-1], "CHOPln_14_1_100") + def test_cksp_ext(self): self.data.ta.cksp(tvmode=False, append=True) self.assertIsInstance(self.data, DataFrame) diff --git a/tests/test_indicator_trend.py b/tests/test_indicator_trend.py index ba209dd..9fe064d 100644 --- a/tests/test_indicator_trend.py +++ b/tests/test_indicator_trend.py @@ -90,10 +90,14 @@ class TestTrend(TestCase): error_analysis(result.iloc[:, 0], CORRELATION, ex) def test_chop(self): - result = pandas_ta.chop(self.high, self.low, self.close) + result = pandas_ta.chop(self.high, self.low, self.close, ln=False) self.assertIsInstance(result, Series) self.assertEqual(result.name, "CHOP_14_1_100") + result = pandas_ta.chop(self.high, self.low, self.close, ln=True) + self.assertIsInstance(result, Series) + self.assertEqual(result.name, "CHOPln_14_1_100") + def test_cksp(self): result = pandas_ta.cksp(self.high, self.low, self.close, tvmode=False) self.assertIsInstance(result, DataFrame)