diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..3d69cb4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,36 @@ +--- +name: Bug report +about: Create a report to help us improve. +title: '' +labels: bug +assignees: twopirllc + +--- + +**Which version are you running? The lastest version is on Github. Pip is for major releases.** +```python +import pandas_ta as ta +print(ta.version) +``` + +**Upgrade.** +```sh +$ pip install -U git+https://github.com/twopirllc/pandas-ta +``` + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Provide sample code. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. + +Thanks for using Pandas TA! diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..7933e03 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,33 @@ +--- +name: Feature request +about: Suggest an idea for this project. +title: '' +labels: enhancement +assignees: '' + +--- + +**Which version are you running? The lastest version is Github. Pip is for major releases.** +```python +import pandas_ta as ta +print(ta.version) +``` + +**Upgrade.** +```sh +$ pip install -U git+https://github.com/twopirllc/pandas-ta +``` + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. + +Thanks for using Pandas TA! diff --git a/.github/ISSUE_TEMPLATE/indicator-request.md b/.github/ISSUE_TEMPLATE/indicator-request.md new file mode 100644 index 0000000..1fcec8e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/indicator-request.md @@ -0,0 +1,33 @@ +--- +name: Indicator Request +about: Be as detailed as possible with links please. +title: '' +labels: enhancement +assignees: twopirllc + +--- + +**Which version are you running? The lastest version is on Github. Pip is for major releases.** +```python +import pandas_ta as ta +print(ta.version) +``` + +**Upgrade.** +```sh +$ pip install -U git+https://github.com/twopirllc/pandas-ta +``` + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context, web links, or screenshots about the feature request here. + +Thanks for using Pandas TA! diff --git a/.gitignore b/.gitignore index 89d7fbf..af07da9 100644 --- a/.gitignore +++ b/.gitignore @@ -122,8 +122,8 @@ data/SPY_5min.csv data/SPY_1min.csv data/SPY_D_adxfish.csv data/SPY_D_lbsz.csv -data/TV_5min.csv data/similang-ch.csv +data/TV_5min.csv data/tulip.csv examples/cache.sqlite @@ -141,6 +141,7 @@ doc.py bt.ipynb scratch.ipynb ta_extension.ipynb +scratch.ipynb kerasmodeller.ipynb Charts.ipynb pandas_pips diff --git a/README.md b/README.md index 1c3a4b4..a1656d6 100644 --- a/README.md +++ b/README.md @@ -56,10 +56,11 @@ and _Weighted Moving Average_. ## __New Indicators__ -_Squeeze_ (**squeeze**). A Momentum indicator. Both John Carter's TTM **and** Lazybear's TradingView versions are implemented. The default is John Carter's, or ```lazybear=False```. Set ```lazybear=True``` to enable Lazybear's. +* _Squeeze_ (**squeeze**). A Momentum indicator. Both John Carter's TTM **and** Lazybear's TradingView versions are implemented. The default is John Carter's, or ```lazybear=False```. Set ```lazybear=True``` to enable Lazybear's. + ## __Updated Indicators__ -_Fisher Transform_ **fisher**: Added Fisher's default **ema** signal line. To change the length of the signal line, use the argument: ```signal=5```. Default: 5 -_Fisher Transform_ **fisher** and _Kaufman's Adaptive Moving Average_ **kama**: Fixed a bug where their columns were not added to final DataFrame when using the _strategy_ method. +* _Fisher Transform_ **fisher**: Added Fisher's default **ema** signal line. To change the length of the signal line, use the argument: ```signal=5```. Default: 5 +* _Fisher Transform_ **fisher** and _Kaufman's Adaptive Moving Average_ **kama**: Fixed a bug where their columns were not added to final DataFrame when using the _strategy_ method. ## What is a Pandas DataFrame Extension? diff --git a/pandas_ta/core.py b/pandas_ta/core.py index 28469bc..bd01f1b 100644 --- a/pandas_ta/core.py +++ b/pandas_ta/core.py @@ -838,6 +838,15 @@ class AnalysisIndicators(BasePandasObject): result = stoch(high=high, low=low, close=close, fast_k=fast_k, slow_k=slow_k, slow_d=slow_d, offset=offset, **kwargs) return result + @finalize + def ttm_trend(self, high=None, low=None, close=None, offset=None, length=None, **kwargs): + high = self._get_column(high, "high") + low = self._get_column(low, "low") + close = self._get_column(close, "close") + + result = ttm_trend(high=high, low=low, close=close, length=length, offset=offset, **kwargs) + return result + @finalize def trix(self, close=None, length=None, signal=None, scalar=None, drift=None, offset=None, **kwargs): close = self._get_column(close, "close") @@ -1588,4 +1597,4 @@ class AnalysisIndicators(BasePandasObject): volume = self._get_column(volume, 'volume') result = vp(close=close, volume=volume, width=width, percent=percent, **kwargs) - return result \ No newline at end of file + return result diff --git a/pandas_ta/trend/__init__.py b/pandas_ta/trend/__init__.py index dbdce91..372e815 100644 --- a/pandas_ta/trend/__init__.py +++ b/pandas_ta/trend/__init__.py @@ -12,4 +12,5 @@ from .long_run import long_run from .psar import psar from .qstick import qstick from .short_run import short_run -from .vortex import vortex \ No newline at end of file +from .ttm_trend import ttm_trend +from .vortex import vortex diff --git a/pandas_ta/trend/ttm_trend.py b/pandas_ta/trend/ttm_trend.py new file mode 100644 index 0000000..1d469e4 --- /dev/null +++ b/pandas_ta/trend/ttm_trend.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +from pandas import DataFrame +from pandas_ta.utils import get_offset, verify_series + +def ttm_trend(high, low, close, length=None, offset=None, **kwargs): + """Indicator: TTM Trend""" + # Validate arguments + high = verify_series(high) + low = verify_series(low) + close = verify_series(close) + length = int(length) if length and length > 0 else 6 + offset = get_offset(offset) + + # Calculate Result + trend_avg = ((high + low)/2) + for i in range(1, length): + trend_avg = trend_avg + ((high.shift(i) + low.shift(i))/2) + + trend_avg = trend_avg / length + + tm_trend = (close > trend_avg).astype(int) + tm_trend.replace(0, -1, inplace=True) + + # Offset + if offset != 0: + tm_trend = tm_trend.shift(offset) + + # Handle fills + if 'fillna' in kwargs: + tm_trend.fillna(kwargs['fillna'], inplace=True) + if 'fill_method' in kwargs: + tm_trend.fillna(method=kwargs['fill_method'], inplace=True) + + # Name and Categorize it + tm_trend.name = f"TTM_TRND_{length}" + tm_trend.category = "momentum" + + # Prepare DataFrame to return + data = {tm_trend.name: tm_trend} + df = DataFrame(data) + df.name = f"TTMTREND_{length}" + df.category = tm_trend.category + + return df + + + +ttm_trend.__doc__ = \ +"""This indicator is from John Carters book “Mastering the trade” an plots the bars green or red. +It checks if the price is above or under the average price of the previous 5 bars. +The indicator should hep you stay in a trade until the colors chance. +Two bars of the opposite color is the signal to get in or out. +Sources: + https://www.prorealcode.com/prorealtime-indicators/ttm-trend-price/ +Calculation: + Default Inputs: + length=6 + averageprice = (((high[5]+low[5])/2)+((high[4]+low[4])/2)+((high[3]+low[3])/2)+((high[2]+low[2])/2)+((high[1]+low[1])/2)+((high[6]+low[6])/2))/6 + if close > averageprice then + drawcandle(open,high,low,close) coloured(0,255,0) + endif + + if close < averageprice then + drawcandle(open,high,low,close) coloured(255,0,0) + endif +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: 6 + 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.DataFrame: ttm_trend. +""" diff --git a/tests/test_indicator_trend.py b/tests/test_indicator_trend.py index f6a7152..47537bd 100644 --- a/tests/test_indicator_trend.py +++ b/tests/test_indicator_trend.py @@ -154,7 +154,12 @@ class TestTrend(TestCase): self.assertIsInstance(result, Series) self.assertEqual(result.name, "SR_2") + def test_ttm_trend(self): + result = pandas_ta.ttm_trend(self.high, self.low, self.close) + self.assertIsInstance(result, DataFrame) + self.assertEqual(result.name, "TTMTREND_6") + def test_vortex(self): result = pandas_ta.vortex(self.high, self.low, self.close) self.assertIsInstance(result, DataFrame) - self.assertEqual(result.name, "VTX_14") \ No newline at end of file + self.assertEqual(result.name, "VTX_14") diff --git a/tests/test_indicator_trend_ext.py b/tests/test_indicator_trend_ext.py index a3df15f..83ddcb0 100644 --- a/tests/test_indicator_trend_ext.py +++ b/tests/test_indicator_trend_ext.py @@ -98,6 +98,11 @@ class TestTrendExtension(TestCase): self.assertIsInstance(self.data, DataFrame) self.assertEqual(self.data.columns[-1], "SR_2") + def test_ttm_trend_ext(self): + self.data.ta.ttm_trend(append=True) + self.assertIsInstance(self.data, DataFrame) + self.assertEqual(list(self.data.columns[-1:]), ["TTM_TRND_6"]) + def test_vortext_ext(self): self.data.ta.vortex(append=True) self.assertIsInstance(self.data, DataFrame)