From 2ae00ad976f3295bd647a1a535e02f1c45b3602d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Delacotte?= Date: Mon, 19 May 2025 23:40:07 +0200 Subject: [PATCH] =?UTF-8?q?Strat=C3=A9gie=20toujours=20foireuse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Zeus_8_3_2_B_4_2.py | 529 ++++++++++++++++++++++---------------------- 1 file changed, 264 insertions(+), 265 deletions(-) diff --git a/Zeus_8_3_2_B_4_2.py b/Zeus_8_3_2_B_4_2.py index 95dfa01..0bcfccd 100644 --- a/Zeus_8_3_2_B_4_2.py +++ b/Zeus_8_3_2_B_4_2.py @@ -149,13 +149,13 @@ class Zeus_8_3_2_B_4_2(IStrategy): 'mid_smooth_deriv1_1d': { "color": "blue" }, - 'mid_smooth_deriv1_1h': { + 'mid_smooth_1h_deriv1': { "color": "red" }, 'mid_smooth_deriv2_1d': { "color": "pink" }, - 'mid_smooth_deriv2_1h': { + 'mid_smooth_1h_deriv2': { "color": "#da59a6" } } @@ -205,7 +205,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): sell_allow_decrease = DecimalParameter(0.005, 0.02, default=0.2, decimals=2, space='sell', optimize=True, load=True) # Probabilité de hausse pour futur_percent_3h (en %): - # mid_smooth_deriv1_1h_bin B5 B4 B3 B2 B1 N0 H1 H2 H3 H4 H5 + # mid_smooth_1h_deriv1_bin B5 B4 B3 B2 B1 N0 H1 H2 H3 H4 H5 # sma24_deriv1_1h_bin # B5 41.0 47.2 48.1 45.6 74.0 65.9 66.5 83.8 77.8 72.1 81.0 # B4 41.2 35.8 48.4 46.5 59.9 60.2 75.8 79.4 84.6 83.0 78.5 @@ -226,7 +226,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): # Données sous forme de dictionnaire # Bornes des quantiles pour - mid_smooth_deriv1_24_bins = [-37.4852, -0.7541, -0.4233, -0.2510, -0.1338, -0.0389, 0.0496, 0.1464, 0.2660, 0.4384, 0.7697, 48.2985] + mid_smooth_24_deriv1_bins = [-37.4852, -0.7541, -0.4233, -0.2510, -0.1338, -0.0389, 0.0496, 0.1464, 0.2660, 0.4384, 0.7697, 48.2985] sma144_deriv1_bins = [-0.2592, -0.0166, -0.0091, -0.0051, -0.0025, -0.0005, 0.0012, 0.0034, 0.0062, 0.0105, 0.0183, 0.2436] smooth24_sma144_deriv1_matrice = { @@ -315,14 +315,14 @@ class Zeus_8_3_2_B_4_2(IStrategy): smooth_sma_24_diff_numeric_matrice = smooth_sma_24_diff_matrice_df.reindex(index=ordered_labels, columns=ordered_labels).values # Bornes des quantiles pour - mid_smooth_deriv1_1h = [-11.5091, -0.4887, -0.1902, -0.0823, -0.0281, -0.0008, 0.0110, 0.0439, 0.1066, 0.2349, 0.5440, 14.7943] + mid_smooth_1h_deriv1 = [-11.5091, -0.4887, -0.1902, -0.0823, -0.0281, -0.0008, 0.0110, 0.0439, 0.1066, 0.2349, 0.5440, 14.7943] # Bornes des quantiles pour - mid_smooth_deriv2_1h = [-6.2109, -0.2093, -0.0900, -0.0416, -0.0171, -0.0035, 0.0033, 0.0168, 0.0413, 0.0904, 0.2099, 6.2109] + mid_smooth_1h_deriv2 = [-6.2109, -0.2093, -0.0900, -0.0416, -0.0171, -0.0035, 0.0033, 0.0168, 0.0413, 0.0904, 0.2099, 6.2109] # ========================================================================= # variables pour probabilité jour # Bornes des quantiles pour - mid_smooth_deriv1_1h_1d_bins = [-11.5091, -0.4887, -0.1902, -0.0823, -0.0281, -0.0008, 0.0110, 0.0439, 0.1066, 0.2349, 0.5440, 14.7943] + mid_smooth_1h_deriv1_1d_bins = [-11.5091, -0.4887, -0.1902, -0.0823, -0.0281, -0.0008, 0.0110, 0.0439, 0.1066, 0.2349, 0.5440, 14.7943] # Bornes des quantiles pour sma24_deriv1_1h_1d_bins = [-2.1101, -0.1413, -0.0768, -0.0433, -0.0196, -0.0028, 0.0120, 0.0304, 0.0560, 0.0933, 0.1568, 0.7793] @@ -360,10 +360,10 @@ class Zeus_8_3_2_B_4_2(IStrategy): last_candle = dataframe.iloc[-1].squeeze() last_candle_2 = dataframe.iloc[-2].squeeze() last_candle_3 = dataframe.iloc[-3].squeeze() - val = self.getProbaHausse144(last_candle) + # val = self.getProbaHausse144(last_candle) # allow_to_buy = True #(not self.stop_all) #& (not self.all_down) - allow_to_buy = not self.pairs[pair]['stop'] and val > self.buy_val.value #not last_candle['tendency'] in ('B-', 'B--') # (rate <= float(limit)) | (entry_tag == 'force_entry') + allow_to_buy = not self.pairs[pair]['stop'] #and val > self.buy_val.value #not last_candle['tendency'] in ('B-', 'B--') # (rate <= float(limit)) | (entry_tag == 'force_entry') if allow_to_buy: self.trades = list() @@ -461,9 +461,6 @@ class Zeus_8_3_2_B_4_2(IStrategy): baisse = self.pairs[pair]['max_profit'] - current_profit mx = self.pairs[pair]['max_profit'] / 5 - if (last_candle['deriv1_1h'] < 0 and last_candle['deriv2_1h'] < 0) and ((baisse > mx) & (current_profit > expected_profit)): - return 'Drv_' + str(count_of_buys) - self.pairs[pair]['count_of_buys'] = count_of_buys self.pairs[pair]['current_profit'] = current_profit self.pairs[pair]['max_profit'] = max(self.pairs[pair]['max_profit'], current_profit) @@ -473,6 +470,9 @@ class Zeus_8_3_2_B_4_2(IStrategy): # if (last_candle['tendency'] in ('H++', 'H+')) and (last_candle['rsi'] < 80): # return None # + if (last_candle['mid_smooth_1h_deriv1'] < 0 and before_last_candle['mid_smooth_1h_deriv1'] >= 0) and (current_profit > expected_profit): + return 'Drv_' + str(count_of_buys) + # if (baisse > mx) & (current_profit > expected_profit): # self.trades = list() # return 'mx_' + str(count_of_buys) @@ -556,34 +556,36 @@ class Zeus_8_3_2_B_4_2(IStrategy): max_touch = '' #round(last_candle['max12_1d'], 1) #round(self.pairs[pair]['max_touch'], 1) pct_max = round((last_candle['close'] - self.pairs[pair]['first_buy']) / self.pairs[pair]['first_buy'], 3) # round(100 * self.pairs[pair]['current_profit'], 1) - if trade_type is not None: - if np.isnan(last_candle['rsi_1d']): - string = ' ' - else: - string = (str(int(last_candle['rsi_1d']))) + " " + str(int(last_candle['rsi_deriv1_1d'])) - trade_type = trade_type \ - + " " + string \ - + " " + str(int(last_candle['rsi_1h'])) \ - + " " + str(int(last_candle['rsi_deriv1_1h'])) + # if trade_type is not None: + # if np.isnan(last_candle['rsi_1d']): + # string = ' ' + # else: + # string = (str(int(last_candle['rsi_1d']))) + " " + str(int(last_candle['rsi_deriv1_1d'])) + # trade_type = trade_type \ + # + " " + string \ + # + " " + str(int(last_candle['rsi_1h'])) \ + # + " " + str(int(last_candle['rsi_deriv1_1h'])) - val144 = self.getProbaHausse144(last_candle) - val1h = self.getProbaHausse1h(last_candle) + # val144 = self.getProbaHausse144(last_candle) + # val1h = self.getProbaHausse1h(last_candle) self.printLog( f"| {date:<16} | {action:<10} | {pair[0:3]:<3} | {trade_type or '-':<18} |{rate or '-':>9}| {dispo or '-':>6} " f"| {profit or '-':>8} | {pct_max or '-':>6} | {round(self.pairs[pair]['max_touch'], 2) or '-':>11} | {last_lost or '-':>12} " f"| {int(self.pairs[pair]['last_max']) or '-':>7} |{buys or '-':>4}|{stake or '-':>7}" - f"|{last_candle['tendency'] or '-':>3}|{last_candle['tendency_1h'] or '-':>3}|{last_candle['tendency_1d'] or '-':>3}" - f"|{round(last_candle['mid_smooth_deriv1_24'],3) or '-':>6}|{round(last_candle['mid_smooth_deriv1_1h'],3) or '-':>6}|{round(last_candle['mid_smooth_deriv1_1d'],3) or '-' :>6}|" - f"{round(last_candle['mid_smooth_deriv2_24'],3) or '-' :>6}|{round(last_candle['mid_smooth_deriv2_1h'],3) or '-':>6}|{round(last_candle['mid_smooth_deriv2_1d'],3) or '-':>6}|" - f"{round(val144, 1) or '-' :>6}|{round(val1h, 1) or '-':>6}|" + f"|{last_candle['tendency'] or '-':>3}|" #{last_candle['tendency_1h'] or '-':>3}|{last_candle['tendency_1d'] or '-':>3}" + # f"|{round(last_candle['mid_smooth_24_deriv1'],3) or '-':>6}|{round(last_candle['mid_smooth_1h_deriv1'],3) or '-':>6}|{round(last_candle['mid_smooth_deriv1_1d'],3) or '-' :>6}|" + # f"{round(last_candle['mid_smooth_24_deriv2'],3) or '-' :>6}|{round(last_candle['mid_smooth_1h_deriv2'],3) or '-':>6}|{round(last_candle['mid_smooth_deriv2_1d'],3) or '-':>6}|" + # f"{round(val144, 1) or '-' :>6}|{round(val1h, 1) or '-':>6}|" ) def printLineLog(self): # f"sum1h|sum1d|Tdc|Tdh|Tdd| drv1 |drv_1h|drv_1d|" self.printLog( f"+{'-' * 18}+{'-' * 12}+{'-' * 5}+{'-' * 20}+{'-' * 9}+{'-' * 8}+{'-' * 10}+{'-' * 8}+{'-' * 13}+{'-' * 14}+{'-' * 9}+{'-' * 4}+{'-' * 7}+" - f"{'-' * 3}+{'-' * 3}+{'-' * 3}+{'-' * 6}+{'-' * 6}+{'-' * 6}+" + f"{'-' * 3}" + #"+{'-' * 3}+{'-' * 3} + # f"+{'-' * 6}+{'-' * 6}+{'-' * 6}+{'-' * 6}+{'-' * 6}+{'-' * 6}+" ) def printLog(self, str): @@ -594,8 +596,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): def add_tendency_column(self, dataframe: pd.DataFrame, suffixe='') -> pd.DataFrame: def tag_by_derivatives(row): - d1 = row[f"mid_smooth_deriv1{suffixe}"] - d2 = row[f"mid_smooth_deriv2{suffixe}"] + d1 = row[f"mid_smooth{suffixe}_deriv1"] + d2 = row[f"mid_smooth{suffixe}_deriv2"] d1_lim_inf = -0.01 d1_lim_sup = 0.01 if d1 >= d1_lim_inf and d1 <= d1_lim_sup: # and d2 >= d2_lim_inf and d2 <= d2_lim_sup: @@ -664,18 +666,11 @@ class Zeus_8_3_2_B_4_2(IStrategy): ) # Normalization - dataframe['average_line'] = dataframe['close'].mean() - dataframe['average_line_50'] = talib.MIDPOINT(dataframe['close'], timeperiod=50) - - dataframe['average_line_288'] = talib.MIDPOINT(dataframe['close'], timeperiod=288) - dataframe['average_line_288_098'] = dataframe['average_line_288'] * 0.98 - dataframe['average_line_288_099'] = dataframe['average_line_288'] * 0.99 - # Compter les baisses consécutives self.calculateDownAndUp(dataframe, limit=0.0001) - dataframe = self.calculateRegression(dataframe, column='mid_smooth', window=24, degree=4, future_offset=12) - dataframe = self.calculateRegression(dataframe, column='mid_smooth_24', window=24, degree=4, future_offset=12) + # dataframe = self.calculateRegression(dataframe, column='mid_smooth', window=24, degree=4, future_offset=12) + # dataframe = self.calculateRegression(dataframe, column='mid_smooth_24', window=24, degree=4, future_offset=12) ################### INFORMATIVE 1h informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h") @@ -684,32 +679,24 @@ class Zeus_8_3_2_B_4_2(IStrategy): informative['haclose'] = heikinashi['close'] informative['hapercent'] = (informative['haclose'] - informative['haopen']) / informative['haclose'] - informative = self.calculateDerivation(informative, window=12) + # informative = self.calculateDerivation(informative, window=12) + # informative = self.apply_regression_derivatives(informative, column='mid', window=5, degree=4) # informative['volatility'] = talib.STDDEV(informative['close'], timeperiod=14) / informative['close'] # informative['atr'] = (talib.ATR(informative['high'], informative['low'], informative['close'], timeperiod=14)) / informative['close'] informative['rsi'] = talib.RSI(informative['close']) #, timeperiod=7) - self.calculeDerivees(informative, 'rsi') informative['max12'] = talib.MAX(informative['close'], timeperiod=12) informative['min12'] = talib.MIN(informative['close'], timeperiod=12) informative['sma5'] = talib.SMA(informative, timeperiod=5) - self.calculeDerivees(informative, 'sma5') informative['sma24'] = talib.SMA(informative, timeperiod=24) - self.calculeDerivees(informative, 'sma24') - - self.calculateDownAndUp(informative, limit=0.0012) - - informative['close_smooth'] = self.conditional_smoothing(informative['mid'], threshold=0.0015) - informative['smooth'], informative['deriv1'], informative['deriv2'] = self.smooth_and_derivatives(informative['close_smooth']) - informative['deriv1'] = 100 * informative['deriv1'] / informative['mid'] - informative['deriv2'] = 1000 * informative['deriv2'] / informative['mid'] + # self.calculateDownAndUp(informative, limit=0.0012) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True) ################### INFORMATIVE 1d informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d") - informative = self.calculateDerivation(informative, window=5, factor_1=10000, factor_2=1000) + # informative = self.calculateDerivation(informative, window=5, factor_1=10000, factor_2=1000) # informative['volatility'] = talib.STDDEV(informative['close'], timeperiod=14) / informative['close'] # informative['atr'] = (talib.ATR(informative['high'], informative['low'], informative['close'], timeperiod=14)) / informative['close'] @@ -719,11 +706,16 @@ class Zeus_8_3_2_B_4_2(IStrategy): informative['max3'] = talib.MAX(informative['close'], timeperiod=3) informative['min3'] = talib.MIN(informative['close'], timeperiod=3) - informative['rsi'] = talib.RSI(informative['close']) #, timeperiod=7) - self.calculeDerivees(informative, 'rsi') + # informative['rsi'] = talib.RSI(informative['close']) #, timeperiod=7) + # self.calculeDerivees(informative, 'rsi') + # + # informative['sma5'] = talib.SMA(informative, timeperiod=5) + # self.calculeDerivees(informative, 'sma5') - informative['sma5'] = talib.SMA(informative, timeperiod=5) - self.calculeDerivees(informative, 'sma5') + # informative['close_smooth'] = self.conditional_smoothing(informative['mid'].dropna(), threshold=0.0015).dropna() + # informative['smooth'], informative['deriv1'], informative['deriv2'] = self.smooth_and_derivatives(informative['close_smooth']) + # informative['deriv1'] = 100 * informative['deriv1'] / informative['mid'] + # informative['deriv2'] = 1000 * informative['deriv2'] / informative['mid'] dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True) @@ -761,59 +753,64 @@ class Zeus_8_3_2_B_4_2(IStrategy): # dataframe['amount'] = amount print(f"amount= {amount}") - # dataframe['mid_smooth_tag'] = qtpylib.crossed_below(dataframe['mid_smooth_deriv1_24'], dataframe['mid_smooth_deriv2_24']) + # dataframe['mid_smooth_tag'] = qtpylib.crossed_below(dataframe['mid_smooth_24_deriv1'], dataframe['mid_smooth_deriv2_24']) # =============================== # lissage des valeurs horaires - horizon_h = 12 * 5 - horizon_d = 24 * 5 - dataframe['mid_smooth_1h'] = dataframe['mid_smooth_1h'].rolling(window=horizon_h).mean() - dataframe["mid_smooth_deriv1_1h"] = dataframe["mid_smooth_1h"].rolling(horizon_h).mean().diff() / horizon_h - dataframe["mid_smooth_deriv2_1h"] = horizon_h * dataframe["mid_smooth_deriv1_1h"].rolling(horizon_h).mean().diff() + dataframe['mid_smooth_1h'] = dataframe['mid'].rolling(window=6).mean() + dataframe["mid_smooth_1h_deriv1"] = 100 * dataframe["mid_smooth_1h"].diff() / dataframe['mid_smooth_1h'] + dataframe["mid_smooth_1h_deriv2"] = 10 * dataframe["mid_smooth_1h_deriv1"].diff() - dataframe['sma5_1h'] = dataframe['sma5_1h'].rolling(window=horizon_h).mean() - dataframe['sma5_deriv1_1h'] = dataframe['sma5_deriv1_1h'].rolling(window=horizon_h).mean() - dataframe['sma24_1h'] = dataframe['sma24_1h'].rolling(window=horizon_h).mean() - dataframe['sma24_deriv1_1h'] = dataframe['sma24_deriv1_1h'].rolling(window=horizon_h).mean() + # dataframe['close_smooth_1h'] = self.conditional_smoothing(dataframe['mid'].rolling(window=3).mean().dropna(), threshold=0.0005) + # dataframe['smooth_1h'], dataframe['deriv1_1h'], dataframe['deriv2_1h'] = self.smooth_and_derivatives(dataframe['close_smooth_1h']) + # dataframe['deriv1_1h'] = 100 * dataframe['deriv1_1h'] / dataframe['mid_smooth_1h'] + # dataframe['deriv2_1h'] = 1000 * dataframe['deriv2_1h'] / dataframe['mid_smooth_1h'] - dataframe = self.calculateRegression(dataframe, column='mid_smooth_1h', window=horizon_h * 12, degree=4, future_offset=24) + + # dataframe['sma5_1h'] = dataframe['sma5_1h'].rolling(window=horizon_h).mean() + # dataframe['sma5_deriv1_1h'] = dataframe['sma5_deriv1_1h'].rolling(window=horizon_h).mean() + # dataframe['sma24_1h'] = dataframe['sma24_1h'].rolling(window=horizon_h).mean() + # dataframe['sma24_deriv1_1h'] = dataframe['sma24_deriv1_1h'].rolling(window=horizon_h).mean() + + # dataframe = self.calculateRegression(dataframe, column='mid_smooth_1h', window=horizon_h * 12, degree=4, future_offset=24) # Suppose que df['close'] est ton prix de clôture - dataframe['close_smooth'] = self.conditional_smoothing(dataframe['mid'], threshold=0.0015) + # dataframe['close_smooth_24'] = self.conditional_smoothing(dataframe['mid'].rolling(24).mean().dropna(), threshold=0.0015) + # dataframe['smooth_24'], dataframe['smooth_24_deriv1'], dataframe['smooth_24_deriv2'] = self.smooth_and_derivatives(dataframe['close_smooth_24']) + # dataframe['smooth_24_deriv1'] = 100 * dataframe['smooth_24_deriv1'] / dataframe['mid_smooth_24'] + # dataframe['smooth_24_deriv2'] = 100 * dataframe['smooth_24_deriv2'] / dataframe['mid_smooth_24'] + + dataframe['close_smooth'] = self.conditional_smoothing(dataframe['mid'].rolling(3).mean().dropna(), threshold=0.001) dataframe['smooth'], dataframe['deriv1'], dataframe['deriv2'] = self.smooth_and_derivatives(dataframe['close_smooth']) dataframe['deriv1'] = 100 * dataframe['deriv1'] / dataframe['mid'] - dataframe['deriv2'] = 1000 * dataframe['deriv2'] / dataframe['mid'] + dataframe['deriv2'] = 100 * dataframe['deriv2'] / dataframe['mid'] # =============================== # Lissage des valeurs Journalières - dataframe['mid_smooth_1d'] = dataframe['mid_smooth_1d'].rolling(window=horizon_d * 5).mean() - dataframe["mid_smooth_deriv1_1d"] = dataframe["mid_smooth_1d"].rolling(horizon_d).mean().diff() / horizon_d - dataframe["mid_smooth_deriv2_1d"] = horizon_d * dataframe["mid_smooth_deriv1_1d"].rolling(horizon_d).mean().diff() - - dataframe['close_smooth_1d'] = self.conditional_smoothing(dataframe['mid_smooth_1d'], threshold=0.0015) - dataframe['smooth_1d'], dataframe['deriv1_1d'], dataframe['deriv2_1d'] = self.smooth_and_derivatives(dataframe['close_smooth_1d']) - dataframe['deriv1_1d'] = 10 * dataframe['deriv1_1d'] / dataframe['mid_smooth_1d'] - dataframe['deriv2_1d'] = 100 * dataframe['deriv2_1d'] / dataframe['mid_smooth_1d'] - - dataframe['sma5_1d'] = dataframe['sma5_1d'].rolling(window=horizon_d * 5).mean() - dataframe['sma5_deriv1_1d'] = dataframe['sma5_deriv1_1d'].rolling(window=horizon_d).mean() + # horizon_d = 24 * 5 + # dataframe['mid_smooth_1d'] = dataframe['mid_smooth_1d'].rolling(window=horizon_d * 5).mean() + # dataframe["mid_smooth_deriv1_1d"] = dataframe["mid_smooth_1d"].rolling(horizon_d).mean().diff() / horizon_d + # dataframe["mid_smooth_deriv2_1d"] = horizon_d * dataframe["mid_smooth_deriv1_1d"].rolling(horizon_d).mean().diff() + # + # dataframe['sma5_1d'] = dataframe['sma5_1d'].rolling(window=horizon_d * 5).mean() + # dataframe['sma5_deriv1_1d'] = dataframe['sma5_deriv1_1d'].rolling(window=horizon_d).mean() # dataframe['sma24_1d'] = dataframe['sma24_1d'].rolling(window=horizon_d).mean() # dataframe['sma24_deriv1_1d'] = dataframe['sma24_deriv1_1d'].rolling(window=horizon_d).mean() # dataframe = self.calculateRegression(dataframe, column='mid_smooth_1d', window=24, degree=4, future_offset=12) - dataframe['percent_with_previous_day'] = 100 * (dataframe['close'] - dataframe['close_1d']) / dataframe['close'] - dataframe['percent_with_max_hour'] = 100 * (dataframe['close'] - dataframe['max12_1h']) / dataframe['close'] - - dataframe['futur_percent_1h'] = 100 * ((dataframe['mid_smooth_1h'].shift(-12) - dataframe['mid_smooth_1h']) / dataframe['mid_smooth_1h']).rolling(horizon_h).mean() - dataframe['futur_percent_3h'] = 100 * ((dataframe['mid_smooth_1h'].shift(-36) - dataframe['mid_smooth_1h']) / dataframe['mid_smooth_1h']).rolling(horizon_h).mean() - dataframe['futur_percent_5h'] = 100 * ((dataframe['mid_smooth_1h'].shift(-60) - dataframe['mid_smooth_1h']) / dataframe['mid_smooth_1h']).rolling(horizon_h).mean() - dataframe['futur_percent_12h'] = 100 * ((dataframe['mid_smooth_1h'].shift(-144) - dataframe['mid_smooth_1h']) / dataframe['mid_smooth_1h']).rolling(horizon_h).mean() + # dataframe['percent_with_previous_day'] = 100 * (dataframe['close'] - dataframe['close_1d']) / dataframe['close'] + # dataframe['percent_with_max_hour'] = 100 * (dataframe['close'] - dataframe['max12_1h']) / dataframe['close'] + # + # dataframe['futur_percent_1h'] = 100 * ((dataframe['mid_smooth_1h'].shift(-12) - dataframe['mid_smooth_1h']) / dataframe['mid_smooth_1h']).rolling(horizon_h).mean() + # dataframe['futur_percent_3h'] = 100 * ((dataframe['mid_smooth_1h'].shift(-36) - dataframe['mid_smooth_1h']) / dataframe['mid_smooth_1h']).rolling(horizon_h).mean() + # dataframe['futur_percent_5h'] = 100 * ((dataframe['mid_smooth_1h'].shift(-60) - dataframe['mid_smooth_1h']) / dataframe['mid_smooth_1h']).rolling(horizon_h).mean() + # dataframe['futur_percent_12h'] = 100 * ((dataframe['mid_smooth_1h'].shift(-144) - dataframe['mid_smooth_1h']) / dataframe['mid_smooth_1h']).rolling(horizon_h).mean() # dataframe['futur_percent_1d'] = 100 * (dataframe['close'].shift(-1) - dataframe['close']) / dataframe['close'] # dataframe['futur_percent_3d'] = 100 * (dataframe['close'].shift(-3) - dataframe['close']) / dataframe['close'] - self.calculateProbabilite2Index(dataframe, ['futur_percent_12h'], 'mid_smooth_deriv1_1d', 'sma24_deriv1_1h') + # self.calculateProbabilite2Index(dataframe, ['futur_percent_12h'], 'mid_smooth_deriv1_1d', 'sma24_deriv1_1h') return dataframe @@ -837,10 +834,10 @@ class Zeus_8_3_2_B_4_2(IStrategy): # 1. Calcul du lissage par moyenne mobile médiane dataframe[f"mid_smooth{suffixe}"] = dataframe['close'].rolling(window=window).mean() # 2. Dérivée première = différence entre deux bougies successives - dataframe[f"mid_smooth_deriv1{suffixe}"] = round(factor_1 * dataframe[f"mid_smooth{suffixe}"].rolling(window=3).mean().diff() / dataframe[f"mid_smooth{suffixe}"], 4) + dataframe[f"mid_smooth{suffixe}_deriv1"] = round(factor_1 * dataframe[f"mid_smooth{suffixe}"].rolling(window=3).mean().diff() / dataframe[f"mid_smooth{suffixe}"], 4) # 3. Dérivée seconde = différence de la dérivée première - dataframe[f"mid_smooth_deriv2{suffixe}"] = round(factor_2 * dataframe[f"mid_smooth_deriv1{suffixe}"].rolling(window=3).mean().diff(), 4) + dataframe[f"mid_smooth{suffixe}_deriv2"] = round(factor_2 * dataframe[f"mid_smooth{suffixe}_deriv1"].rolling(window=3).mean().diff(), 4) dataframe = self.add_tendency_column(dataframe, suffixe) return dataframe @@ -863,19 +860,6 @@ class Zeus_8_3_2_B_4_2(IStrategy): # print('adjust exit price ' + str(self.adjust_exit_price(dataframe.iloc[-1]))) print('calcul expected_profit ' + str(expected_profit)) - buy_level = dataframe['average_line_50'] #dataframe['buy_level'] # self.get_buy_level(pair, dataframe) - - # dataframe.loc[ - # ( - # (dataframe['max200_diff'] >= 0.01) - # & (dataframe['percent12'] < -0.002) - # & (dataframe['open'] < dataframe['average_line_288_099']) - # & (dataframe['open'] < dataframe['average_line_50']) - # & (dataframe['min12'].shift(2) == dataframe['min12']) - # & (dataframe['up_count'] > 0) - # & (dataframe["bb_width"] > 0.01) - # ), ['enter_long', 'enter_tag']] = (1, 'mx200') - # dataframe.loc[ # ( # (dataframe['percent'] > 0) @@ -884,102 +868,103 @@ class Zeus_8_3_2_B_4_2(IStrategy): dataframe.loc[ ( - (dataframe['deriv1_1h'] >= 0) - & (dataframe['deriv1'] >= 0) - & (dataframe['deriv1'].shift(1) <= 0) - & (dataframe['deriv1'] >= dataframe['deriv1'].shift(1)) - ), ['enter_long', 'enter_tag']] = (1, 'smooth') - - # dataframe.loc[ - # ( - # (dataframe['low'] < dataframe['min200']) - # & (dataframe['min50'] == dataframe['min50'].shift(3)) - # & (dataframe['tendency'] != "B-") - # ), ['enter_long', 'enter_tag']] = (1, 'low') + # (dataframe['deriv2_1h'].shift(2) >= dataframe['deriv2_1h'].shift(1)) + # & (dataframe['deriv2_1h'].shift(1) <= dataframe['deriv2_1h']) + # (dataframe['deriv1_1h'] >= -0.01) + # & (dataframe['deriv2_1h'] >= -0.00) + (dataframe['mid_smooth_1h_deriv1'].shift(1) <= 0) + & (dataframe['mid_smooth_1h_deriv1'] >= 0) + # + # + # (dataframe['mid_smooth_1h_deriv1'] >= 0) + # & (dataframe['mid_smooth_1h_deriv1'] >= 0) + # & (dataframe['mid_smooth_1h_deriv1'].shift(1) <= 0) + # & (dataframe['mid_smooth_1h_deriv1'] >= dataframe['mid_smooth_1h_deriv1'].shift(1)) + ), ['enter_long', 'enter_tag']] = (1, 'smth') dataframe['test'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.01, np.nan) if self.dp.runmode.value in ('backtest'): today = datetime.now().strftime("%Y-%m-%d-%H:%M:%S") dataframe.to_feather(f"user_data/data/binance/{today}-{metadata['pair'].replace('/', '_')}_df.feather") - - df = dataframe - - # Colonnes à traiter - # futur_cols = ['futur_percent_1h', 'futur_percent_3h', 'futur_percent_5h', 'futur_percent_12h'] - futur_cols = ['futur_percent_1h'] - - # Tranches équitables par quantiles - - indic_1 = 'mid_smooth_deriv1_24' - indic_2 = 'sma144_deriv1' - #indic_2 = 'percent_with_max_hour' - # indic_1 = 'mid_smooth_deriv1_1h' - # indic_2 = 'sma5_deriv1_1d' - - self.calculateProbabilite2Index(df, futur_cols, indic_1, indic_2) + # + # df = dataframe + # + # # Colonnes à traiter + # # futur_cols = ['futur_percent_1h', 'futur_percent_3h', 'futur_percent_5h', 'futur_percent_12h'] + # futur_cols = ['futur_percent_1h'] + # + # # Tranches équitables par quantiles + # + # indic_1 = 'mid_smooth_24_deriv1' + # indic_2 = 'sma144_deriv1' + # #indic_2 = 'percent_with_max_hour' + # # indic_1 = 'mid_smooth_1h_deriv1' + # # indic_2 = 'sma5_deriv1_1d' + # + # self.calculateProbabilite2Index(df, futur_cols, indic_1, indic_2) return dataframe - def calculateProbabilite2Index(self, df, futur_cols, indic_1, indic_2): - # # Définition des tranches pour les dérivées - # bins_deriv = [-np.inf, -0.05, -0.01, 0.01, 0.05, np.inf] - # labels = ['forte baisse', 'légère baisse', 'neutre', 'légère hausse', 'forte hausse'] - # - # # Ajout des colonnes bin (catégorisation) - # df[f"{indic_1}_bin"] = pd.cut(df['mid_smooth_deriv1_1h'], bins=bins_deriv, labels=labels) - # df[f"{indic_2}_bin"] = pd.cut(df['mid_smooth_deriv1_1d'], bins=bins_deriv, labels=labels) - # - # # Colonnes de prix futur à analyser - # futur_cols = ['futur_percent_1h', 'futur_percent_2h', 'futur_percent_3h', 'futur_percent_4h', 'futur_percent_5h'] - # - # # Calcul des moyennes et des effectifs - # grouped = df.groupby([f"{indic_2}_bin", f"{indic_1}_bin"])[futur_cols].agg(['mean', 'count']) - # - # pd.set_option('display.width', 200) # largeur max affichage - # pd.set_option('display.max_columns', None) - pd.set_option('display.max_columns', None) - pd.set_option('display.width', 300) # largeur max affichage - - # nettoyage - # series = df[f"{indic_2}"].dropna() - # unique_vals = df[f"{indic_2}"].nunique() - # print(unique_vals) - # print(df[f"{indic_2}"]) - n = len(self.labels) - - df[f"{indic_1}_bin"], bins_1h = pd.qcut(df[f"{indic_1}"], q=n, labels=self.labels, retbins=True, - duplicates='drop') - df[f"{indic_2}_bin"], bins_1d = pd.qcut(df[f"{indic_2}"], q=n, labels=self.labels, retbins=True, - duplicates='drop') - # Affichage formaté pour code Python - print(f"Bornes des quantiles pour {indic_1} : [{', '.join([f'{b:.4f}' for b in bins_1h])}]") - print(f"Bornes des quantiles pour {indic_2} : [{', '.join([f'{b:.4f}' for b in bins_1d])}]") - # Agrégation - grouped = df.groupby([f"{indic_2}_bin", f"{indic_1}_bin"], observed=True)[futur_cols].agg(['mean', 'count']) - # Affichage - with pd.option_context('display.max_rows', None, 'display.max_columns', None): - print(grouped.round(4)) - # Ajout des probabilités de hausse - for col in futur_cols: - df[f"{col}_is_up"] = df[col] > 0 - - # Calcul de la proba de hausse - proba_up = df.groupby([f"{indic_2}_bin", f"{indic_1}_bin"], observed=True)[f"{col}_is_up"].mean().unstack() - - print(f"\nProbabilité de hausse pour {col} (en %):") - with pd.option_context('display.max_rows', None, 'display.max_columns', None): - print((proba_up * 100).round(1)) - - # Affichage formaté des valeurs comme tableau Python - with pd.option_context('display.max_rows', None, 'display.max_columns', None): - df_formatted = (proba_up * 100).round(1) - - print("data = {") - for index, row in df_formatted.iterrows(): - row_values = ", ".join([f"{val:.1f}" for val in row]) - print(f"'{index}': [{row_values}], ") - print("}") + # def calculateProbabilite2Index(self, df, futur_cols, indic_1, indic_2): + # # # Définition des tranches pour les dérivées + # # bins_deriv = [-np.inf, -0.05, -0.01, 0.01, 0.05, np.inf] + # # labels = ['forte baisse', 'légère baisse', 'neutre', 'légère hausse', 'forte hausse'] + # # + # # # Ajout des colonnes bin (catégorisation) + # # df[f"{indic_1}_bin"] = pd.cut(df['mid_smooth_1h_deriv1'], bins=bins_deriv, labels=labels) + # # df[f"{indic_2}_bin"] = pd.cut(df['mid_smooth_deriv1_1d'], bins=bins_deriv, labels=labels) + # # + # # # Colonnes de prix futur à analyser + # # futur_cols = ['futur_percent_1h', 'futur_percent_2h', 'futur_percent_3h', 'futur_percent_4h', 'futur_percent_5h'] + # # + # # # Calcul des moyennes et des effectifs + # # grouped = df.groupby([f"{indic_2}_bin", f"{indic_1}_bin"])[futur_cols].agg(['mean', 'count']) + # # + # # pd.set_option('display.width', 200) # largeur max affichage + # # pd.set_option('display.max_columns', None) + # pd.set_option('display.max_columns', None) + # pd.set_option('display.width', 300) # largeur max affichage + # + # # nettoyage + # # series = df[f"{indic_2}"].dropna() + # # unique_vals = df[f"{indic_2}"].nunique() + # # print(unique_vals) + # # print(df[f"{indic_2}"]) + # n = len(self.labels) + # + # df[f"{indic_1}_bin"], bins_1h = pd.qcut(df[f"{indic_1}"], q=n, labels=self.labels, retbins=True, + # duplicates='drop') + # df[f"{indic_2}_bin"], bins_1d = pd.qcut(df[f"{indic_2}"], q=n, labels=self.labels, retbins=True, + # duplicates='drop') + # # Affichage formaté pour code Python + # print(f"Bornes des quantiles pour {indic_1} : [{', '.join([f'{b:.4f}' for b in bins_1h])}]") + # print(f"Bornes des quantiles pour {indic_2} : [{', '.join([f'{b:.4f}' for b in bins_1d])}]") + # # Agrégation + # grouped = df.groupby([f"{indic_2}_bin", f"{indic_1}_bin"], observed=True)[futur_cols].agg(['mean', 'count']) + # # Affichage + # with pd.option_context('display.max_rows', None, 'display.max_columns', None): + # print(grouped.round(4)) + # # Ajout des probabilités de hausse + # for col in futur_cols: + # df[f"{col}_is_up"] = df[col] > 0 + # + # # Calcul de la proba de hausse + # proba_up = df.groupby([f"{indic_2}_bin", f"{indic_1}_bin"], observed=True)[f"{col}_is_up"].mean().unstack() + # + # print(f"\nProbabilité de hausse pour {col} (en %):") + # with pd.option_context('display.max_rows', None, 'display.max_columns', None): + # print((proba_up * 100).round(1)) + # + # # Affichage formaté des valeurs comme tableau Python + # with pd.option_context('display.max_rows', None, 'display.max_columns', None): + # df_formatted = (proba_up * 100).round(1) + # + # print("data = {") + # for index, row in df_formatted.iterrows(): + # row_values = ", ".join([f"{val:.1f}" for val in row]) + # print(f"'{index}': [{row_values}], ") + # print("}") def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # dataframe.loc[ @@ -1111,7 +1096,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): return None def getProbaHausse144(self, last_candle): - value_1 = self.getValuesFromTable(self.mid_smooth_deriv1_24_bins, last_candle['mid_smooth_deriv1_24']) + value_1 = self.getValuesFromTable(self.mid_smooth_24_deriv1_bins, last_candle['mid_smooth_24_deriv1']) value_2 = self.getValuesFromTable(self.sma144_deriv1_bins, last_candle['sma144_deriv1']) val = self.approx_val_from_bins( @@ -1122,7 +1107,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): return val def getProbaHausse1h(self, last_candle): - value_1 = self.getValuesFromTable(self.mid_smooth_1h_bins, last_candle['mid_smooth_deriv1_1h']) + value_1 = self.getValuesFromTable(self.mid_smooth_1h_bins, last_candle['mid_smooth_1h_deriv1']) value_2 = self.getValuesFromTable(self.sma24_deriv1_1h_bins, last_candle['sma24_deriv1_1h']) val = self.approx_val_from_bins(matrice=self.smooth_smadiff_matrice_df, numeric_matrice=self.smooth_smadiff_numeric_matrice, @@ -1199,69 +1184,69 @@ class Zeus_8_3_2_B_4_2(IStrategy): # # Filtrer les signaux: ne prendre un signal haussier que si dérivée1 > 0 et dérivée2 > 0. # Détecter les zones de retournement: quand dérivée1 ≈ 0 et que dérivée2 change de signe. - def calculateRegression(self, - dataframe: DataFrame, - column= 'close', - window= 50, - degree=3, - future_offset: int = 10 # projection à n bougies après - ) -> DataFrame: - df = dataframe.copy() - - regression_fit = [] - regression_future_fit = [] - - regression_fit = [] - regression_future_fit = [] - - for i in range(len(df)): - if i < window: - regression_fit.append(np.nan) - regression_future_fit.append(np.nan) - continue - - # Fin de la fenêtre d’apprentissage - end_index = i - start_index = i - window - y = df[column].iloc[start_index:end_index].values - - # Si les données sont insuffisantes (juste par précaution) - if len(y) < window: - regression_fit.append(np.nan) - regression_future_fit.append(np.nan) - continue - - # x centré pour meilleure stabilité numérique - x = np.linspace(-1, 1, window) - coeffs = np.polyfit(x, y, degree) - poly = np.poly1d(coeffs) - - # Calcul point présent (dernier de la fenêtre) - x_now = x[-1] - regression_fit.append(poly(x_now)) - - # Calcul point futur, en ajustant si on dépasse la fin - remaining = len(df) - i - 1 - effective_offset = min(future_offset, remaining) - x_future = x_now + (effective_offset / window) * 2 # respect du même pas - regression_future_fit.append(poly(x_future)) - - df[f"{column}_regression"] = regression_fit - # 2. Dérivée première = différence entre deux bougies successives - df[f"{column}_regression_deriv1"] = round(100 * df[f"{column}_regression"].diff() / df[f"{column}_regression"], 4) - - # 3. Dérivée seconde = différence de la dérivée première - df[f"{column}_regression_deriv2"] = round(10 * df[f"{column}_regression_deriv1"].rolling(int(window / 4)).mean().diff(), 4) - - df[f"{column}_future_{future_offset}"] = regression_future_fit - - # # 2. Dérivée première = différence entre deux bougies successives - # df[f"{column}_future_{future_offset}_deriv1"] = round(100 * df[f"{column}_future_{future_offset}"].diff() / df[f"{column}_future_{future_offset}"], 4) - # - # # 3. Dérivée seconde = différence de la dérivée première - # df[f"{column}_future_{future_offset}_deriv2"] = round(10 * df[f"{column}_future_{future_offset}_deriv1"].rolling(int(window / 4)).mean().diff(), 4) - - return df + # def calculateRegression(self, + # dataframe: DataFrame, + # column= 'close', + # window= 50, + # degree=3, + # future_offset: int = 10 # projection à n bougies après + # ) -> DataFrame: + # df = dataframe.copy() + # + # regression_fit = [] + # regression_future_fit = [] + # + # regression_fit = [] + # regression_future_fit = [] + # + # for i in range(len(df)): + # if i < window: + # regression_fit.append(np.nan) + # regression_future_fit.append(np.nan) + # continue + # + # # Fin de la fenêtre d’apprentissage + # end_index = i + # start_index = i - window + # y = df[column].iloc[start_index:end_index].values + # + # # Si les données sont insuffisantes (juste par précaution) + # if len(y) < window: + # regression_fit.append(np.nan) + # regression_future_fit.append(np.nan) + # continue + # + # # x centré pour meilleure stabilité numérique + # x = np.linspace(-1, 1, window) + # coeffs = np.polyfit(x, y, degree) + # poly = np.poly1d(coeffs) + # + # # Calcul point présent (dernier de la fenêtre) + # x_now = x[-1] + # regression_fit.append(poly(x_now)) + # + # # Calcul point futur, en ajustant si on dépasse la fin + # remaining = len(df) - i - 1 + # effective_offset = min(future_offset, remaining) + # x_future = x_now + (effective_offset / window) * 2 # respect du même pas + # regression_future_fit.append(poly(x_future)) + # + # df[f"{column}_regression"] = regression_fit + # # 2. Dérivée première = différence entre deux bougies successives + # df[f"{column}_regression_deriv1"] = round(100 * df[f"{column}_regression"].diff() / df[f"{column}_regression"], 4) + # + # # 3. Dérivée seconde = différence de la dérivée première + # df[f"{column}_regression_deriv2"] = round(10 * df[f"{column}_regression_deriv1"].rolling(int(window / 4)).mean().diff(), 4) + # + # df[f"{column}_future_{future_offset}"] = regression_future_fit + # + # # # 2. Dérivée première = différence entre deux bougies successives + # # df[f"{column}_future_{future_offset}_deriv1"] = round(100 * df[f"{column}_future_{future_offset}"].diff() / df[f"{column}_future_{future_offset}"], 4) + # # + # # # 3. Dérivée seconde = différence de la dérivée première + # # df[f"{column}_future_{future_offset}_deriv2"] = round(10 * df[f"{column}_future_{future_offset}_deriv1"].rolling(int(window / 4)).mean().diff(), 4) + # + # return df def getValuesFromTable(self, values, value): for i in range(len(values) - 1): @@ -1401,16 +1386,30 @@ class Zeus_8_3_2_B_4_2(IStrategy): smoothed.append(last) return pd.Series(smoothed, index=series.index) - - # Lissage + dérivées def smooth_and_derivatives(self, series, window=25, polyorder=3): - y = series.values - smoothed = savgol_filter(y, window_length=window, polyorder=polyorder) - deriv1 = savgol_filter(y, window_length=window, polyorder=polyorder, deriv=1) - deriv2 = savgol_filter(y, window_length=window, polyorder=polyorder, deriv=2) + series = series.copy() + if series.isna().sum() > 0: + series = series.fillna(method='ffill').fillna(method='bfill') # Si tu veux éviter toute NaN + + smooth = self.causal_savgol(series, window=window, polyorder=polyorder) + deriv1 = np.diff(smooth, prepend=smooth[0]) + deriv2 = np.diff(deriv1, prepend=deriv1[0]) + + return pd.Series(smooth, index=series.index), pd.Series(deriv1, index=series.index), pd.Series(deriv2, index=series.index) + + def causal_savgol(self, series, window=25, polyorder=3): + result = [] + half_window = window # Fenêtre complète dans le passé + for i in range(len(series)): + if i < half_window: + result.append(np.nan) + continue + window_series = series[i - half_window:i] + if window_series.isna().any(): + result.append(np.nan) + continue + coeffs = np.polyfit(range(window), window_series, polyorder) + poly = np.poly1d(coeffs) + result.append(poly(window - 1)) + return pd.Series(result, index=series.index) - return ( - pd.Series(smoothed, index=series.index), - pd.Series(deriv1, index=series.index), - pd.Series(deriv2, index=series.index), - )