From 9352cbf8ec3ba794812d1c727a92df9be5ef55e8 Mon Sep 17 00:00:00 2001 From: Lluis Date: Wed, 20 May 2020 16:07:06 +0200 Subject: [PATCH] Add above and below functions --- pandas_ta/core.py | 34 ++++++++++++++++++++++++++++++++++ pandas_ta/utils.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/pandas_ta/core.py b/pandas_ta/core.py index 6eb579d..6f6fbe4 100644 --- a/pandas_ta/core.py +++ b/pandas_ta/core.py @@ -836,6 +836,40 @@ class AnalysisIndicators(BasePandasObject): self._append(result, **kwargs) return result + def above(self, a=None, b=None, asint=True, offset=None, **kwargs): + if a is None and b is None: return self._df + else: + a = self._get_column(a, f"{a}") + b = self._get_column(b, f"{b}") + result = above(series_a=a, series_b=b, asint=asint, offset=offset, **kwargs) + self._append(result, **kwargs) + return result + + def above_value(self, a=None, value=None, asint=True, offset=None, **kwargs): + if a is None and value is None: return self._df + else: + a = self._get_column(a, f"{a}") + result = above_value(series_a=a, value=value, asint=asint, offset=offset, **kwargs) + self._append(result, **kwargs) + return result + + def below(self, a=None, b=None, asint=True, offset=None, **kwargs): + if a is None and b is None: return self._df + else: + a = self._get_column(a, f"{a}") + b = self._get_column(b, f"{b}") + result = below(series_a=a, series_b=b, asint=asint, offset=offset, **kwargs) + self._append(result, **kwargs) + return result + + def below_value(self, a=None, value=None, asint=True, offset=None, **kwargs): + if a is None and value is None: return self._df + else: + a = self._get_column(a, f"{a}") + result = below_value(series_a=a, value=value, asint=asint, offset=offset, **kwargs) + self._append(result, **kwargs) + return result + # Volatility Indicators diff --git a/pandas_ta/utils.py b/pandas_ta/utils.py index a92243d..cca1f30 100644 --- a/pandas_ta/utils.py +++ b/pandas_ta/utils.py @@ -57,6 +57,52 @@ def cross(series_a:pd.Series, series_b:pd.Series, above:bool =True, asint:bool = return cross +def above(series_a:pd.Series, series_b:pd.Series, asint:bool =True, offset:int =None, **kwargs): + return _above_below(series_a, series_b, above=True, asint=asint, offset=offset, **kwargs) + + +def above_value(series_a:pd.Series, value:float, asint:bool =True, offset:int =None, **kwargs): + series_b = pd.Series(value, index=series_a.index, name=f'{value}'.replace('.','_')) + return _above_below(series_a, series_b, above=True, asint=asint, offset=offset, **kwargs) + + +def below(series_a:pd.Series, series_b:pd.Series, asint:bool =True, offset:int =None, **kwargs): + return _above_below(series_a, series_b, above=False, asint=asint, offset=offset, **kwargs) + + +def below_value(series_a:pd.Series, value:float, asint:bool =True, offset:int =None, **kwargs): + series_b = pd.Series(value, index=series_a.index, name=f'{value}'.replace('.','_')) + return _above_below(series_a, series_b, above=False, asint=asint, offset=offset, **kwargs) + + +def _above_below(series_a:pd.Series, series_b:pd.Series, above:bool =True, asint:bool =True, offset:int =None, **kwargs): + series_a = verify_series(series_a) + series_b = verify_series(series_b) + offset = get_offset(offset) + + series_a.apply(zero) + series_b.apply(zero) + + # Calculate Result + if above: + current = series_a >= series_b + else: + current = series_a <= series_b + + if asint: + current = current.astype(int) + + # Offset + if offset != 0: + current = current.shift(offset) + + # Name & Category + current.name = f"{series_a.name}_{'A' if above else 'B'}_{series_b.name}" + current.category = 'utility' + + return current + + def df_error_analysis(dfA:pd.DataFrame, dfB:pd.DataFrame, **kwargs): """ """ col = kwargs.pop('col', None)