From ed62cbc51fcf83f155b489f38f34ab79a3605091 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Fri, 10 Feb 2023 22:41:53 -0500 Subject: [PATCH 01/17] Add files via upload Bull Bear Index BBI --- pandas_ta/trend/bbi.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 pandas_ta/trend/bbi.py diff --git a/pandas_ta/trend/bbi.py b/pandas_ta/trend/bbi.py new file mode 100644 index 00000000..afc26a9a --- /dev/null +++ b/pandas_ta/trend/bbi.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +""" +Indicator: BBI Bull Bear Index +While this was inspired by Tushare, I found a different way to calculate this at https://www.tradingview.com/script/KvLCcuHB-BBI-4MA-4-overlay/ + + +""" +from pandas_ta.overlap import ma +import numpy as np + +def bbi(data, shorter=None, short=None, long=None, longer=None): + #usually a 3, 6, 12, and 24 day sma is used here I think + #but it may be more useful to allow this to be changed + shorter = shorter if shorter and shorter > 0 else 3 + short = short if short and short > 0 else 6 + long = long if long and long > 0 else 12 + longer = longer if longer and longer > 0 else 24 + + + + CS = [] + BBI = [] + for index, row in data.iterrows(): + CS.append(row["close"]) + + if len(CS) < 24: + BBI.append(row["close"]) + else: + #bbi = np.average([np.average(CS[-3:]), np.average(CS[-6:]), np.average(CS[-12:]), np.average(CS[-24:])]) + bbi = (ma("sma", CS[-shorter:], length=shorter)+ma("sma", CS[-short:], length=short)+ma("sma", CS[-long:], length=long)+ma("sma", CS[-longer:], length=longer)/4) + BBI.append(bbi) + + return np.asarray(BBI) \ No newline at end of file From d4b748d78256440d4d17c1c77cd6951bdeeb1fd1 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Fri, 10 Feb 2023 22:57:45 -0500 Subject: [PATCH 02/17] ASI Accumulation Swing Index --- pandas_ta/volatility/asi.py | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 pandas_ta/volatility/asi.py diff --git a/pandas_ta/volatility/asi.py b/pandas_ta/volatility/asi.py new file mode 100644 index 00000000..92a196ba --- /dev/null +++ b/pandas_ta/volatility/asi.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +""" +Indicator: ASI Accumulation Swing Index +Inspired by tushare +""" +import numpy as np +from pandas_ta.overlap import ma + +def asi(data, n=None): + + n = n if n and n > 0 else 5 + + SI = [] + for index, row in data.iterrows(): + if index == 0: + last_row = row + SI.append(0.) + else: + + a = abs(row["close"] - last_row["close"]) + b = abs(row["low"] - last_row["close"]) + c = abs(row["high"] - last_row["close"]) + d = abs(last_row["close"] - last_row["open"]) + + if b > a and b > c: + r = b + (1 / 2) * a + (1 / 4) * d + elif c > a and c > b: + r = c + (1 / 4) * d + else: + r = 0 + + e = row["close"] - last_row["close"] + f = row["close"] - last_row["open"] + g = last_row["close"] - last_row["open"] + + x = e + (1 / 2) * f + g + k = max(a, b) + l = 3 + + if np.isclose(r, 0) or np.isclose(l, 0): + si = 0 + else: + si = 50 * (x / r) * (k / l) + + SI.append(si) + + ASI = ma("sma",SI, n) + return ASI From 0000258beed7528221fa9e12df0039425771dcb5 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Fri, 10 Feb 2023 23:29:58 -0500 Subject: [PATCH 03/17] WR Williams Overbought/Oversold Index --- pandas_ta/trend/wr.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 pandas_ta/trend/wr.py diff --git a/pandas_ta/trend/wr.py b/pandas_ta/trend/wr.py new file mode 100644 index 00000000..f9f05953 --- /dev/null +++ b/pandas_ta/trend/wr.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +""" +WR Williams Overbought/Oversold Index +TODO: change input to rows and not entire dataframe + +""" + +def wnr(data, n=None): + n = n if n and n > 0 else 14 + + + high_prices = [] + low_prices = [] + WNR = [] + + for index, row in data.iterrows(): + high_prices.append(row["high"]) + if len(high_prices) == n: + del high_prices[0] + low_prices.append(row["low"]) + if len(low_prices) == n: + del low_prices[0] + + highest = max(high_prices) + lowest = min(low_prices) + + wnr = (highest - row["close"]) / (highest - lowest) * 100 + WNR.append(wnr) + + return WNR \ No newline at end of file From e98eee2e166de676b6d1529949e3e2221c169f34 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Fri, 10 Feb 2023 23:30:52 -0500 Subject: [PATCH 04/17] VR Volatility Volume Ratio --- pandas_ta/volume/vr.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 pandas_ta/volume/vr.py diff --git a/pandas_ta/volume/vr.py b/pandas_ta/volume/vr.py new file mode 100644 index 00000000..1f6a4f42 --- /dev/null +++ b/pandas_ta/volume/vr.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +""" +VR Volatility Volume Ratio +TODO: change input to rows and not entire dataframe +""" +import numpy as np + +def vr(data, n=None): + n = n if n and n > 0 else 26 + + + VR = [] + + AV_volumes, BV_volumes, CV_volumes = [], [], [] + for index, row in data.iterrows(): + + if row["close"] > row["open"]: + AV_volumes.append(row["volume"]) + elif row["close"] < row["open"]: + BV_volumes.append(row["volume"]) + else: + CV_volumes.append(row["volume"]) + + if len(AV_volumes) == n: + del AV_volumes[0] + if len(BV_volumes) == n: + del BV_volumes[0] + if len(CV_volumes) == n: + del CV_volumes[0] + + avs = sum(AV_volumes) + bvs = sum(BV_volumes) + cvs = sum(CV_volumes) + + if (bvs + (1 / 2) * cvs) != 0: + vr = (avs + (1 / 2) * cvs) / (bvs + (1 / 2) * cvs) + else: + vr = 0 + + VR.append(vr) + + return np.asarray(VR) \ No newline at end of file From c562d673ae1b7b8c69a370fb6ab1fdc4b33d28b9 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Fri, 10 Feb 2023 23:39:26 -0500 Subject: [PATCH 05/17] KDJ Stochastics --- pandas_ta/momentum/kdj.py | 135 ++++++++++---------------------------- 1 file changed, 35 insertions(+), 100 deletions(-) diff --git a/pandas_ta/momentum/kdj.py b/pandas_ta/momentum/kdj.py index f941e28f..069523ea 100644 --- a/pandas_ta/momentum/kdj.py +++ b/pandas_ta/momentum/kdj.py @@ -1,100 +1,35 @@ -# -*- coding: utf-8 -*- -from pandas import DataFrame -from pandas_ta.overlap import rma -from pandas_ta.utils import get_offset, non_zero_range, verify_series - - -def kdj(high=None, low=None, close=None, length=None, signal=None, offset=None, **kwargs): - """Indicator: KDJ (KDJ)""" - # Validate Arguments - length = int(length) if length and length > 0 else 9 - signal = int(signal) if signal and signal > 0 else 3 - _length = max(length, signal) - high = verify_series(high, _length) - low = verify_series(low, _length) - close = verify_series(close, _length) - offset = get_offset(offset) - - if high is None or low is None or close is None: return - - # Calculate Result - highest_high = high.rolling(length).max() - lowest_low = low.rolling(length).min() - - fastk = 100 * (close - lowest_low) / non_zero_range(highest_high, lowest_low) - - k = rma(fastk, length=signal) - d = rma(k, length=signal) - j = 3 * k - 2 * d - - # Offset - if offset != 0: - k = k.shift(offset) - d = d.shift(offset) - j = j.shift(offset) - - # Handle fills - if "fillna" in kwargs: - k.fillna(kwargs["fillna"], inplace=True) - d.fillna(kwargs["fillna"], inplace=True) - j.fillna(kwargs["fillna"], inplace=True) - if "fill_method" in kwargs: - k.fillna(method=kwargs["fill_method"], inplace=True) - d.fillna(method=kwargs["fill_method"], inplace=True) - j.fillna(method=kwargs["fill_method"], inplace=True) - - # Name and Categorize it - _params = f"_{length}_{signal}" - k.name = f"K{_params}" - d.name = f"D{_params}" - j.name = f"J{_params}" - k.category = d.category = j.category = "momentum" - - # Prepare DataFrame to return - kdjdf = DataFrame({k.name: k, d.name: d, j.name: j}) - kdjdf.name = f"KDJ{_params}" - kdjdf.category = "momentum" - - return kdjdf - - -kdj.__doc__ = \ -"""KDJ (KDJ) - -The KDJ indicator is actually a derived form of the Slow -Stochastic with the only difference being an extra line -called the J line. The J line represents the divergence -of the %D value from the %K. The value of J can go -beyond [0, 100] for %K and %D lines on the chart. - -Sources: - https://www.prorealcode.com/prorealtime-indicators/kdj/ - https://docs.anychart.com/Stock_Charts/Technical_Indicators/Mathematical_Description#kdj - -Calculation: - Default Inputs: - length=9, signal=3 - LL = low for last 9 periods - HH = high for last 9 periods - - FAST_K = 100 * (close - LL) / (HH - LL) - - K = RMA(FAST_K, signal) - D = RMA(K, signal) - J = 3K - 2D - -Args: - high (pd.Series): Series of 'high's - low (pd.Series): Series of 'low's - close (pd.Series): Series of 'close's - length (int): Default: 9 - signal (int): Default: 3 - 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. -""" +# -*- coding: utf-8 -*- +""" +KDJ + +Not sure if this is the same as the existing Stochastic Indicator +Please reference https://www.moomoo.com/us/learn/detail-what-is-the-kdj-67019-220809006 +TODO: Change input to rows rather than entire dataframe +""" +import numpy as np +def kdj(data): + + + + K, D, J = [], [], [] + last_k, last_d = None, None + for index, row in data.iterrows(): + if last_k is None or last_d is None: + last_k = 50 + last_d = 50 + + c, l, h = row["close"], row["low"], row["high"] + + rsv = (c - l) / (h - l) * 100 + + k = (2 / 3) * last_k + (1 / 3) * rsv + d = (2 / 3) * last_d + (1 / 3) * k + j = 3 * k - 2 * d + + K.append(k) + D.append(d) + J.append(j) + + last_k, last_d = k, d + + return np.asarray(K), np.asarray(D), np.asarray(J) \ No newline at end of file From 99af815ed5b3cbad84179e4e02567ee9d852496a Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Fri, 10 Feb 2023 23:45:30 -0500 Subject: [PATCH 06/17] Update kdj.py Changed input arguments --- pandas_ta/momentum/kdj.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/pandas_ta/momentum/kdj.py b/pandas_ta/momentum/kdj.py index 069523ea..c18154cc 100644 --- a/pandas_ta/momentum/kdj.py +++ b/pandas_ta/momentum/kdj.py @@ -4,32 +4,32 @@ Not sure if this is the same as the existing Stochastic Indicator Please reference https://www.moomoo.com/us/learn/detail-what-is-the-kdj-67019-220809006 -TODO: Change input to rows rather than entire dataframe """ import numpy as np -def kdj(data): +def kdj(close, low, high): K, D, J = [], [], [] last_k, last_d = None, None - for index, row in data.iterrows(): - if last_k is None or last_d is None: - last_k = 50 - last_d = 50 + for c in close: + for l in low: + for h in high: + if last_k is None or last_d is None: + last_k = 50 + last_d = 50 - c, l, h = row["close"], row["low"], row["high"] - rsv = (c - l) / (h - l) * 100 + rsv = (c - l) / (h - l) * 100 - k = (2 / 3) * last_k + (1 / 3) * rsv - d = (2 / 3) * last_d + (1 / 3) * k - j = 3 * k - 2 * d + k = (2 / 3) * last_k + (1 / 3) * rsv + d = (2 / 3) * last_d + (1 / 3) * k + j = 3 * k - 2 * d - K.append(k) - D.append(d) - J.append(j) + K.append(k) + D.append(d) + J.append(j) - last_k, last_d = k, d + last_k, last_d = k, d - return np.asarray(K), np.asarray(D), np.asarray(J) \ No newline at end of file + return np.asarray(K), np.asarray(D), np.asarray(J) From 0ba7980e6a1a3dbc942f440bc06199b999f1f6b0 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 09:51:44 -0500 Subject: [PATCH 07/17] Update kdj.py Tested on some data to see if it returns the same as the tushare function it is based on --- pandas_ta/momentum/kdj.py | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/pandas_ta/momentum/kdj.py b/pandas_ta/momentum/kdj.py index c18154cc..ac09e293 100644 --- a/pandas_ta/momentum/kdj.py +++ b/pandas_ta/momentum/kdj.py @@ -8,28 +8,22 @@ import numpy as np def kdj(close, low, high): - - + rsv = (close - low) / (high - low) * 100 K, D, J = [], [], [] - last_k, last_d = None, None - for c in close: - for l in low: - for h in high: - if last_k is None or last_d is None: - last_k = 50 - last_d = 50 - + print((rsv)) - rsv = (c - l) / (h - l) * 100 - k = (2 / 3) * last_k + (1 / 3) * rsv - d = (2 / 3) * last_d + (1 / 3) * k - j = 3 * k - 2 * d + K.append( (2 / 3) * 50 + (1 / 3) * rsv[0]) + + + D.append((2 / 3) * 50 + (1 / 3) * K[0]) + + for i in range(1,len(rsv)): + K.append((2 / 3) * K[i-1] + (1 / 3) * rsv[i]) + D.append((2 / 3) * D[i-1] + (1 / 3) * K[i]) + J.append(3 * K[i] - 2 * D[i]) - K.append(k) - D.append(d) - J.append(j) - last_k, last_d = k, d + return np.asarray(K), np.asarray(D), np.asarray(J) From e23e47677c1dad03237f040cdae46d4707986e4b Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 09:52:47 -0500 Subject: [PATCH 08/17] Update kdj.py --- pandas_ta/momentum/kdj.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas_ta/momentum/kdj.py b/pandas_ta/momentum/kdj.py index ac09e293..a97cca9e 100644 --- a/pandas_ta/momentum/kdj.py +++ b/pandas_ta/momentum/kdj.py @@ -10,7 +10,6 @@ def kdj(close, low, high): rsv = (close - low) / (high - low) * 100 K, D, J = [], [], [] - print((rsv)) K.append( (2 / 3) * 50 + (1 / 3) * rsv[0]) From 8ce566119bfe6b19f3da9490929e714a4da9524b Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 11:26:13 -0500 Subject: [PATCH 09/17] Update kdj.py --- pandas_ta/momentum/kdj.py | 40 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/pandas_ta/momentum/kdj.py b/pandas_ta/momentum/kdj.py index a97cca9e..31c60d36 100644 --- a/pandas_ta/momentum/kdj.py +++ b/pandas_ta/momentum/kdj.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- + """ KDJ @@ -6,8 +6,22 @@ Please reference https://www.moomoo.com/us/learn/detail-what-is-the-kdj-67019-220809006 """ import numpy as np +import pandas as pd +from pandas_ta.utils import verify_series def kdj(close, low, high): + # Validate arguments + + close = verify_series(close) + low = verify_series(low) + high = verify_series(high) + + if close is None: return + if low is None: return + if open is None: return + + #calculate + rsv = (close - low) / (high - low) * 100 K, D, J = [], [], [] @@ -17,12 +31,32 @@ def kdj(close, low, high): D.append((2 / 3) * 50 + (1 / 3) * K[0]) + J.append(3 * K[0] - 2 * D[0]) + for i in range(1,len(rsv)): K.append((2 / 3) * K[i-1] + (1 / 3) * rsv[i]) D.append((2 / 3) * D[i-1] + (1 / 3) * K[i]) J.append(3 * K[i] - 2 * D[i]) + + # Prepare DataFrame to return + + K = pd.DataFrame(K) + D = pd.DataFrame(D) + J = pd.DataFrame(J) + + + K.name = 'STOCH_K_TUSHARE' + D.name = 'STOCH_D_TUSHARE' + J.name = 'STOCH_J_TUSHARE' + + K.category = D.category = J.category = "momentum" - + df = pd.DataFrame() + df["K"] = K + df["D"] = D + df["J"] = J - return np.asarray(K), np.asarray(D), np.asarray(J) + df.name = 'KDJ' + df.category = K.category + return df From 526f525a9bd04cbf4f60ce4c899459202491a54a Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 13:26:49 -0500 Subject: [PATCH 10/17] Update vr.py --- pandas_ta/volume/vr.py | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/pandas_ta/volume/vr.py b/pandas_ta/volume/vr.py index 1f6a4f42..91ff6780 100644 --- a/pandas_ta/volume/vr.py +++ b/pandas_ta/volume/vr.py @@ -1,25 +1,36 @@ -# -*- coding: utf-8 -*- """ VR Volatility Volume Ratio -TODO: change input to rows and not entire dataframe """ import numpy as np +from pandas_ta.utils import verify_series +import pandas as pd -def vr(data, n=None): +def vr(close, open, volume, n=None): + + # Validate arguments n = n if n and n > 0 else 26 + close = verify_series(close) + open = verify_series(open) + volume = verify_series(volume) + + if close is None: return + if volume is None: return + if open is None: return + + #calculate VR = [] AV_volumes, BV_volumes, CV_volumes = [], [], [] - for index, row in data.iterrows(): + for i in range(0,len(close)): - if row["close"] > row["open"]: - AV_volumes.append(row["volume"]) - elif row["close"] < row["open"]: - BV_volumes.append(row["volume"]) + if close[i] > open[i]: + AV_volumes.append(volume[i]) + elif close[i] < open[i]: + BV_volumes.append(volume[i]) else: - CV_volumes.append(row["volume"]) + CV_volumes.append(volume[i]) if len(AV_volumes) == n: del AV_volumes[0] @@ -36,7 +47,11 @@ def vr(data, n=None): vr = (avs + (1 / 2) * cvs) / (bvs + (1 / 2) * cvs) else: vr = 0 - VR.append(vr) + # Prepare DataFrame to return + Final = pd.DataFrame(VR) + Final.name = "Volatility_Volume_Ratio" + Final.category = "volume" + - return np.asarray(VR) \ No newline at end of file + return Final From 821733825e1f4d5fa5ef7a0d1f8bead179c8db4c Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 13:49:21 -0500 Subject: [PATCH 11/17] Update vr.py --- pandas_ta/volume/vr.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas_ta/volume/vr.py b/pandas_ta/volume/vr.py index 91ff6780..a210f323 100644 --- a/pandas_ta/volume/vr.py +++ b/pandas_ta/volume/vr.py @@ -49,9 +49,9 @@ def vr(close, open, volume, n=None): vr = 0 VR.append(vr) # Prepare DataFrame to return - Final = pd.DataFrame(VR) - Final.name = "Volatility_Volume_Ratio" - Final.category = "volume" + VR = pd.DataFrame(VR) + VR.name = "Volatility_Volume_Ratio" + VR.category = "volume" - return Final + return VR From db2955f15da553cc1c5c261c26eb8eca0847963d Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 13:53:58 -0500 Subject: [PATCH 12/17] Update wr.py --- pandas_ta/trend/wr.py | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/pandas_ta/trend/wr.py b/pandas_ta/trend/wr.py index f9f05953..c58d7b4f 100644 --- a/pandas_ta/trend/wr.py +++ b/pandas_ta/trend/wr.py @@ -1,30 +1,47 @@ -# -*- coding: utf-8 -*- """ WR Williams Overbought/Oversold Index -TODO: change input to rows and not entire dataframe -""" -def wnr(data, n=None): +""" +import pandas as pd +from pandas_ta.utils import verify_series + +def wnr(close, low, high, n=None): + + # Validate arguments + + close = verify_series(close) + low = verify_series(low) + high = verify_series(high) + + if close is None: return + if low is None: return + if open is None: return n = n if n and n > 0 else 14 - + #calculate + high_prices = [] low_prices = [] WNR = [] - for index, row in data.iterrows(): - high_prices.append(row["high"]) + for i in range(0,len(close)): + high_prices.append(high[i]) if len(high_prices) == n: del high_prices[0] - low_prices.append(row["low"]) + low_prices.append(low[i]) if len(low_prices) == n: del low_prices[0] highest = max(high_prices) lowest = min(low_prices) - wnr = (highest - row["close"]) / (highest - lowest) * 100 + wnr = (highest - close[i]) / (highest - lowest) * 100 WNR.append(wnr) + # Prepare DataFrame to return + WNR = pd.DataFrame(WNR) + WNR.category = "trend" + WNR.name = "Williams_Index" + + return WNR - return WNR \ No newline at end of file From a8e7292877d50718d313382e1c477092c173021f Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 13:58:08 -0500 Subject: [PATCH 13/17] Update kdj.py --- pandas_ta/momentum/kdj.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas_ta/momentum/kdj.py b/pandas_ta/momentum/kdj.py index 31c60d36..e8dada51 100644 --- a/pandas_ta/momentum/kdj.py +++ b/pandas_ta/momentum/kdj.py @@ -18,7 +18,7 @@ def kdj(close, low, high): if close is None: return if low is None: return - if open is None: return + if high is None: return #calculate From e3c2d7e4131008dc37ce68857bf60d9d68256317 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 15:45:18 -0500 Subject: [PATCH 14/17] Update asi.py --- pandas_ta/volatility/asi.py | 79 ++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/pandas_ta/volatility/asi.py b/pandas_ta/volatility/asi.py index 92a196ba..11f91c65 100644 --- a/pandas_ta/volatility/asi.py +++ b/pandas_ta/volatility/asi.py @@ -1,48 +1,65 @@ -# -*- coding: utf-8 -*- """ Indicator: ASI Accumulation Swing Index Inspired by tushare + """ import numpy as np from pandas_ta.overlap import ma +import pandas as pd +from pandas_ta.utils import verify_series -def asi(data, n=None): - +def asi(close, low, high, open, n=None): + + # Validate arguments + + close = verify_series(close) + low = verify_series(low) + high = verify_series(high) + open = verify_series(open) + + if close is None: return + if low is None: return + if high is None: return + if open is None: return + n = n if n and n > 0 else 5 - + #calculate SI = [] - for index, row in data.iterrows(): - if index == 0: - last_row = row - SI.append(0.) - else: + SI.append(0.) - a = abs(row["close"] - last_row["close"]) - b = abs(row["low"] - last_row["close"]) - c = abs(row["high"] - last_row["close"]) - d = abs(last_row["close"] - last_row["open"]) + for i in range(1,len(close)): + a = abs(close[i] - close[i-1]) + b = abs(low[i] - close[i-1]) + c = abs(high[i] - close[i-1]) + d = abs(close[i-1] - open[i-1]) - if b > a and b > c: - r = b + (1 / 2) * a + (1 / 4) * d - elif c > a and c > b: - r = c + (1 / 4) * d - else: - r = 0 + if b > a and b > c: + r = b + (1 / 2) * a + (1 / 4) * d + elif c > a and c > b: + r = c + (1 / 4) * d + else: + r = 0 + + e = close[i] - close[i-1] + f = close[i] - open[i-1] + g = close[i-1] - open[i-1] - e = row["close"] - last_row["close"] - f = row["close"] - last_row["open"] - g = last_row["close"] - last_row["open"] + x = e + (1 / 2) * f + g + k = max(a, b) + l = 3 - x = e + (1 / 2) * f + g - k = max(a, b) - l = 3 + if np.isclose(r, 0) or np.isclose(l, 0): + si = 0 + else: + si = 50 * (x / r) * (k / l) - if np.isclose(r, 0) or np.isclose(l, 0): - si = 0 - else: - si = 50 * (x / r) * (k / l) + SI.append(si) - SI.append(si) + # Prepare DataFrame to return + SI = pd.DataFrame(SI) - ASI = ma("sma",SI, n) + ASI = SI.rolling(n).mean() + ASI.name = 'ASI' + ASI.category = 'volatility' return ASI + From 5afa9b559924c5d6cdd57afe5d9570a52837b074 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 15:53:44 -0500 Subject: [PATCH 15/17] Update bbi.py --- pandas_ta/trend/bbi.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/pandas_ta/trend/bbi.py b/pandas_ta/trend/bbi.py index afc26a9a..f5d7ccce 100644 --- a/pandas_ta/trend/bbi.py +++ b/pandas_ta/trend/bbi.py @@ -1,14 +1,17 @@ -# -*- coding: utf-8 -*- """ Indicator: BBI Bull Bear Index While this was inspired by Tushare, I found a different way to calculate this at https://www.tradingview.com/script/KvLCcuHB-BBI-4MA-4-overlay/ - """ from pandas_ta.overlap import ma import numpy as np +import pandas as pd +from pandas_ta.utils import verify_series -def bbi(data, shorter=None, short=None, long=None, longer=None): +def bbi(close, shorter=None, short=None, long=None, longer=None): + # Validate arguments + close = verify_series(close) + if close is None: return #usually a 3, 6, 12, and 24 day sma is used here I think #but it may be more useful to allow this to be changed shorter = shorter if shorter and shorter > 0 else 3 @@ -20,14 +23,20 @@ def bbi(data, shorter=None, short=None, long=None, longer=None): CS = [] BBI = [] - for index, row in data.iterrows(): - CS.append(row["close"]) + for i in range(0,len(close)): + CS.append(close[i]) if len(CS) < 24: - BBI.append(row["close"]) + BBI.append(close[i]) else: #bbi = np.average([np.average(CS[-3:]), np.average(CS[-6:]), np.average(CS[-12:]), np.average(CS[-24:])]) bbi = (ma("sma", CS[-shorter:], length=shorter)+ma("sma", CS[-short:], length=short)+ma("sma", CS[-long:], length=long)+ma("sma", CS[-longer:], length=longer)/4) BBI.append(bbi) + + # Prepare DataFrame to return + BBI = pd.DataFrame(BBI) + BBI.name = 'BBI' + BBI.category = 'trend' + return BBI + - return np.asarray(BBI) \ No newline at end of file From 3a8e9fdec75a7ff60fa9c441a915764b9aa4d7e2 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 16:23:03 -0500 Subject: [PATCH 16/17] Add files via upload ADXR --- pandas_ta/trend/adxr.py | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 pandas_ta/trend/adxr.py diff --git a/pandas_ta/trend/adxr.py b/pandas_ta/trend/adxr.py new file mode 100644 index 00000000..482b65cd --- /dev/null +++ b/pandas_ta/trend/adxr.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +""" +ADXR +""" + +import numpy as np +import pandas as pd +from pandas_ta.utils import verify_series +from pandas_ta.trend import adx +def adxr(high, low, close, n=None): + + # Validate arguments + close = verify_series(close) + low = verify_series(low) + high = verify_series(high) + + + if close is None: return + if low is None: return + if high is None: return + + n = n if n and n > 0 else 6 + + ADX = adx(high, low, close, length=n).iloc[:, 0] + print(ADX) + ADXR = [] + + for i in range(0,len(close)): + + if i>= n: + adxr = (ADX[i] + ADX[i - n]) / 2 + ADXR.append(adxr) + else: + ADXR.append(0) + + # Prepare DataFrame to return + + ADXR = pd.DataFrame(ADXR) + ADXR.name = 'ADXR' + ADXR.category = 'trend' + return ADXR + + + +#test +''' +import yfinance as yf +df = yf.download(tickers = 'GD' , period='20d', interval='1d') +print(adxr(df['High'], df['Low'], df['Close'])) +#print(df) +''' \ No newline at end of file From f944d2d2902ec88380ca3c6d0e94c94c44791436 Mon Sep 17 00:00:00 2001 From: andymc31 <72295085+andymc31@users.noreply.github.com> Date: Sat, 11 Feb 2023 16:23:34 -0500 Subject: [PATCH 17/17] Update adxr.py --- pandas_ta/trend/adxr.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pandas_ta/trend/adxr.py b/pandas_ta/trend/adxr.py index 482b65cd..6914e249 100644 --- a/pandas_ta/trend/adxr.py +++ b/pandas_ta/trend/adxr.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ ADXR """ @@ -39,13 +38,3 @@ def adxr(high, low, close, n=None): ADXR.name = 'ADXR' ADXR.category = 'trend' return ADXR - - - -#test -''' -import yfinance as yf -df = yf.download(tickers = 'GD' , period='20d', interval='1d') -print(adxr(df['High'], df['Low'], df['Close'])) -#print(df) -''' \ No newline at end of file