From 443a630493d19ea5a0c7698d98f5eed05fff50ca Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Mon, 24 Mar 2025 13:38:20 +0100 Subject: [PATCH] fix(qacv3): properly handle zero range in series MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../user_data/strategies/QuickAdapterV3.py | 16 +++++++++------- quickadapter/user_data/strategies/Utils.py | 13 +++++++++++-- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 1910b18..ea4d31e 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -19,6 +19,7 @@ import pandas_ta as pta from Utils import ( ewo, + non_zero_range, vwapb, top_change_percent, get_distance, @@ -55,7 +56,7 @@ class QuickAdapterV3(IStrategy): INTERFACE_VERSION = 3 def version(self) -> str: - return "3.1.14" + return "3.1.15" timeframe = "5m" @@ -194,7 +195,6 @@ class QuickAdapterV3(IStrategy): dataframe["close"], dataframe["volume"], length=period, - fillna=0.0, ) dataframe["%-tcp-period"] = top_change_percent(dataframe, period=period) # dataframe["%-bcp-period"] = bottom_change_percent(dataframe, period=period) @@ -252,12 +252,11 @@ class QuickAdapterV3(IStrategy): dataframe["%-bb_width"] = ( dataframe["bb_upperband"] - dataframe["bb_lowerband"] ) / dataframe["bb_middleband"] - dataframe["%-ibs"] = ( - (dataframe["close"] - dataframe["low"]) - / (dataframe["high"] - dataframe["low"]) - ).fillna(0.0) + dataframe["%-ibs"] = (dataframe["close"] - dataframe["low"]) / ( + non_zero_range(dataframe["high"], dataframe["low"]) + ) # dataframe["jaw"], dataframe["teeth"], dataframe["lips"] = alligator( - # dataframe, zero_lag=True + # dataframe, mamode="ema", zero_lag=True # ) # dataframe["%-dist_to_jaw"] = get_distance(dataframe["close"], dataframe["jaw"]) # dataframe["%-dist_to_teeth"] = get_distance( @@ -268,6 +267,9 @@ class QuickAdapterV3(IStrategy): # ) # dataframe["%-spread_jaw_teeth"] = dataframe["jaw"] - dataframe["teeth"] # dataframe["%-spread_teeth_lips"] = dataframe["teeth"] - dataframe["lips"] + # dataframe["%-alligator_trend_strength"] = ( + # dataframe["lips"] - dataframe["teeth"] + # ) + (non_zero_range(dataframe["teeth"], dataframe["jaw"])) dataframe["zlema_50"] = pta.zlma(dataframe["close"], length=50, mamode="ema") dataframe["zlema_12"] = pta.zlma(dataframe["close"], length=12, mamode="ema") dataframe["zlema_26"] = pta.zlma(dataframe["close"], length=26, mamode="ema") diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index 84855f1..0486385 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -4,6 +4,7 @@ import pandas_ta as pta import talib.abstract as ta from scipy.signal import convolve from scipy.signal.windows import gaussian +from sys import float_info from technical import qtpylib @@ -11,6 +12,14 @@ def get_distance(p1: pd.Series | float, p2: pd.Series | float) -> pd.Series | fl return abs(p1 - p2) +def non_zero_range(s1: pd.Series, s2: pd.Series) -> pd.Series: + """Returns the difference of two series and adds epsilon to any zero values.""" + diff = s1 - s2 + if diff.eq(0).any().any(): + diff += float_info.epsilon + return diff + + def get_gaussian_window(std: float, center: bool) -> int: if std is None: raise ValueError("Standard deviation cannot be None") @@ -102,8 +111,8 @@ def price_retracement_percent(dataframe: pd.DataFrame, period: int) -> pd.Series ) return (dataframe["close"] - previous_close_low) / ( - previous_close_high - previous_close_low - ).fillna(0.0) + non_zero_range(previous_close_high, previous_close_low) + ) # VWAP bands -- 2.43.0