diff --git a/README.md b/README.md index 3935b5f..405dc8c 100644 --- a/README.md +++ b/README.md @@ -80,12 +80,13 @@ help(pd.DataFrame().ta.log_return) # Technical Analysis Indicators (by Category) -## _Momentum_ (19) +## _Momentum_ (20) * _Awesome Oscillator_: **ao** * _Absolute Price Oscillator_: **apo** * _Balance of Power_: **bop** * _Commodity Channel Index_: **cci** +* _Center of Gravity_: **cg** * _Chande Momentum Oscillator_: **cmo** * _Coppock Curve_: **coppock** * _Fisher Transform_: **fisher** diff --git a/pandas_ta/__init__.py b/pandas_ta/__init__.py index 5ebeb30..9f8ab2f 100644 --- a/pandas_ta/__init__.py +++ b/pandas_ta/__init__.py @@ -23,6 +23,7 @@ from .momentum.ao import ao from .momentum.apo import apo from .momentum.bop import bop from .momentum.cci import cci +from .momentum.cg import cg from .momentum.cmo import cmo from .momentum.coppock import coppock from .momentum.fisher import fisher diff --git a/pandas_ta/core.py b/pandas_ta/core.py index c9c612f..bd7f8d5 100644 --- a/pandas_ta/core.py +++ b/pandas_ta/core.py @@ -264,6 +264,13 @@ class AnalysisIndicators(BasePandasObject): self._append(result, **kwargs) return result + def cg(self, close=None, length=None, offset=None, **kwargs): + close = self._get_column(close, 'close') + from .momentum.cg import cg + result = cg(close=close, length=length, offset=offset, **kwargs) + self._append(result, **kwargs) + return result + def cmo(self, close=None, length=None, drift=None, offset=None, **kwargs): close = self._get_column(close, 'close') from .momentum.cmo import cmo diff --git a/pandas_ta/momentum/cg.py b/pandas_ta/momentum/cg.py new file mode 100644 index 0000000..77f351a --- /dev/null +++ b/pandas_ta/momentum/cg.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +from ..utils import get_offset, verify_series, weights + +def cg(close, length=None, offset=None, **kwargs): + """Indicator: Center of Gravity (CG)""" + # Validate Arguments + close = verify_series(close) + length = int(length) if length and length > 0 else 10 + offset = get_offset(offset) + + # Calculate Result + coefficients = [length - i for i in range(0, length)] + numerator = -close.rolling(length).apply(weights(coefficients), raw=True) + cg = numerator / close.rolling(length).sum() + + # Offset + if offset != 0: + cg = cg.shift(offset) + + # Handle fills + if 'fillna' in kwargs: + cg.fillna(kwargs['fillna'], inplace=True) + if 'fill_method' in kwargs: + cg.fillna(method=kwargs['fill_method'], inplace=True) + + # Name and Categorize it + cg.name = f"CG_{length}" + cg.category = 'momentum' + + return cg + + + +cg.__doc__ = \ +"""Center of Gravity (CG) + +The Center of Gravity Indicator by John Ehlers attempts to identify turning +points while exhibiting zero lag and smoothing. + +Sources: + http://www.mesasoftware.com/papers/TheCGOscillator.pdf + +Calculation: + Default Inputs: + length=10 + +Args: + close (pd.Series): Series of 'close's + length (int): The length of the period. Default: 10 + offset (int): How many periods to offset the result. Default: 0 + +Kwargs: + fillna (value, optional): pd.DataFrame.fillna(value) + fill_method (value, optional): Type of fill method + +Returns: + pd.Series: New feature generated. +""" diff --git a/setup.py b/setup.py index 991c365..5152b3f 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ long_description = "An easy to use Python 3 Pandas Extension of Technical Analys setup( name = "pandas_ta", packages = ["pandas_ta"], - version = "0.1.28b", + version = "0.1.29b", 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 bfda283..ef72258 100644 --- a/tests/test_indicator_momentum.py +++ b/tests/test_indicator_momentum.py @@ -84,6 +84,11 @@ class TestMomentum(TestCase): except Exception as ex: error_analysis(result, CORRELATION, ex) + def test_cg(self): + result = pandas_ta.cg(self.close) + self.assertIsInstance(result, Series) + self.assertEqual(result.name, 'CG_10') + def test_cmo(self): result = pandas_ta.cmo(self.close) self.assertIsInstance(result, Series) diff --git a/tests/test_indicator_momentum_ext.py b/tests/test_indicator_momentum_ext.py index 1c4cf3d..2bea314 100644 --- a/tests/test_indicator_momentum_ext.py +++ b/tests/test_indicator_momentum_ext.py @@ -43,6 +43,11 @@ class TestMomentumExtension(TestCase): self.assertIsInstance(self.data, DataFrame) self.assertEqual(self.data.columns[-1], 'CCI_20_0.015') + def test_cg_ext(self): + self.data.ta.cg(append=True) + self.assertIsInstance(self.data, DataFrame) + self.assertEqual(self.data.columns[-1], 'CG_10') + def test_cmo_ext(self): self.data.ta.cmo(append=True) self.assertIsInstance(self.data, DataFrame)