From f52cf74eb0e85e6caa6379534c179cc817ed2525 Mon Sep 17 00:00:00 2001 From: Bukosabino Date: Mon, 4 May 2020 17:50:00 +0200 Subject: [PATCH] fixing bug donchian channels https://github.com/bukosabino/ta/issues/133 --- release.md | 6 +- setup.py | 4 +- ta/tests/__init__.py | 2 +- ta/tests/data/cs-dc.csv | 101 ++++++++++---------------------- ta/tests/data/cs-dc2.csv | 31 ++++++++++ ta/tests/volatility.py | 90 +++++++++++++++++++++------- ta/volatility.py | 123 ++++++++++++++------------------------- ta/wrapper.py | 7 ++- 8 files changed, 186 insertions(+), 178 deletions(-) create mode 100644 ta/tests/data/cs-dc2.csv diff --git a/release.md b/release.md index a323ce04..a91994fe 100644 --- a/release.md +++ b/release.md @@ -1,6 +1,10 @@ | Date | Version | Comment | | ------------- | ------------- | ------------- | -| 2020/05/03 | 0.5.21 | Donchian Channel: adding tests; adding some useful functions; fixing some minor bug https://github.com/bukosabino/ta/issues/133 | +| | | 1. Keltner Channel: adding tests; adding n atr input parametr; fixing some minor bug; adding unittests for adx https://github.com/bukosabino/ta/pull/148 | +| | | 2. Refactor tests code and speed up the tests https://github.com/bukosabino/ta/pull/149 | +| | | 3. Refactor tests code https://github.com/bukosabino/ta/pull/150 | +| | | 4. Donchian Channel: Fixing bug https://github.com/bukosabino/ta/pull/151 | +| 2020/05/03 | 0.5.21 | Donchian Channel: adding tests; adding some useful functions; fixing some minor bug https://github.com/bukosabino/ta/pull/147 https://github.com/bukosabino/ta/issues/133 | | 2020/04/20 | 0.5.20 | remove fstring compatibility for python versions < 3.6 | | 2020/04/20 | 0.5.19 | adding fstring compatibility for python versions < 3.6 https://github.com/bukosabino/ta/pull/141 | | 2020/04/16 | 0.5.18 | Adding VWAP indicator https://github.com/bukosabino/ta/issues/130 | diff --git a/setup.py b/setup.py index 02dac610..4bc1c2e8 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ setup( name='ta', packages=['ta'], - version='0.5.21', + version='0.5.22', description='Technical Analysis Library in Python', long_description='It is a Technical Analysis library to financial time series datasets. You can use to do feature engineering. It is builded on Python Pandas library.', author='Dario Lopez Padial (Bukosabino)', @@ -16,7 +16,7 @@ 'numpy', 'pandas', ], - download_url='https://github.com/bukosabino/ta/tarball/0.5.21', + download_url='https://github.com/bukosabino/ta/tarball/0.5.22', keywords=['technical analysis', 'python3', 'pandas'], license='The MIT License (MIT)', classifiers=[ diff --git a/ta/tests/__init__.py b/ta/tests/__init__.py index 9b0ca080..0fe7ebc3 100644 --- a/ta/tests/__init__.py +++ b/ta/tests/__init__.py @@ -7,7 +7,7 @@ TestVortexIndicator) from ta.tests.volatility import (TestAverageTrueRange, TestAverageTrueRange2, TestBollingerBands, TestDonchianChannel, - TestKeltnerChannel) + TestDonchianChannel2, TestKeltnerChannel) from ta.tests.volume import (TestAccDistIndexIndicator, TestEaseOfMovementIndicator, TestForceIndexIndicator, TestMFIIndicator, diff --git a/ta/tests/data/cs-dc.csv b/ta/tests/data/cs-dc.csv index 7b637820..5337c5ae 100644 --- a/ta/tests/data/cs-dc.csv +++ b/ta/tests/data/cs-dc.csv @@ -1,70 +1,31 @@ -Date,Close,average,upper_band,lower_band,middle_band,dc_high_indicator,dc_low_indicator,dc_percentage,dc_band_width -2010-01-07,90.700,,,,,,,, -2010-01-08,92.900,,,,,,,, -2010-01-09,92.980,,,,,,,, -2010-01-10,91.800,,,,,,,, -2010-01-11,92.660,,,,,,,, -2010-01-12,92.680,,,,,,,, -2010-01-13,92.300,,,,,,,, -2010-01-14,92.770,,,,,,,, -2010-01-15,92.540,,,,,,,, -2010-01-16,92.950,,,,,,,, -2010-01-17,93.200,,,,,,,, -2010-01-18,91.070,,,,,,,, -2010-01-19,89.830,,,,,,,, -2010-01-20,89.740,,,,,,,, -2010-01-21,90.400,,,,,,,, -2010-01-22,90.740,,,,,,,, -2010-01-23,88.020,,,,,,,, -2010-01-24,88.090,,,,,,,, -2010-01-25,88.840,,,,,,,, -2010-01-26,90.780,91.24950,93.20,88.02,90.61,0,0,0.5328185328,5.676743434 -2010-01-27,90.540,91.24150,93.20,88.02,90.61,0,0,0.4864864865,5.677241168 -2010-01-28,91.390,91.16600,93.20,88.02,90.61,0,0,0.6505791506,5.68194283 -2010-01-29,90.650,91.04950,93.20,88.02,90.61,0,0,0.5077220077,5.689213011 -2010-01-30,90.700,90.99450,93.20,88.02,90.61,0,0,0.5173745174,5.692651754 -2010-01-31,92.900,91.00650,93.20,88.02,90.61,0,0,0.9420849421,5.691901128 -2010-02-01,92.980,91.02150,93.20,88.02,90.61,0,0,0.9575289575,5.690963124 -2010-02-02,91.800,90.99650,93.20,88.02,90.61,0,0,0.7297297297,5.692526636 -2010-02-03,92.660,90.99100,93.20,88.02,90.61,0,0,0.8957528958,5.692870723 -2010-02-04,92.680,90.99800,93.20,88.02,90.61,0,0,0.8996138996,5.692432801 -2010-02-05,92.300,90.96550,93.20,88.02,90.61,0,0,0.8262548263,5.694466583 -2010-02-06,92.770,90.94400,92.98,88.02,90.50,0,0,0.9576612903,5.4539057 -2010-02-07,92.540,91.01750,92.98,88.02,90.50,0,0,0.9112903226,5.449501469 -2010-02-08,92.950,91.17350,92.98,88.02,90.50,0,0,0.9939516129,5.440177244 -2010-02-09,93.200,91.34650,93.20,88.02,90.61,1,0,1,5.670715353 -2010-02-10,91.070,91.38000,93.20,88.02,90.61,0,0,0.5888030888,5.668636463 -2010-02-11,89.830,91.33450,93.20,88.02,90.61,0,0,0.3494208494,5.671460401 -2010-02-12,89.740,91.42050,93.20,88.09,90.65,0,0,0.3228962818,5.589555953 -2010-02-13,90.400,91.53600,93.20,88.84,91.02,0,0,0.3577981651,4.763153295 -2010-02-14,90.740,91.63100,93.20,89.74,91.47,0,0,0.289017341,3.776014668 -2010-02-15,88.020,91.49300,93.20,88.02,90.61,0,1,0,5.661635316 -2010-02-16,88.090,91.37050,93.20,88.02,90.61,0,0,0.01351351351,5.669225844 -2010-02-17,88.840,91.24300,93.20,88.02,90.61,0,0,0.1583011583,5.677147836 -2010-02-18,90.780,91.24950,93.20,88.02,90.61,0,0,0.5328185328,5.676743434 -2010-02-19,90.540,91.24150,93.20,88.02,90.61,0,0,0.4864864865,5.677241168 -2010-02-20,91.390,91.16600,93.20,88.02,90.61,0,0,0.6505791506,5.68194283 -2010-02-21,90.650,91.04950,93.20,88.02,90.61,0,0,0.5077220077,5.689213011 -2010-02-22,90.700,90.99450,93.20,88.02,90.61,0,0,0.5173745174,5.692651754 -2010-02-23,92.900,91.00650,93.20,88.02,90.61,0,0,0.9420849421,5.691901128 -2010-02-24,92.980,91.02150,93.20,88.02,90.61,0,0,0.9575289575,5.690963124 -2010-02-25,91.800,90.99650,93.20,88.02,90.61,0,0,0.7297297297,5.692526636 -2010-02-26,92.660,90.99100,93.20,88.02,90.61,0,0,0.8957528958,5.692870723 -2010-02-27,92.680,90.99800,93.20,88.02,90.61,0,0,0.8996138996,5.692432801 -2010-02-28,92.300,90.96550,93.20,88.02,90.61,0,0,0.8262548263,5.694466583 -2010-03-01,92.770,90.94400,92.98,88.02,90.50,0,0,0.9576612903,5.4539057 -2010-03-02,92.540,91.01750,92.98,88.02,90.50,0,0,0.9112903226,5.449501469 -2010-03-03,92.950,91.17350,92.98,88.02,90.50,0,0,0.9939516129,5.440177244 -2010-03-04,93.200,91.34650,93.20,88.02,90.61,1,0,1,5.670715353 -2010-03-05,91.070,91.38000,93.20,88.02,90.61,0,0,0.5888030888,5.668636463 -2010-03-06,89.830,91.33450,93.20,88.02,90.61,0,0,0.3494208494,5.671460401 -2010-03-07,89.740,91.42050,93.20,88.09,90.65,0,0,0.3228962818,5.589555953 -2010-03-08,90.400,91.53600,93.20,88.84,91.02,0,0,0.3577981651,4.763153295 -2010-03-09,95.400,91.86400,95.40,89.74,92.57,1,0,1,6.161281895 -2010-03-10,96.800,92.16500,96.80,89.74,93.27,1,0,1,7.660174687 -2010-03-11,110.000,93.13800,110.00,89.74,99.87,1,0,1,21.75266808 -2010-03-12,88.840,93.01050,110.00,88.84,99.42,0,1,0,22.75011961 -2010-03-13,90.780,93.01700,110.00,88.84,99.42,0,0,0.09168241966,22.74852984 -2010-03-14,90.540,93.00900,110.00,88.84,99.42,0,0,0.08034026465,22.75048651 -2010-03-15,91.390,92.93350,110.00,88.84,99.42,0,0,0.120510397,22.76896921 -2010-03-16,90.650,92.81700,110.00,88.84,99.42,0,0,0.08553875236,22.79754786 \ No newline at end of file +date,high,low,close,average,upper_band,lower_band,middle_band,dc_percentage,dc_band_width +2010-01-07,48.700000000000000,47.790000000000000,48.160000000000000,,,,,, +2010-01-08,48.720000000000000,48.140000000000000,48.610000000000000,,,,,, +2010-01-09,48.900000000000000,48.390000000000000,48.750000000000000,,,,,, +2010-01-10,48.870000000000000,48.370000000000000,48.630000000000000,,,,,, +2010-01-11,48.820000000000000,48.240000000000000,48.740000000000000,,,,,, +2010-01-12,49.050000000000000,48.635000000000000,49.030000000000000,,,,,, +2010-01-13,49.200000000000000,48.940000000000000,49.070000000000000,,,,,, +2010-01-14,49.350000000000000,48.860000000000000,49.320000000000000,,,,,, +2010-01-15,49.920000000000000,49.500000000000000,49.910000000000000,,,,,, +2010-01-16,50.190000000000000,49.870000000000000,50.130000000000000,,,,,, +2010-01-17,50.120000000000000,49.200000000000000,49.530000000000000,,,,,, +2010-01-18,49.660000000000000,48.900000000000000,49.500000000000000,,,,,, +2010-01-19,49.880000000000000,49.430000000000000,49.750000000000000,,,,,, +2010-01-20,50.190000000000000,49.725000000000000,50.030000000000000,,,,,, +2010-01-21,50.360000000000000,49.260000000000000,50.310000000000000,,,,,, +2010-01-22,50.570000000000000,50.090000000000000,50.520000000000000,,,,,, +2010-01-23,50.650000000000000,50.300000000000000,50.410000000000000,,,,,, +2010-01-24,50.430000000000000,49.210000000000000,49.340000000000000,,,,,, +2010-01-25,49.630000000000000,48.980000000000000,49.370000000000000,,,,,, +2010-01-26,50.330000000000000,49.610000000000000,50.230000000000000,49.46700,50.65,47.79,49.22,0.8531468531,5.781632199 +2010-01-27,50.290000000000000,49.200000000000000,49.237500000000000,49.52088,50.65,48.14,49.40,0.437250996,5.068569568 +2010-01-28,50.170000000000000,49.430000000000000,49.930000000000000,49.58688,50.65,48.24,49.45,0.7012448133,4.860157048 +2010-01-29,49.320000000000000,48.080000000000000,48.430000000000000,49.57088,50.65,48.08,49.37,0.1361867704,5.184495936 +2010-01-30,48.500000000000000,47.640000000000000,48.500000000000000,49.56438,50.65,47.64,49.15,0.2857142857,6.07291023 +2010-01-31,48.320100000000000,41.550000000000000,46.570000000000000,49.45588,50.65,41.55,46.10,0.5516483516,18.40024062 +2010-02-01,46.800000000000000,44.283300000000000,45.410000000000000,49.27488,50.65,41.55,46.10,0.4241758242,18.4678297 +2010-02-02,47.800000000000000,47.310000000000000,47.770000000000000,49.20988,50.65,41.55,46.10,0.6835164835,18.49222336 +2010-02-03,48.390000000000000,47.200000000000000,47.720000000000000,49.12988,50.65,41.55,46.10,0.678021978,18.52233493 +2010-02-04,48.660000000000000,47.900000000000000,48.620000000000000,49.06538,50.65,41.55,46.10,0.7769230769,18.54668389 +2010-02-05,48.790000000000000,47.730100000000000,47.850000000000000,48.95138,50.65,41.55,46.10,0.6923076923,18.58987618 \ No newline at end of file diff --git a/ta/tests/data/cs-dc2.csv b/ta/tests/data/cs-dc2.csv new file mode 100644 index 00000000..b41ec668 --- /dev/null +++ b/ta/tests/data/cs-dc2.csv @@ -0,0 +1,31 @@ +date,high,low,close,average,upper_band,lower_band,middle_band,dc_percentage,dc_band_width +2010-01-07,48.700000000000000,47.790000000000000,48.160000000000000,,,,,, +2010-01-08,48.720000000000000,48.140000000000000,48.610000000000000,,,,,, +2010-01-09,48.900000000000000,48.390000000000000,48.750000000000000,,,,,, +2010-01-10,48.870000000000000,48.370000000000000,48.630000000000000,,,,,, +2010-01-11,48.820000000000000,48.240000000000000,48.740000000000000,,,,,, +2010-01-12,49.050000000000000,48.635000000000000,49.030000000000000,,,,,, +2010-01-13,49.200000000000000,48.940000000000000,49.070000000000000,,,,,, +2010-01-14,49.350000000000000,48.860000000000000,49.320000000000000,,,,,, +2010-01-15,49.920000000000000,49.500000000000000,49.910000000000000,,,,,, +2010-01-16,50.190000000000000,49.870000000000000,50.130000000000000,,,,,, +2010-01-17,50.120000000000000,49.200000000000000,49.530000000000000,,,,,, +2010-01-18,49.660000000000000,48.900000000000000,49.500000000000000,,,,,, +2010-01-19,49.880000000000000,49.430000000000000,49.750000000000000,,,,,, +2010-01-20,50.190000000000000,49.725000000000000,50.030000000000000,,,,,, +2010-01-21,50.360000000000000,49.260000000000000,50.310000000000000,,,,,, +2010-01-22,50.570000000000000,50.090000000000000,50.520000000000000,,,,,, +2010-01-23,50.650000000000000,50.300000000000000,50.410000000000000,,,,,, +2010-01-24,50.430000000000000,49.210000000000000,49.340000000000000,,,,,, +2010-01-25,49.630000000000000,48.980000000000000,49.370000000000000,,,,,, +2010-01-26,50.330000000000000,49.610000000000000,50.230000000000000,,,,,, +2010-01-27,50.290000000000000,49.200000000000000,49.237500000000000,49.46700,50.65,47.79,49.22,0.8531468531,5.781632199 +2010-01-28,50.170000000000000,49.430000000000000,49.930000000000000,49.52088,50.65,48.14,49.40,0.437250996,5.068569568 +2010-01-29,49.320000000000000,48.080000000000000,48.430000000000000,49.58688,50.65,48.24,49.45,0.7012448133,4.860157048 +2010-01-30,48.500000000000000,47.640000000000000,48.500000000000000,49.57088,50.65,48.08,49.37,0.1361867704,5.184495936 +2010-01-31,48.320100000000000,41.550000000000000,46.570000000000000,49.56438,50.65,47.64,49.15,0.2857142857,6.07291023 +2010-02-01,46.800000000000000,44.283300000000000,45.410000000000000,49.45588,50.65,41.55,46.10,0.5516483516,18.40024062 +2010-02-02,47.800000000000000,47.310000000000000,47.770000000000000,49.27488,50.65,41.55,46.10,0.4241758242,18.4678297 +2010-02-03,48.390000000000000,47.200000000000000,47.720000000000000,49.20988,50.65,41.55,46.10,0.6835164835,18.49222336 +2010-02-04,48.660000000000000,47.900000000000000,48.620000000000000,49.12988,50.65,41.55,46.10,0.678021978,18.52233493 +2010-02-05,48.790000000000000,47.730100000000000,47.850000000000000,49.06538,50.65,41.55,46.10,0.7769230769,18.54668389 \ No newline at end of file diff --git a/ta/tests/volatility.py b/ta/tests/volatility.py index 9d55b81e..afbd0a01 100644 --- a/ta/tests/volatility.py +++ b/ta/tests/volatility.py @@ -7,10 +7,7 @@ bollinger_hband_indicator, bollinger_lband, bollinger_lband_indicator, bollinger_mavg, bollinger_pband, bollinger_wband, - donchian_channel_hband, - donchian_channel_hband_indicator, - donchian_channel_lband, - donchian_channel_lband_indicator, + donchian_channel_hband, donchian_channel_lband, donchian_channel_mband, donchian_channel_pband, donchian_channel_wband, keltner_channel_hband, keltner_channel_hband_indicator, @@ -177,7 +174,8 @@ class TestDonchianChannel(unittest.TestCase): @classmethod def setUpClass(cls): cls._df = pd.read_csv(cls._filename, sep=',') - cls._params = dict(close=cls._df['Close'], n=20, fillna=False) + cls._params = dict( + high=cls._df['high'], low=cls._df['low'], close=cls._df['close'], n=20, offset=0, fillna=False) cls._indicator = DonchianChannel(**cls._params) @classmethod @@ -209,16 +207,6 @@ def test_pband(self): result = self._indicator.donchian_channel_pband() pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) - def test_hband_indicator(self): - target = 'dc_high_indicator' - result = self._indicator.donchian_channel_hband_indicator() - pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) - - def test_lband_indicator(self): - target = 'dc_low_indicator' - result = self._indicator.donchian_channel_lband_indicator() - pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) - def test_mavg2(self): target = 'middle_band' result = donchian_channel_mband(**self._params) @@ -244,14 +232,74 @@ def test_pband2(self): result = donchian_channel_pband(**self._params) pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) - def test_hband_indicator2(self): - target = 'dc_high_indicator' - result = donchian_channel_hband_indicator(**self._params) + +class TestDonchianChannel2(unittest.TestCase): + """ + https://www.investopedia.com/terms/d/donchianchannels.asp + https://docs.google.com/spreadsheets/d/17JWWsxSiAb24BLzncUpccc8hg-03QjVWVXmoRCJ2lME/edit#gid=0 + """ + + _filename = 'ta/tests/data/cs-dc2.csv' + + @classmethod + def setUpClass(cls): + cls._df = pd.read_csv(cls._filename, sep=',') + cls._params = dict( + high=cls._df['high'], low=cls._df['low'], close=cls._df['close'], n=20, offset=1, fillna=False) + cls._indicator = DonchianChannel(**cls._params) + + @classmethod + def tearDownClass(cls): + del(cls._df) + + def test_mavg(self): + target = 'middle_band' + result = self._indicator.donchian_channel_mband() pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) - def test_lband_indicator2(self): - target = 'dc_low_indicator' - result = donchian_channel_lband_indicator(**self._params) + def test_hband(self): + target = 'upper_band' + result = self._indicator.donchian_channel_hband() + pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) + + def test_lband(self): + target = 'lower_band' + result = self._indicator.donchian_channel_lband() + pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) + + def test_wband(self): + target = 'dc_band_width' + result = self._indicator.donchian_channel_wband() + pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) + + def test_pband(self): + target = 'dc_percentage' + result = self._indicator.donchian_channel_pband() + pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) + + def test_mavg2(self): + target = 'middle_band' + result = donchian_channel_mband(**self._params) + pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) + + def test_hband2(self): + target = 'upper_band' + result = donchian_channel_hband(**self._params) + pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) + + def test_lband2(self): + target = 'lower_band' + result = donchian_channel_lband(**self._params) + pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) + + def test_wband2(self): + target = 'dc_band_width' + result = donchian_channel_wband(**self._params) + pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) + + def test_pband2(self): + target = 'dc_percentage' + result = donchian_channel_pband(**self._params) pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False) diff --git a/ta/volatility.py b/ta/volatility.py index ef89a1f9..36b4efb1 100644 --- a/ta/volatility.py +++ b/ta/volatility.py @@ -283,22 +283,33 @@ class DonchianChannel(IndicatorMixin): https://www.investopedia.com/terms/d/donchianchannels.asp Args: + high(pandas.Series): dataset 'High' column. + low(pandas.Series): dataset 'Low' column. close(pandas.Series): dataset 'Close' column. n(int): n period. - ndev(int): n factor standard deviation fillna(bool): if True, fill nan values. """ - def __init__(self, close: pd.Series, n: int = 20, fillna: bool = False): + def __init__( + self, + high: pd.Series, + low: pd.Series, + close: pd.Series, + n: int = 20, + offset: int = 0, + fillna: bool = False): + self._offset = offset self._close = close + self._high = high + self._low = low self._n = n self._fillna = fillna self._run() def _run(self): self.min_periods = 1 if self._fillna else self._n - self._hband = self._close.rolling(self._n, min_periods=self.min_periods).max() - self._lband = self._close.rolling(self._n, min_periods=self.min_periods).min() + self._hband = self._high.rolling(self._n, min_periods=self.min_periods).max() + self._lband = self._low.rolling(self._n, min_periods=self.min_periods).min() def donchian_channel_hband(self) -> pd.Series: """Donchian Channel High Band @@ -307,6 +318,8 @@ def donchian_channel_hband(self) -> pd.Series: pandas.Series: New feature generated. """ hband = self._check_fillna(self._hband, value=-1) + if self._offset != 0: + hband = hband.shift(self._offset) return pd.Series(hband, name='dchband') def donchian_channel_lband(self) -> pd.Series: @@ -316,6 +329,8 @@ def donchian_channel_lband(self) -> pd.Series: pandas.Series: New feature generated. """ lband = self._check_fillna(self._lband, value=-1) + if self._offset != 0: + lband = lband.shift(self._offset) return pd.Series(lband, name='dclband') def donchian_channel_mband(self) -> pd.Series: @@ -326,6 +341,8 @@ def donchian_channel_mband(self) -> pd.Series: """ mband = ((self._hband - self._lband) / 2.0) + self._lband mband = self._check_fillna(mband, value=-1) + if self._offset != 0: + mband = mband.shift(self._offset) return pd.Series(mband, name='dcmband') def donchian_channel_wband(self) -> pd.Series: @@ -337,6 +354,8 @@ def donchian_channel_wband(self) -> pd.Series: mavg = self._close.rolling(self._n, min_periods=self.min_periods).mean() wband = ((self._hband - self._lband) / mavg) * 100 wband = self._check_fillna(wband, value=0) + if self._offset != 0: + wband = wband.shift(self._offset) return pd.Series(wband, name='dcwband') def donchian_channel_pband(self) -> pd.Series: @@ -347,34 +366,10 @@ def donchian_channel_pband(self) -> pd.Series: """ pband = (self._close - self._lband) / (self._hband - self._lband) pband = self._check_fillna(pband, value=0) + if self._offset != 0: + pband = pband.shift(self._offset) return pd.Series(pband, name='dcpband') - def donchian_channel_hband_indicator(self) -> pd.Series: - """Donchian Channel Indicator Crossing High Band (binary) - - It returns 1, if close is higher than donchian_channel_hband. Else, it returns 0. - - Returns: - pandas.Series: New feature generated. - """ - hband = pd.Series(np.where( - np.isnan(self._hband), np.nan, np.where(self._close >= self._hband, 1.0, 0.0)), index=self._close.index) - hband = self._check_fillna(hband, value=0) - return pd.Series(hband, name='dcihband') - - def donchian_channel_lband_indicator(self) -> pd.Series: - """Donchian Channel Indicator Crossing Low Band (binary) - - It returns 1, if close is lower than donchian_channel_lband. Else, it returns 0. - - Returns: - pandas.Series: New feature generated. - """ - lband = pd.Series(np.where( - np.isnan(self._lband), np.nan, np.where(self._close <= self._lband, 1.0, 0.0)), index=self._close.index) - lband = self._check_fillna(lband, value=0) - return pd.Series(lband, name='dcilband') - def average_true_range(high, low, close, n=14, fillna=False): """Average True Range (ATR) @@ -708,7 +703,7 @@ def keltner_channel_lband_indicator(high, low, close, n=20, n_atr=10, fillna=Fal return indicator.keltner_channel_lband_indicator() -def donchian_channel_hband(close, n=20, fillna=False): +def donchian_channel_hband(high, low, close, n=20, offset=0, fillna=False): """Donchian Channel High Band (DC) The upper band marks the highest price of an issue for n periods. @@ -716,6 +711,8 @@ def donchian_channel_hband(close, n=20, fillna=False): https://www.investopedia.com/terms/d/donchianchannels.asp Args: + high(pandas.Series): dataset 'High' column. + low(pandas.Series): dataset 'Low' column. close(pandas.Series): dataset 'Close' column. n(int): n period. fillna(bool): if True, fill nan values. @@ -723,11 +720,11 @@ def donchian_channel_hband(close, n=20, fillna=False): Returns: pandas.Series: New feature generated. """ - indicator = DonchianChannel(close=close, n=n, fillna=fillna) + indicator = DonchianChannel(high=high, low=low, close=close, n=n, offset=offset, fillna=fillna) return indicator.donchian_channel_hband() -def donchian_channel_lband(close, n=20, fillna=False): +def donchian_channel_lband(high, low, close, n=20, offset=0, fillna=False): """Donchian Channel Low Band (DC) The lower band marks the lowest price for n periods. @@ -735,6 +732,8 @@ def donchian_channel_lband(close, n=20, fillna=False): https://www.investopedia.com/terms/d/donchianchannels.asp Args: + high(pandas.Series): dataset 'High' column. + low(pandas.Series): dataset 'Low' column. close(pandas.Series): dataset 'Close' column. n(int): n period. fillna(bool): if True, fill nan values. @@ -742,11 +741,11 @@ def donchian_channel_lband(close, n=20, fillna=False): Returns: pandas.Series: New feature generated. """ - indicator = DonchianChannel(close=close, n=n, fillna=fillna) + indicator = DonchianChannel(high=high, low=low, close=close, n=n, offset=offset, fillna=fillna) return indicator.donchian_channel_lband() -def donchian_channel_mband(close, n=10, fillna=False, ov=True): +def donchian_channel_mband(high, low, close, n=10, offset=0, fillna=False): """Donchian Channel Middle Band (DC) https://www.investopedia.com/terms/d/donchianchannels.asp @@ -761,16 +760,18 @@ def donchian_channel_mband(close, n=10, fillna=False, ov=True): Returns: pandas.Series: New feature generated. """ - indicator = DonchianChannel(close=close, n=n, fillna=fillna) + indicator = DonchianChannel(high=high, low=low, close=close, n=n, offset=offset, fillna=fillna) return indicator.donchian_channel_mband() -def donchian_channel_wband(close, n=10, fillna=False): +def donchian_channel_wband(high, low, close, n=10, offset=0, fillna=False): """Donchian Channel Band Width (DC) https://www.investopedia.com/terms/d/donchianchannels.asp Args: + high(pandas.Series): dataset 'High' column. + low(pandas.Series): dataset 'Low' column. close(pandas.Series): dataset 'Close' column. n(int): n period. fillna(bool): if True, fill nan values. @@ -778,16 +779,18 @@ def donchian_channel_wband(close, n=10, fillna=False): Returns: pandas.Series: New feature generated. """ - indicator = DonchianChannel(close=close, n=n, fillna=fillna) + indicator = DonchianChannel(high=high, low=low, close=close, n=n, offset=offset, fillna=fillna) return indicator.donchian_channel_wband() -def donchian_channel_pband(close, n=10, fillna=False): +def donchian_channel_pband(high, low, close, n=10, offset=0, fillna=False): """Donchian Channel Percentage Band (DC) https://www.investopedia.com/terms/d/donchianchannels.asp Args: + high(pandas.Series): dataset 'High' column. + low(pandas.Series): dataset 'Low' column. close(pandas.Series): dataset 'Close' column. n(int): n period. fillna(bool): if True, fill nan values. @@ -795,45 +798,5 @@ def donchian_channel_pband(close, n=10, fillna=False): Returns: pandas.Series: New feature generated. """ - indicator = DonchianChannel(close=close, n=n, fillna=fillna) + indicator = DonchianChannel(high=high, low=low, close=close, n=n, offset=offset, fillna=fillna) return indicator.donchian_channel_pband() - - -def donchian_channel_hband_indicator(close, n=20, fillna=False): - """Donchian High Band Indicator (DC) - - Returns 1, if close is higher than donchian high band channel. Else, - return 0. - - https://www.investopedia.com/terms/d/donchianchannels.asp - - Args: - close(pandas.Series): dataset 'Close' column. - n(int): n period. - fillna(bool): if True, fill nan values. - - Returns: - pandas.Series: New feature generated. - """ - indicator = DonchianChannel(close=close, n=n, fillna=fillna) - return indicator.donchian_channel_hband_indicator() - - -def donchian_channel_lband_indicator(close, n=20, fillna=False): - """Donchian Low Band Indicator (DC) - - Returns 1, if close is lower than donchian low band channel. Else, - return 0. - - https://www.investopedia.com/terms/d/donchianchannels.asp - - Args: - close(pandas.Series): dataset 'Close' column. - n(int): n period. - fillna(bool): if True, fill nan values. - - Returns: - pandas.Series: New feature generated. - """ - indicator = DonchianChannel(close=close, n=n, fillna=fillna) - return indicator.donchian_channel_lband_indicator() diff --git a/ta/wrapper.py b/ta/wrapper.py index 77f3b41c..a59704a3 100644 --- a/ta/wrapper.py +++ b/ta/wrapper.py @@ -124,11 +124,12 @@ def add_volatility_ta(df: pd.DataFrame, high: str, low: str, close: str, df[f'{colprefix}volatility_kcli'] = indicator_kc.keltner_channel_lband_indicator() # Donchian Channel - indicator_dc = DonchianChannel(close=df[close], n=20, fillna=fillna) + indicator_dc = DonchianChannel(high=df[high], low=df[low], close=df[close], n=20, offset=0, fillna=fillna) df[f'{colprefix}volatility_dcl'] = indicator_dc.donchian_channel_lband() df[f'{colprefix}volatility_dch'] = indicator_dc.donchian_channel_hband() - df[f'{colprefix}volatility_dchi'] = indicator_dc.donchian_channel_hband_indicator() - df[f'{colprefix}volatility_dcli'] = indicator_dc.donchian_channel_lband_indicator() + df[f'{colprefix}volatility_dch'] = indicator_dc.donchian_channel_mband() + df[f'{colprefix}volatility_dcl'] = indicator_dc.donchian_channel_wband() + df[f'{colprefix}volatility_dch'] = indicator_dc.donchian_channel_pband() return df