diff --git a/Zeus_11.py b/Zeus_11.py index 3b51534..bdcf82a 100644 --- a/Zeus_11.py +++ b/Zeus_11.py @@ -56,13 +56,12 @@ class Zeus_11(IStrategy): # Stoploss: stoploss = -1 # 0.256 # Custom stoploss - use_custom_stoploss = True + use_custom_stoploss = False # Buy hypers timeframe = '5m' - max_open_trades = 5 - max_amount = 40 + columns_logged = False # DCA config position_adjustment_enable = True @@ -179,14 +178,25 @@ class Zeus_11(IStrategy): # hard stoploss profit sell_allow_decrease = DecimalParameter(0.005, 0.02, default=0.2, decimals=2, space='sell', optimize=True, load=True) - # pHSL = DecimalParameter(-0.200, -0.040, default=-0.08, decimals=3, space='sell', optimize=False, load=True) - # # profit threshold 1, trigger point, SL_1 is used - # pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell', optimize=True, load=True) - # pSL_1 = DecimalParameter(0.008, 0.020, default=0.011, decimals=3, space='sell', optimize=True, load=True) - # - # # profit threshold 2, SL_2 is used - # pPF_2 = DecimalParameter(0.040, 0.100, default=0.080, decimals=3, space='sell', optimize=True, load=True) - # pSL_2 = DecimalParameter(0.020, 0.070, default=0.040, decimals=3, space='sell', optimize=True, load=True) + pairs = { + pair: { + "first_buy": 0, + "last_max": 0, + "trade_info": {}, + "max_touch": 0.0, + "last_sell": 0.0, + "last_buy": 0.0, + 'count_of_buys': 0, + 'current_profit': 0, + 'expected_profit': 0, + "last_candle": {}, + "last_trade": None, + 'base_stake_amount': 0, + 'stop_buy': False + } + for pair in ["BTC/USDC", "ETH/USDC", "DOGE/USDC", "DASH/USDC", "XRP/USDC", "SOL/USDC", + "BTC/USDT", "ETH/USDT", "DOGE/USDT", "DASH/USDT", "XRP/USDT", "SOL/USDT"] + } def min_max_scaling(self, series: pd.Series) -> pd.Series: """Normaliser les données en les ramenant entre 0 et 100.""" @@ -212,7 +222,32 @@ class Zeus_11(IStrategy): allow_to_buy = True # (rate <= float(limit)) | (entry_tag == 'force_entry') self.trades = list() dispo = round(self.wallets.get_available_stake_amount()) - print(f"BUY {pair} {entry_tag} {current_time} allow_to_buy={allow_to_buy} dispo={dispo}") + + self.pairs[pair]['first_buy'] = rate + self.pairs[pair]['last_buy'] = rate + self.pairs[pair]['max_touch'] = last_candle['close'] + self.pairs[pair]['last_candle'] = last_candle + self.pairs[pair]['count_of_buys'] = 1 + self.pairs[pair]['current_profit'] = 0 + + print( + f"|{'-' * 18}+{'-' * 12}+{'-' * 12}+{'-' * 20}+{'-' * 14}+{'-' * 8}+{'-' * 10}+{'-' * 7}+{'-' * 13}+{'-' * 14}+{'-' * 14}+{'-' * 7}+{'-' * 12}|" + ) + + stake_amount = self.adjust_stake_amount(pair, last_candle) + + self.log_trade( + last_candle=last_candle, + date=current_time, + action="START BUY", + pair=pair, + rate=rate, + dispo=dispo, + profit=0, + trade_type=entry_tag, + buys=1, + stake=round(stake_amount, 2) + ) return allow_to_buy @@ -226,11 +261,27 @@ class Zeus_11(IStrategy): allow_to_sell = (last_candle['percent'] < 0) if allow_to_sell: + self.pairs[pair]['last_sell'] = rate + self.pairs[pair]['last_trade'] = trade + self.pairs[pair]['last_candle'] = last_candle self.trades = list() dispo= round(self.wallets.get_available_stake_amount()) - print(f"Sell {pair} {current_time} {exit_reason} dispo={dispo} amount={amount} rate={rate} open_rate={trade.open_rate}") - else: - print('Cancel Sell ' + exit_reason + ' ' + str(current_time) + ' ' + pair) + # print(f"Sell {pair} {current_time} {exit_reason} dispo={dispo} amount={amount} rate={rate} open_rate={trade.open_rate}") + self.log_trade( + last_candle=last_candle, + date=current_time, + action="Sell", + pair=pair, + trade_type=exit_reason, + rate=last_candle['close'], + dispo=dispo, + profit=round(trade.calc_profit(rate, amount), 2) + ) + self.pairs[pair]['max_touch'] = 0 + self.pairs[pair]['last_buy'] = 0 + + # else: + # print('Cancel Sell ' + exit_reason + ' ' + str(current_time) + ' ' + pair) return (allow_to_sell) | (exit_reason == 'force_exit') def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, @@ -253,19 +304,17 @@ class Zeus_11(IStrategy): before_last_candle = dataframe.iloc[-2].squeeze() count_of_buys = trade.nr_of_successful_entries + max_touch_before = self.pairs[pair]['max_touch'] + self.pairs[pair]['last_max'] = max(last_candle['haclose'], self.pairs[pair]['last_max']) - # self.analyze_conditions(pair, dataframe) + last_lost = (last_candle['close'] - max_touch_before) / max_touch_before + count_of_buys = trade.nr_of_successful_entries + + self.pairs[pair]['count_of_buys'] = count_of_buys + self.pairs[pair]['current_profit'] = current_profit - # print("---------------" + pair + "----------------") expected_profit = self.expectedProfit(pair, last_candle) - # Calcul du prix cible basé sur l'ATR - atr_take_profit = trade.open_rate + (last_candle['atr'] * 2) # Prendre profit à 2x l'ATR - - # print(f"{pair} Custom exit atr_take_profit={atr_take_profit:.4f}") - # if current_rate >= atr_take_profit: - # return 'sell_atr_take_profit' - if (last_candle['percent3'] < 0.0) & (current_profit > last_candle['min_max200'] / 3): self.trades = list() return 'min_max200_' + str(count_of_buys) @@ -284,6 +333,59 @@ class Zeus_11(IStrategy): return informative_pairs + 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': + return + if self.columns_logged % 30 == 0: + # print( + # f"|{'-' * 18}+{'-' * 12}+{'-' * 12}+{'-' * 20}+{'-' * 14}+{'-' * 8}+{'-' * 10}+{'-' * 7}+{'-' * 13}+{'-' * 14}+{'-' * 14}+{'-' * 7}+{'-' * 12}|" + # ) + print( + f"| {'Date':<16} | {'Action':<10} | {'Pair':<10} | {'Trade Type':<18} | {'Rate':>12} | {'Dispo':>6} | {'Profit':>8} | {'Pct':>5} | {'max_touch':>11} | {'last_lost':>12} | {'last_max':>12} | {'Buys':>5} | {'Stake':>10} |" + ) + print( + f"|{'-' * 18}+{'-' * 12}+{'-' * 12}+{'-' * 20}+{'-' * 14}+{'-' * 8}+{'-' * 10}+{'-' * 7}+{'-' * 13}+{'-' * 14}+{'-' * 14}+{'-' * 7}+{'-' * 12}|" + ) + self.columns_logged += 1 + date = str(date)[:16] if date else "-" + limit = None + # if buys is not None: + # limit = round(last_rate * (1 - self.fibo[buys] / 100), 4) + + rsi = '' + rsi_pct = '' + # if last_candle is not None: + # if (not np.isnan(last_candle['rsi_1d'])) and (not np.isnan(last_candle['rsi_1h'])): + # rsi = str(int(last_candle['rsi_1d'])) + " " + str(int(last_candle['rsi_1h'])) + # if (not np.isnan(last_candle['rsi_pct_1d'])) and (not np.isnan(last_candle['rsi_pct_1h'])): + # rsi_pct = str(int(10000 * last_candle['bb_mid_pct_1d'])) + " " + str( + # int(last_candle['rsi_pct_1d'])) + " " + str(int(last_candle['rsi_pct_1h'])) + + # first_rate = self.percent_threshold.value + # last_rate = self.threshold.value + # action = self.color_line(action, action) + sma5_1d = '' + sma5_1h = '' + + sma5 = str(sma5_1d) + ' ' + str(sma5_1h) + + last_lost = round((last_candle['haclose'] - self.pairs[pair]['max_touch']) / self.pairs[pair]['max_touch'], 3) + + 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: + trade_type = trade_type \ + + " " + str(round(100 * self.pairs[pair]['expected_profit'], 1)) + # + " " + str(round(last_candle['sma5_diff_1d'], 1)) \ + # + " " + str(round(last_candle['sma5_diff_1h'], 1)) + + print( + f"| {date:<16} | {action:<10} | {pair:<10} | {trade_type or '-':<18} | {rate or '-':>12} | {dispo or '-':>6} | {profit or '-':>8} | {pct_max or '-':>5} | {max_touch or '-':>11} | {last_lost or '-':>12} | {round(self.pairs[pair]['last_max'], 2) or '-':>12} | {buys or '-':>5} | {stake or '-':>10} |" + ) + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # Add all ta features pair = metadata['pair'] @@ -540,33 +642,21 @@ class Zeus_11(IStrategy): self.trades = Trade.get_open_trades() return self.trades - # def getTrade(self, pair): - # trades = self.getOpenTrades() - # trade_for_pair = None - # for trade in trades: - # if trade.pair == pair: - # trade_for_pair = trade - # break - # return trade_for_pair - def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: pair = metadata['pair'] - # self.getOpenTrades() - expected_profit = self.expectedProfit(pair, dataframe.iloc[-1]) - # self.getBinanceOrderBook(pair, dataframe) - last_candle = dataframe.iloc[-1].squeeze() + #expected_profit = self.expectedProfit(pair, dataframe.iloc[-1]) + #last_candle = dataframe.iloc[-1].squeeze() - print("---------------" + pair + "----------------") - print('adjust stake amount ' + str(self.adjust_stake_amount(pair, dataframe.iloc[-1]))) - # print('adjust exit price ' + str(self.adjust_exit_price(dataframe.iloc[-1]))) - print('calcul expected_profit ' + str(expected_profit)) + # print("---------------" + pair + "----------------") + # print('adjust stake amount ' + str(self.adjust_stake_amount(pair, dataframe.iloc[-1]))) + # # print('adjust exit price ' + str(self.adjust_exit_price(dataframe.iloc[-1]))) + # print('calcul expected_profit ' + str(expected_profit)) - buy_level = dataframe['buy_level'] # self.get_buy_level(pair, dataframe) + # buy_level = dataframe['buy_level'] # self.get_buy_level(pair, dataframe) dataframe.loc[ ( - # (dataframe['hapercent'] > 0) (dataframe['down_count'].shift(1) < - 6) & (dataframe['down_count'] == 0) & (dataframe['down_pct'].shift(1) <= -0.5) @@ -599,7 +689,7 @@ class Zeus_11(IStrategy): if (len(dataframe) < 1): return None pair = trade.pair - if pair not in ('BTC/USDC', 'XRP/USDC'): + if pair not in ('BTC/USDC', 'XRP/USDC', 'BTC/USDT', 'XRP/USDT'): return None max_buys = 20 @@ -619,17 +709,33 @@ class Zeus_11(IStrategy): current_time_utc = current_time.astimezone(timezone.utc) open_date = trade.open_date.astimezone(timezone.utc) days_since_open = (current_time_utc - open_date).days + pct_max = round((last_candle['close'] - self.pairs[trade.pair]['last_buy']) / self.pairs[trade.pair]['last_buy'], 3) # if (days_since_open > count_of_buys) & (0 < count_of_buys <= max_buys) & (current_rate <= limit) & (last_candle['enter_long'] == 1): if ((last_candle['enter_long'] == 1) or last_candle['percent48'] < - 0.03) \ - and ( hours > 48 or (current_profit < -0.015 * count_of_buys and hours > 6)): + and (pct_max < -0.015): try: # This then calculates current safety order size # stake_amount = stake_amount * pow(1.5, count_of_buys) - print( - f"Adjust {current_time} price={trade.pair} rate={current_rate:.4f} buys={count_of_buys} limit={limit:.4f} stake={stake_amount:.4f}") + # print( + # f"Adjust {current_time} price={trade.pair} rate={current_rate:.4f} buys={count_of_buys} limit={limit:.4f} stake={stake_amount:.4f}") + self.log_trade( + last_candle=last_candle, + date=current_time, + action="Loss -", + dispo=dispo, + pair=trade.pair, + rate=current_rate, + trade_type=last_candle['enter_tag'], + profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2), + buys=trade.nr_of_successful_entries + 1, + stake=round(stake_amount, 2) + ) + self.pairs[trade.pair]['last_buy'] = current_rate + self.pairs[trade.pair]['max_touch'] = last_candle['close'] + self.pairs[trade.pair]['last_candle'] = last_candle return stake_amount except Exception as exception: print(exception)