From 39bd32370a1a3bd465c77e69e246ff07e6393d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Delacotte?= Date: Sun, 21 Sep 2025 20:27:37 +0200 Subject: [PATCH] Calcul 20250101-20250714 735.207 106.112$ 26315.818 --- Zeus_8_3_2_B_4_2.json | 11 ++- Zeus_8_3_2_B_4_2.py | 161 +++++++++++++++++++++++++----------------- 2 files changed, 100 insertions(+), 72 deletions(-) diff --git a/Zeus_8_3_2_B_4_2.json b/Zeus_8_3_2_B_4_2.json index b02d558..5336188 100644 --- a/Zeus_8_3_2_B_4_2.json +++ b/Zeus_8_3_2_B_4_2.json @@ -19,14 +19,13 @@ "buy": { "buy_horizon_predict_1h": 2 }, - "sell": { - "sell_allow_decrease": 0.2 - }, + "sell": {}, "protection": { - "protection_fibo": 9, - "protection_percent_buy_lost": 3 + "sma20_deriv1_1d_protection": -0.05, + "sma24_deriv1_1h_protection": -0.1, + "sma5_deriv1_1d_protection": -0.05 } }, "ft_stratparam_v": 1, - "export_time": "2025-05-24 18:29:22.477903+00:00" + "export_time": "2025-09-16 18:26:35.356631+00:00" } \ No newline at end of file diff --git a/Zeus_8_3_2_B_4_2.py b/Zeus_8_3_2_B_4_2.py index db9977a..97cb955 100644 --- a/Zeus_8_3_2_B_4_2.py +++ b/Zeus_8_3_2_B_4_2.py @@ -42,6 +42,7 @@ MAGENTA = "\033[35m" CYAN = "\033[36m" RESET = "\033[0m" + def pprint_df(dframe): print(tabulate(dframe, headers='keys', tablefmt='psql', showindex=False)) @@ -210,9 +211,14 @@ class Zeus_8_3_2_B_4_2(IStrategy): trades = list() max_profit_pairs = {} - protection_percent_buy_lost = IntParameter(1, 10, default=5, space='protection') - protection_fibo = IntParameter(1, 10, default=2, space='protection') - sell_allow_decrease = DecimalParameter(0.005, 0.02, default=0.2, decimals=2, space='sell', optimize=True, load=True) + sma20_deriv1_1d_protection = DecimalParameter(-0.1, 0.0, default=-0.05, decimals=2, space='protection', + optimize=True, load=True) + sma5_deriv1_1d_protection = DecimalParameter(-0.1, 0.0, default=-0.05, decimals=2, space='protection', + optimize=True, load=True) + sma24_deriv1_1h_protection = DecimalParameter(-1, 0.0, default=-0.05, decimals=1, space='protection', optimize=True, + load=True) + + # sma5_deriv1_1d_protection = DecimalParameter(-0.1, 0.0, default=-0.05, decimals=2, space='protection', optimize=True, load=True) # Récupération des labels ordonnés # labels = ['B5', 'B4', 'B3', 'B2', 'B1', 'N0', 'H1', 'H2', 'H3', 'H4', 'H5'] @@ -267,7 +273,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): } sma5_derive1_2_matrice_df = pd.DataFrame(sma5_derive1_2_matrice, index=index_labels) # Extraction de la matrice numérique - sma5_derive1_2_numeric_matrice = sma5_derive1_2_matrice_df.reindex(index=ordered_labels, columns=ordered_labels).values + sma5_derive1_2_numeric_matrice = sma5_derive1_2_matrice_df.reindex(index=ordered_labels, + columns=ordered_labels).values # paliers = {} @@ -296,7 +303,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): # 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: # poly_func, x_future, y_future, count = self.polynomial_forecast( @@ -428,7 +436,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): self.pairs[pair]['current_profit'] = current_profit self.pairs[pair]['max_profit'] = max(self.pairs[pair]['max_profit'], current_profit) - if last_candle['sma20_deriv1_1d'] > 0 and last_candle['sma5_deriv1_1d'] > 0 and last_candle['mid_smooth_1h_deriv1'] > 0\ + if last_candle['sma20_deriv1_1d'] > 0 and last_candle['sma5_deriv1_1d'] > 0 and last_candle[ + 'mid_smooth_1h_deriv1'] > 0 \ and last_candle['mid_smooth_1h_deriv2'] > 0: return None @@ -470,7 +479,6 @@ class Zeus_8_3_2_B_4_2(IStrategy): self.pairs[pair]['max_touch'] = max(last_candle['close'], self.pairs[pair]['max_touch']) - def getShortName(self, pair): return pair.replace("/USDT", '').replace("/USDC", '') @@ -508,10 +516,10 @@ class Zeus_8_3_2_B_4_2(IStrategy): # # interpolation linéaire # return start_factor + (pct - start_pct) * (end_factor - start_factor) / (end_pct - start_pct) - def log_trade(self, action, pair, date, trade_type=None, rate=None, dispo=None, profit=None, buys=None, stake=None, + def log_trade(self, action, pair, date, trade_type=None, rate=None, dispo=None, profit=None, buys=None, stake=None, last_candle=None): # Afficher les colonnes une seule fois - if self.config.get('runmode') == 'hyperopt': + if self.config.get('runmode') == 'hyperopt' or self.dp.runmode.value in ('hyperopt'): return if self.columns_logged % 10 == 0: self.printLog( @@ -521,7 +529,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): self.printLineLog() df = pd.DataFrame.from_dict(self.pairs, orient='index') colonnes_a_exclure = ['last_candle', 'last_trade', 'last_palier_index', 'stop', - 'trade_info', 'last_date', 'expected_profit', 'last_count_of_buys', 'base_stake_amount', 'stop_buy'] + 'trade_info', 'last_date', 'expected_profit', 'last_count_of_buys', + 'base_stake_amount', 'stop_buy'] df_filtered = df[df['count_of_buys'] > 0].drop(columns=colonnes_a_exclure) # df_filtered = df_filtered["first_buy", "last_max", "max_touch", "last_sell","last_buy", 'count_of_buys', 'current_profit'] @@ -587,10 +596,12 @@ class Zeus_8_3_2_B_4_2(IStrategy): color_smooth_1h = GREEN if last_candle['mid_smooth_1h_deriv1'] > 0 else RED color_smooth2_1h = GREEN if last_candle['mid_smooth_1h_deriv2'] > 0 else RED - last_max = int(self.pairs[pair]['last_max']) if self.pairs[pair]['last_max'] > 1 else round(self.pairs[pair]['last_max'],3) - last_min = int(self.pairs[pair]['last_min']) if self.pairs[pair]['last_min'] > 1 else round(self.pairs[pair]['last_min'], 3) + last_max = int(self.pairs[pair]['last_max']) if self.pairs[pair]['last_max'] > 1 else round( + self.pairs[pair]['last_max'], 3) + last_min = int(self.pairs[pair]['last_min']) if self.pairs[pair]['last_min'] > 1 else round( + self.pairs[pair]['last_min'], 3) - profit=str(round(self.pairs[pair]['current_profit'], 2)) + '/' + str(profit) + profit = str(round(self.pairs[pair]['current_profit'], 2)) + '/' + str(profit) self.printLog( f"| {date:<16} |{action:<10} | {pair[0:3]:<3} | {trade_type or '-':<18} |{rate or '-':>9}| {dispo or '-':>6} " @@ -600,10 +611,10 @@ class Zeus_8_3_2_B_4_2(IStrategy): # 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(val, 1) or '-' :>6}|" - f"{dist_max:>7}|{color_sma20}{round(last_candle['sma20_deriv1_1d'],2):>5}{RESET}" - f"|{color_sma5}{round(last_candle['sma5_deriv1_1d'],2):>5}{RESET}|{color_sma5_2}{round(last_candle['sma5_deriv2_1d'],2):>5}{RESET}" + f"{dist_max:>7}|{color_sma20}{round(last_candle['sma20_deriv1_1d'], 2):>5}{RESET}" + f"|{color_sma5}{round(last_candle['sma5_deriv1_1d'], 2):>5}{RESET}|{color_sma5_2}{round(last_candle['sma5_deriv2_1d'], 2):>5}{RESET}" f"|{color_sma5_1h}{round(last_candle['sma24_deriv1_1h'], 2):>5}{RESET}|{color_sma5_2h}{round(last_candle['sma24_deriv2_1h'], 2):>5}{RESET}" - f"|{color_smooth_1h}{round(last_candle['mid_smooth_1h_deriv1'],2):>5}{RESET}|{color_smooth2_1h}{round(last_candle['mid_smooth_1h_deriv2'],2):>5}{RESET}" + f"|{color_smooth_1h}{round(last_candle['mid_smooth_1h_deriv1'], 2):>5}{RESET}|{color_smooth2_1h}{round(last_candle['mid_smooth_1h_deriv2'], 2):>5}{RESET}" # f"|{last_candle['min60_1d']}|{last_candle['max60_1d']}" ) @@ -827,8 +838,14 @@ class Zeus_8_3_2_B_4_2(IStrategy): # =============================== # lissage des valeurs horaires dataframe['mid_smooth_1h'] = dataframe['mid'].rolling(window=6).mean() - dataframe["mid_smooth_1h_deriv1"] = 100 * dataframe["mid_smooth_1h"].diff().rolling(window=6).mean() / dataframe['mid_smooth_1h'] - dataframe["mid_smooth_1h_deriv2"] = 10 * dataframe["mid_smooth_1h_deriv1"].diff().rolling(window=6).mean() + dataframe["mid_smooth_1h_deriv1"] = 100 * dataframe["mid_smooth_1h"].diff().rolling(window=6).mean() / \ + dataframe['mid_smooth_1h'] + dataframe["mid_smooth_1h_deriv2"] = 100 * dataframe["mid_smooth_1h_deriv1"].diff().rolling(window=6).mean() + + dataframe['mid_smooth_5h'] = talib.EMA(dataframe, timeperiod=60) # dataframe['mid'].rolling(window=60).mean() + dataframe["mid_smooth_5h_deriv1"] = 100 * dataframe["mid_smooth_5h"].diff().rolling(window=60).mean() / \ + dataframe['mid_smooth_5h'] + dataframe["mid_smooth_5h_deriv2"] = 100 * dataframe["mid_smooth_5h_deriv1"].diff().rolling(window=60).mean() # Compter les baisses / hausses consécutives self.calculateDownAndUp(dataframe, limit=0.0001) @@ -891,7 +908,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): # self.calculateProbabilite2Index(dataframe, ['futur_percent_1d'], 'sma24_deriv1_1h', 'sma5_1d') dataframe['ema_volume'] = 20 * (dataframe['volume'] * dataframe['percent']) / ( - abs(dataframe['volume'].shift(1)) + abs(dataframe['volume'].shift(2))) + abs(dataframe['volume'].shift(1)) + abs(dataframe['volume'].shift(2))) self.calculeDerivees(dataframe, 'ema_volume', factor_1=10, factor_2=1) # if self.dp.runmode.value in ('backtest'): @@ -908,14 +925,18 @@ class Zeus_8_3_2_B_4_2(IStrategy): # indic_1 = 'mid_smooth_1h_deriv1' # indic_2 = 'mid_smooth_1h_deriv2' # self.calculateProbabilite2Index(dataframe, futur_cols, indic_1, indic_2) - dataframe['can_sell'] = np.where((dataframe['mid_smooth_3'].shift(1) > dataframe['mid_smooth_3']), dataframe['close'], np.nan) + dataframe['can_sell'] = np.where((dataframe['mid_smooth_3'].shift(1) > dataframe['mid_smooth_3']), + dataframe['close'], np.nan) - dataframe['can_buy'] = np.where((dataframe['mid_smooth_3'].shift(1) < dataframe['mid_smooth_3']), dataframe['close'], np.nan) + dataframe['can_buy'] = np.where((dataframe['mid_smooth_3'].shift(1) < dataframe['mid_smooth_3']), + dataframe['close'], np.nan) dataframe['perte_02'] = np.where((dataframe['percent3'] * 100 < -0.2), dataframe['close'], np.nan) - dataframe['mid_smooth_1h_deriv2_inv'] = np.where((dataframe['mid_smooth_1h_deriv2'].shift(2) >= dataframe['mid_smooth_1h_deriv2'].shift(1)) - & (dataframe['mid_smooth_1h_deriv2'].shift(1) <= dataframe['mid_smooth_1h_deriv2']), dataframe['close'], np.nan) + dataframe['mid_smooth_1h_deriv2_inv'] = np.where( + (dataframe['mid_smooth_1h_deriv2'].shift(2) >= dataframe['mid_smooth_1h_deriv2'].shift(1)) + & (dataframe['mid_smooth_1h_deriv2'].shift(1) <= dataframe['mid_smooth_1h_deriv2']), dataframe['close'], + np.nan) return dataframe @@ -979,7 +1000,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): # évènement "inversion vers le bas" (pente passe de >0 à <=0) sur chaque bougie cross_down = (dataframe['bb_ub_slope'].shift(1) > 0) & (dataframe['bb_ub_slope'] <= 0) dataframe['bb_cross_down'] = 10000 * cross_down * dataframe['bb_width'] \ - * (dataframe['bb_lowerband'] - dataframe['bb_lowerband'].shift(1)) / dataframe['bb_lowerband'] + * (dataframe['bb_lowerband'] - dataframe['bb_lowerband'].shift(1)) / dataframe[ + 'bb_lowerband'] # vrai si AU MOINS une inversion a eu lieu dans les 5 bougies *précédentes* (on exclut l'actuelle) inversion_last5 = cross_down.shift(1).rolling(5, min_periods=1).max().astype(bool) @@ -1013,10 +1035,10 @@ class Zeus_8_3_2_B_4_2(IStrategy): ( # (valid_inversion & inversion_last5 ) - (dataframe['mid_smooth_3'].shift(1) < dataframe['mid_smooth_3']) - & (dataframe['hapercent'] > 0) - & (dataframe['max_rsi_12'] < 70) - & (dataframe['open'] <= dataframe['bb_middleband']) + (dataframe['mid_smooth_3'].shift(1) < dataframe['mid_smooth_3']) + & (dataframe['hapercent'] > 0) + & (dataframe['max_rsi_12'] < 70) + & (dataframe['open'] <= dataframe['bb_middleband']) # valid_inversion # ((dataframe['bb_cross_down'] < - 0.1) @@ -1025,14 +1047,14 @@ class Zeus_8_3_2_B_4_2(IStrategy): # | (dataframe['bb_cross_down'].shift(3) < - 0.1) # ) # & (dataframe['hapercent'] > 0) - # & (dataframe['close'] * factor < dataframe['bb_upperband5']) + # & (dataframe['close'] * factor < dataframe['bb_upperband5']) # # # (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') + ), ['enter_long', 'enter_tag']] = (1, 'smth') dataframe['test'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.01, np.nan) @@ -1098,13 +1120,14 @@ class Zeus_8_3_2_B_4_2(IStrategy): 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])}]") + # 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 @@ -1139,7 +1162,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): max_stake: float, **kwargs): # ne rien faire si ordre deja en cours if trade.has_open_orders: - print("skip open orders") + # print("skip open orders") return None if (self.wallets.get_available_stake_amount() < 50): # or trade.stake_amount >= max_stake: return 0 @@ -1165,7 +1188,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): pct_first = 0 - total_counts = sum(pair_data['count_of_buys'] for pair_data in self.pairs.values() if not pair in ('BTC/USDT', 'BTC/USDC')) + total_counts = sum( + pair_data['count_of_buys'] for pair_data in self.pairs.values() if not pair in ('BTC/USDT', 'BTC/USDC')) if self.pairs[pair]['first_buy']: pct_first = self.getPctFirstBuy(pair, last_candle) @@ -1181,17 +1205,17 @@ class Zeus_8_3_2_B_4_2(IStrategy): if pair in ('BTC/USDT', 'BTC/USDC') or count_of_buys <= 2: lim = - pct - (count_of_buys * 0.001) - #lim = self.getLimitBuy(pair, last_candle, pct) + # lim = self.getLimitBuy(pair, last_candle, pct) # lim = - (0.012 * (1 + round(count_of_buys / 5)) + 0.001 * (count_of_buys - 1)) # lim = - (0.012 + 0.001 * (count_of_buys - 1) + (0.002 * count_of_buys if count_of_buys > 10 else 0.001 * count_of_buys if count_of_buys > 5 else 0)) else: pct = 0.05 lim = - pct - (count_of_buys * 0.001) - #lim = self.getLimitBuy(pair, last_candle, pct) + # lim = self.getLimitBuy(pair, last_candle, pct) if (len(dataframe) < 1): - print("skip dataframe") + # print("skip dataframe") return None if not self.should_enter_trade(pair, last_candle, current_time): @@ -1305,15 +1329,15 @@ class Zeus_8_3_2_B_4_2(IStrategy): # > - 0.03 ==>Avg. stake amount 253.535 USDT │ Total trade volume 145312.936 USDT 284 │ 1.19 │ 1014.898 │ 50.74| 1 day, 17:54:00 │ 283 0 1 99.6 │ 0.684 USDT 0.02% │ # > - 0.015 ==>Avg. stake amount 249.107 USDT │ Total trade volume 138186.861 USDT 275 │ 1.20 │ 901.976 │ 45.1 │ 1 day, 19:17:00 │ 274 0 1 99.6 │ 0.684 USDT 0.02% - condition = (last_candle['sma5_deriv1_1h'] > 0 or count_of_buys <= 5) #and \ - #(last_candle['mid_smooth_1h_deriv1'] > 0 and last_candle['mid_smooth_1h_deriv1']) + condition = (last_candle['sma5_deriv1_1h'] > 0 or count_of_buys <= 5) # and \ + # (last_candle['mid_smooth_1h_deriv1'] > 0 and last_candle['mid_smooth_1h_deriv1']) # last_candle['mid_smooth_1h_deriv1'] > - 0.05 #(last_candle['mid_smooth_3_deriv1'] > self.buy_mid_smooth_3_deriv1.value) and (last_candle['mid_smooth_24_deriv1'] > self.buy_mid_smooth_24_deriv1.value) # (last_candle['enter_long'] == 1 & (count_of_buys < 3)) \ # or ((before_last_candle['mid_re_smooth_3_deriv1'] <= 0) & (last_candle['mid_re_smooth_3_deriv1'] >= 0) & (3 <= count_of_buys < 6)) \ # or ((before_last_candle['mid_smooth_1h_deriv1'] <= 0) & (last_candle['mid_smooth_1h_deriv1'] >= 0) & (6 <= count_of_buys)) limit_buy = 40 - if (count_of_buys < limit_buy) and condition and (pct_max < lim) : + if (count_of_buys < limit_buy) and condition and (pct_max < lim): try: # if 6 <= count_of_buys: # if not ((before_last_candle_24['sma24_deriv1_1h'] > before_last_candle_12['sma24_deriv1_1h']) @@ -1367,7 +1391,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): return stake_amount except Exception as exception: - print(exception) + # print(exception) return None # if (count_of_buys >= 6): # self.log_trade( @@ -1388,7 +1412,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): # return -trade.stake_amount if (False and count_of_buys < limit_buy and pct_max > 0.004 and hours > 2 and condition - and last_candle['rsi'] < 65 and last_candle['rsi_deriv1'] > 0): + and last_candle['rsi'] < 65 and last_candle['rsi_deriv1'] > 0): try: self.pairs[pair]['has_gain'] += 1 stake_amount = self.pairs[pair]['first_amount'] @@ -1400,7 +1424,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): dispo=dispo, pair=trade.pair, rate=current_rate, - trade_type=str(round(pct_max,4)), + trade_type=str(round(pct_max, 4)), profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2), buys=trade.nr_of_successful_entries + 1, stake=round(stake_amount, 2) @@ -1410,7 +1434,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): self.pairs[trade.pair]['last_candle'] = last_candle return stake_amount except Exception as exception: - print(exception) + # print(exception) return None return None @@ -1429,11 +1453,12 @@ class Zeus_8_3_2_B_4_2(IStrategy): return 1 if last_candle['close'] < last_candle['min60_1d']: return 0 - return round((last_candle['close'] - last_candle['min60_1d']) / (last_candle['max60_1d'] - last_candle['min60_1d']), 4) + return round( + (last_candle['close'] - last_candle['min60_1d']) / (last_candle['max60_1d'] - last_candle['min60_1d']), 4) def getLimitBuy(self, pair, last_candle, first_pct): count_of_buys = self.pairs[pair]['count_of_buys'] - pct60 = self.getPct60D(pair, last_candle) # exemple 0.3 pour 30% + pct60 = self.getPct60D(pair, last_candle) # exemple 0.3 pour 30% if (pct60 < 0.05): lim = - first_pct - (count_of_buys * 0.001 * 0.05 / 0.05) else: @@ -1443,7 +1468,6 @@ class Zeus_8_3_2_B_4_2(IStrategy): return lim - # def getProbaHausseEmaVolume(self, last_candle): # value_1 = self.getValuesFromTable(self.ema_volume, last_candle['ema_volume']) # value_2 = self.getValuesFromTable(self.mid_smooth_1h_deriv1, last_candle['mid_smooth_1h_deriv1']) @@ -1475,7 +1499,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): base_stake_amount = self.config.get('stake_amount') # Montant de base configuré # pct60 = round(100 * self.getPctClose60D(pair, last_candle), 2) - if True: #not pair in ('BTC/USDT', 'BTC/USDC'): + if True: # not pair in ('BTC/USDT', 'BTC/USDC'): # factors = [1, 1.2, 1.3, 1.4] if self.pairs[pair]['count_of_buys'] == 0: pctClose60 = self.getPctClose60D(pair, last_candle) @@ -1483,7 +1507,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): adjusted_stake_amount = max(base_stake_amount / 5, base_stake_amount * (1 - pctClose60)) else: adjusted_stake_amount = self.pairs[pair]['first_amount'] - else : + else: first_price = self.pairs[pair]['first_buy'] if (first_price == 0): first_price = last_candle['close'] @@ -1563,7 +1587,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): # if last_candle['close'] < max_60: # pct_to_max = 0.25 * (max_60 - last_candle['close']) / max_60 # pct_to_max = pct_to_max * (2 - pctClose60) - expected_profit = max(0.004, pct_to_max) # 0.004 + 0.002 * self.pairs[pair]['count_of_buys'] #min(0.01, first_max) + expected_profit = max(0.004, + pct_to_max) # 0.004 + 0.002 * self.pairs[pair]['count_of_buys'] #min(0.01, first_max) # print( # f"Expected profit price={current_price:.4f} min_max={min_max:.4f} min_14={min_14_days:.4f} max_14={max_14_days:.4f} percent={percent:.4f} expected_profit={expected_profit:.4f}") @@ -2074,17 +2099,14 @@ class Zeus_8_3_2_B_4_2(IStrategy): ) # Résultat - print("Moyenne des valeurs par double-tranche :") - print(pivot_mean.round(2)) + # print("Moyenne des valeurs par double-tranche :") + # print(pivot_mean.round(2)) def should_enter_trade(self, pair: str, last_candle, current_time) -> bool: limit = 3 - if pair.startswith('BTC'): - return True # BTC toujours autorisé - - # Filtrer les paires non-BTC + # Filtrer les paires non-BTC non_btc_pairs = [p for p in self.pairs if not p.startswith('BTC')] # Compter les positions actives sur les paires non-BTC @@ -2099,11 +2121,11 @@ class Zeus_8_3_2_B_4_2(IStrategy): for p in non_btc_pairs: if (max_nb_trades == self.pairs[p]['count_of_buys'] and max_nb_trades > limit): - # if (max_amount == self.pairs[p]['total_amount'] and max_amount > limit_amount): + # if (max_amount == self.pairs[p]['total_amount'] and max_amount > limit_amount): max_pair = p total_non_btc += self.pairs[p]['count_of_buys'] - pct_max = self.getPctFirstBuy(pair, last_candle) #self.getPctLastBuy(pair, last_candle) + pct_max = self.getPctFirstBuy(pair, last_candle) # self.getPctLastBuy(pair, last_candle) val = self.getProbaHausseSma5d(last_candle) if val < 15: @@ -2114,18 +2136,25 @@ class Zeus_8_3_2_B_4_2(IStrategy): # char="." # print(f"should_enter_trade canceled all pairs decreased {'':{char}>{self.should_enter_trade_count}}") # return False + # if (last_candle['mid_smooth_1h_deriv1'] < -0.0 and last_candle['sma24_deriv1_1h'] < -0.0): + # return False if self.pairs[pair]['count_of_buys'] >= 3: - if (last_candle['sma20_deriv1_1d'] < -0.05 and last_candle['sma5_deriv1_1d'] < -0.05)\ - or (last_candle['sma5_deriv1_1d'] < -0.1 and last_candle['sma24_deriv1_1h'] < -0.1): + if (last_candle['sma20_deriv1_1d'] < self.sma20_deriv1_1d_protection.value + and last_candle['sma5_deriv1_1d'] < self.sma5_deriv1_1d_protection.value \ + and last_candle['sma24_deriv1_1h'] < self.sma24_deriv1_1h_protection.value): + # or (last_candle['sma5_deriv1_1d'] < -0.1 and last_candle['sma24_deriv1_1h'] < -0.1): return False + if pair.startswith('BTC'): + return True # BTC toujours autorisé + self.should_enter_trade_count = 0 # if max_pair != pair and self.pairs[pair]['total_amount'] > 300: # return False - if (max_pair != '') & (self.pairs[pair]['count_of_buys'] >= limit) : + if (max_pair != '') & (self.pairs[pair]['count_of_buys'] >= limit): trade = self.pairs[max_pair]['current_trade'] current_time = current_time.astimezone(timezone.utc) open_date = trade.open_date.astimezone(timezone.utc) @@ -2133,7 +2162,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): days_since_open = (current_time_utc - open_date).days pct_max_max = self.getPctFirstBuy(max_pair, last_candle) # print(f"days_since_open {days_since_open} max_pair={max_pair} pair={pair}") - return max_pair == pair or pct_max < - 0.25 or (pct_max_max < - 0.15 and max_pair != pair and days_since_open > 30) + return max_pair == pair or pct_max < - 0.25 or ( + pct_max_max < - 0.15 and max_pair != pair and days_since_open > 30) else: return True @@ -2142,16 +2172,16 @@ class Zeus_8_3_2_B_4_2(IStrategy): # 1. Détection plateau informative['rolling_min'] = informative['close'].rolling(plateau_duration).min() informative['rolling_max'] = informative['close'].rolling(plateau_duration).max() - informative['plateau_amplitude'] = (informative['rolling_max'] - informative['rolling_min']) / informative['rolling_min'] + informative['plateau_amplitude'] = (informative['rolling_max'] - informative['rolling_min']) / informative[ + 'rolling_min'] informative['plateau'] = informative['plateau_amplitude'] < plateau_tolerance # 2. Détection "fin de plateau" - #informative['plateau_end'] = (informative['plateau'] & ~informative['plateau'].shift(-1).fillna(False).astype(bool)) + # informative['plateau_end'] = (informative['plateau'] & ~informative['plateau'].shift(-1).fillna(False).astype(bool)) next_plateau = informative['plateau'].shift(-1) next_plateau = next_plateau.fillna(False).astype(bool) informative['plateau_end'] = informative['plateau'] & ~next_plateau - # 3. Enregistrer dernier plateau (min/max) last_min = None last_max = None @@ -2182,4 +2212,3 @@ class Zeus_8_3_2_B_4_2(IStrategy): informative['breakout_distance'] = [s[1] for s in last_status] return informative -