Nouvelle version Zeus_8_3_2_B_4_2.py

This commit is contained in:
Jérôme Delacotte
2025-04-17 16:48:44 +02:00
parent 7e169a9fe6
commit f47836c4b7
2 changed files with 311 additions and 150 deletions

View File

@@ -94,7 +94,27 @@ class Zeus_8_3_2_B_4_2(IStrategy):
}
}
}
columns_logged = False
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,
"last_count_of_buys": 0,
'base_stake_amount': 0,
'stop_buy': False
}
for pair in ["BTC/USDC", "ETH/USDC", "DOGE/USDC", "XRP/USDC", "SOL/USDC",
"BTC/USDT", "ETH/USDT", "DOGE/USDT", "XRP/USDT", "SOL/USDT"]
}
# 20 20 40 60 100 160 260 420
# 50 50 100 300 500
# fibo = [1, 1, 2, 3, 5, 8, 13, 21]
@@ -209,7 +229,32 @@ class Zeus_8_3_2_B_4_2(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}+{'-' * 5}+{'-' * 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
@@ -223,11 +268,27 @@ class Zeus_8_3_2_B_4_2(IStrategy):
allow_to_sell = (last_candle['percent'] < 0)
if allow_to_sell:
self.trades = list()
self.pairs[pair]['last_count_of_buys'] = self.pairs[pair]['count_of_buys']
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
return (allow_to_sell) | (exit_reason == 'force_exit')
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
@@ -247,26 +308,39 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze()
before_last_candle = dataframe.iloc[-2].squeeze()
# self.analyze_conditions(pair, dataframe)
# 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
max_touch_before = self.pairs[pair]['max_touch']
self.pairs[pair]['last_max'] = max(last_candle['haclose'], self.pairs[pair]['last_max'])
# print(f"{pair} Custom exit atr_take_profit={atr_take_profit:.4f}")
# if current_rate >= atr_take_profit:
# return 'sell_atr_take_profit'
count_of_buys = trade.nr_of_successful_entries
if (last_candle['percent3'] < -0.002) & (last_candle['percent12'] < 0) & (
current_profit > last_candle['min_max200'] / 3):
self.pairs[pair]['count_of_buys'] = count_of_buys
self.pairs[pair]['current_profit'] = current_profit
pct_first = round((last_candle['close'] - self.pairs[pair]['first_buy']) / self.pairs[pair]['first_buy'], 3)
# if (last_candle['rsi_1d'] > 50) & (last_candle['percent12'] < 0.0):
if (last_candle['percent3'] < 0.0) & (current_profit > last_candle['min_max200'] / 3):
self.trades = list()
return 'min_max200'
return 'mx_' + str(count_of_buys)
if (last_candle['percent12'] <= -0.01) & (current_profit >= expected_profit):
self.trades = list()
return 'profit'
return 'profit_' + str(count_of_buys)
if (current_profit >= expected_profit) & (last_candle['percent'] < 0.0) \
and ((last_candle['rsi'] >= 75) or before_last_candle['rsi'] >= 75):
self.trades = list()
return 'rsi_' + str(count_of_buys)
# if (last_candle['percent3'] < -0.002) & (last_candle['percent12'] < 0) & (
# current_profit > last_candle['min_max200'] / 3):
# self.trades = list()
# return 'mnmx_' + str(count_of_buys)
# if (last_candle['percent12'] <= -0.01) & (current_profit >= expected_profit):
# self.trades = list()
# return 'profit_' + str(count_of_buys)
self.pairs[pair]['max_touch'] = max(last_candle['haclose'], self.pairs[pair]['max_touch'])
def informative_pairs(self):
# get access to all pairs available in whitelist.
@@ -276,6 +350,63 @@ class Zeus_8_3_2_B_4_2(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':<5}| {'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}+{'-' * 5}+{'-' * 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:
if np.isnan(last_candle['rsi_1d']):
string = ' '
else:
string = (str(int(last_candle['rsi_1d']))) + " " + str(int(last_candle['rsi_diff_1d']))
trade_type = trade_type \
+ " " + string \
+ " " + str(int(last_candle['rsi_1h'])) \
+ " " + str(int(last_candle['rsi_diff_1h']))
print(
f"| {date:<16} | {action:<10} | {pair[0:3]:<3} | {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']
@@ -333,7 +464,9 @@ class Zeus_8_3_2_B_4_2(IStrategy):
(dataframe["close"] - dataframe["bb_lowerband"]) /
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
)
dataframe["bb_width"] = (
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_upperband"]
)
# Normalization
dataframe['average_line'] = dataframe['close'].mean()
@@ -357,18 +490,18 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# # Calculate the mean of the 4 highest values
dataframe['highest_4_average'] = highest_4.mean()
# # Propagate this mean value across the entire dataframe
# dataframe['highest_4_average'] = dataframe['highest_4_average'].iloc[0]
dataframe['volatility'] = talib.STDDEV(dataframe['close'], timeperiod=144) / dataframe['close']
dataframe['atr'] = talib.ATR(dataframe['high'], dataframe['low'], dataframe['close'], timeperiod=144) / \
dataframe['close']
# dataframe['pct_average'] = (dataframe['highest_4_average'] - dataframe['close']) / dataframe['lowest_4_average']
# dataframe['highest_4_average_1'] = dataframe['highest_4_average'] * 0.99
# dataframe['highest_4_average_2'] = dataframe['highest_4_average'] * 0.98
# dataframe['highest_4_average_3'] = dataframe['highest_4_average'] * 0.97
# dataframe['highest_4_average_4'] = dataframe['highest_4_average'] * 0.96
# dataframe['highest_4_average_5'] = dataframe['highest_4_average'] * 0.95
# Compter les baisses consécutives
dataframe['down'] = dataframe['hapercent'] <= 0.001
dataframe['up'] = dataframe['hapercent'] >= 0.0001
dataframe['down_count'] = - dataframe['down'].astype(int) * (
dataframe['down'].groupby((dataframe['down'] != dataframe['down'].shift()).cumsum()).cumcount() + 1)
dataframe['up_count'] = dataframe['up'].astype(int) * (
dataframe['up'].groupby((dataframe['up'] != dataframe['up'].shift()).cumsum()).cumcount() + 1)
dataframe['down_tag'] = (dataframe['down_count'] < -7)
dataframe['up_tag'] = (dataframe['up_count'] > 7)
# Créer une colonne vide
dataframe['down_pct'] = self.calculateUpDownPct(dataframe, 'down_count')
dataframe['up_pct'] = self.calculateUpDownPct(dataframe, 'up_count')
# Normaliser les données de 'close'
# normalized_close = self.min_max_scaling(dataframe['close'])
@@ -376,10 +509,21 @@ class Zeus_8_3_2_B_4_2(IStrategy):
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
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'], length=7)
informative['rsi_diff'] = informative['rsi'] - informative['rsi'].shift(1)
informative['sma5'] = talib.SMA(informative, timeperiod=5)
informative['sma5_pct'] = 100 * (informative['sma5'] - informative['sma5'].shift(1)) / informative['sma5']
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['rsi'] = talib.RSI(informative['close'], length=7)
informative['rsi_diff'] = informative['rsi'] - informative['rsi'].shift(1)
informative['sma5'] = talib.SMA(informative, timeperiod=5)
informative['sma5_pct'] = 100 * (informative['sma5'] - informative['sma5'].shift(1)) / informative['sma5']
sorted_close_prices = informative['close'].tail(365).sort_values()
lowest_4 = sorted_close_prices.head(4)
informative['lowest_4'] = lowest_4.mean()
@@ -461,7 +605,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# # for buy in filled_buys:
# # print(filled_buys)
dataframe['buy_level'] = dataframe['lowest_4_average'] * (1 - self.levels[count_buys] / 100)
# dataframe['buy_level'] = dataframe['lowest_4_average'] * (1 - self.levels[count_buys] / 100)
# ----------------------------------------------------------
# Calcul de la variation entre deux bougies successives
dataframe['price_change'] = dataframe['close'].diff()
@@ -540,71 +684,20 @@ 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['buy_level'] # self.get_buy_level(pair, dataframe)
buy_level = dataframe['average_line_50'] #dataframe['buy_level'] # self.get_buy_level(pair, dataframe)
dataframe.loc[
(
(dataframe['close'] <= dataframe['min200'] * 1.002)
& (dataframe['percent_max_144'] <= -0.012)
& (dataframe['haopen'] < buy_level)
& (dataframe['open'] < dataframe['average_line_288'])
& (dataframe['min50'].shift(3) == dataframe['min50'])
), ['buy', 'enter_tag']] = (1, 'buy_fractal')
dataframe.loc[
(
(dataframe['max200_diff'].shift(4) >= 0.015)
& (dataframe['close'] <= dataframe['lowest_4_average'] * 1.002)
& (dataframe['close'] <= dataframe['min200'] * 1.002)
& (dataframe['max50_diff'].shift(4) >= 0.01)
& (dataframe['haclose'] < dataframe['bb_middleband'])
& (dataframe['close'] < buy_level)
& (dataframe['open'] < dataframe['average_line_288'])
& (dataframe['min50'].shift(3) == dataframe['min50'])
), ['buy', 'enter_tag']] = (1, 'buy_max_diff_015')
dataframe.loc[
(
(dataframe['max200_diff'] >= 0.018)
& (dataframe['close'] <= dataframe['lowest_4_average'] * 1.002)
& (dataframe['max50_diff'] >= 0.009)
& (dataframe['close'] <= dataframe['min200'] * 1.002)
& (dataframe['haclose'] < dataframe['bb_middleband'])
& (dataframe['close'] < buy_level)
& (dataframe['open'] < dataframe['average_line_288'])
& (dataframe['min50'].shift(3) == dataframe['min50'])
), ['buy', 'enter_tag']] = (1, 'buy_max_diff_018')
# dataframe.loc[
# (
# (dataframe['max200_diff'] >= 0.018)
# & (dataframe['open'] < dataframe['average_line_288'])
# & (dataframe['close'] < dataframe['min12'] * 1.002)
# & (dataframe['min12'].shift(2) == dataframe['min12'])
# ), ['buy', 'enter_tag']] = (1, 'buy_min_max200')
dataframe.loc[
(
(dataframe['max200_diff'] >= 0.025)
& (dataframe['percent12'] < -0.002)
& (dataframe['pct_change'] < 0)
# & (dataframe['pct_change'] < 0)
& (dataframe['open'] < dataframe['average_line_288_099'])
& (dataframe['open'] < dataframe['average_line_50'])
& (dataframe['count_buys'] == 0 |
((dataframe['count_buys'] > 0) & (dataframe['close'] <= dataframe['limit']))
)
& (dataframe['percent'] >= -0.0005)
& (dataframe['min12'].shift(2) == dataframe['min12'])
), ['enter_long', 'enter_tag']] = (1, 'buy_min_max200_2')
dataframe.loc[
(
((dataframe['count_buys'] > 0) & (dataframe['close'] <= dataframe['limit']))
& (dataframe['close'] < dataframe['min200'] * 1.002)
# & (dataframe['percent'] >= -0.0005)
& (
(dataframe['min12'].shift(2) == dataframe['min12']) |
(dataframe['min200'].shift(60) >= dataframe['min200'] * 1.03)
)
), ['enter_long', 'enter_tag']] = (1, 'buy_count_buy')
& (dataframe['min12'].shift(2) == dataframe['min12'])
& (dataframe['up_count'] > 0)
& (dataframe["bb_width"] > 0.01)
), ['enter_long', 'enter_tag']] = (1, 'mx200')
dataframe.loc[
(
@@ -626,51 +719,20 @@ class Zeus_8_3_2_B_4_2(IStrategy):
| (dataframe['percent12'] < -0.022)
| (dataframe['percent24'] < -0.022)
)
), ['enter_long', 'enter_tag']] = (1, 'buy_0_percent12')
dataframe.loc[
(
# (dataframe['percent12'] < -0.015)
((dataframe['count_buys'] > 0) & (dataframe['close'] <= dataframe['limit']))
& (dataframe['open'] < dataframe['average_line_50'])
& (dataframe['close'] < dataframe['min12'] * 1.002)
& (dataframe['min12'].shift(2) == dataframe['min12'])
), ['enter_long', 'enter_tag']] = (1, 'buy_percent12')
& (dataframe['up_count'] > 0)
& (dataframe["bb_width"] > 0.01)
), ['enter_long', 'enter_tag']] = (1, 'pct12')
dataframe.loc[
(
(dataframe['percent_max_144'] <= -0.02)
& (dataframe['close'] <= dataframe['lowest_4_average'] * 1.002)
& (dataframe['haopen'] < buy_level)
& (dataframe['min50'].shift(3) == dataframe['min50'])
& (dataframe['close'] <= dataframe['min50'] * 1.002)
& (dataframe['open'] < dataframe['average_line_288'])
), ['enter_long', 'enter_tag']] = (1, 'buy_percent_max_144')
dataframe.loc[
(
(dataframe['close'] <= dataframe['min200'] * 1.002)
& (dataframe["bb_width"] > 0.01)
& (dataframe['min_max200'] > 0.015)
& (dataframe['pct_change'] < 0)
# & (dataframe['pct_change'] < 0)
& (dataframe['haopen'] < buy_level)
& (dataframe['open'] < dataframe['average_line_288'])
), ['enter_long', 'enter_tag']] = (1, 'buy_min_max_200')
dataframe.loc[
(
(dataframe['percent_max_144'] <= -0.02)
& (dataframe['close'] <= dataframe['lowest_4_average'] * 1.002)
& (dataframe['close_02'] < dataframe['max144'])
& (dataframe['haopen'] < buy_level)
& (dataframe['close'] <= dataframe['average_line_288_099'])
& (dataframe['min50'].shift(3) == dataframe['min50'])
& (dataframe['close'] <= dataframe['min50'] * 1.002)
), ['enter_long', 'enter_tag']] = (1, 'buy_close_02')
dataframe.loc[
(
(dataframe['close'] <= dataframe['lowest_4_average'] * 1.002)
& (dataframe['haopen'] >= dataframe['average_line_288_098'])
& (dataframe['haclose'] <= dataframe['average_line_288_098'])
& (dataframe['haopen'] < buy_level)
), ['enter_long', 'enter_tag']] = (1, 'buy_average_line_288_098')
& (dataframe['up_count'] > 0)
), ['enter_long', 'enter_tag']] = (1, 'mnmx200')
dataframe.loc[
(
(dataframe['close'].shift(2) <= dataframe['min200'])
@@ -680,7 +742,18 @@ class Zeus_8_3_2_B_4_2(IStrategy):
& (dataframe['count_buys'] == 0 |
((dataframe['count_buys'] > 0) & (dataframe['close'] <= dataframe['limit']))
)
), ['enter_long', 'enter_tag']] = (1, 'buy_min200')
& (dataframe['up_count'] > 0)
), ['enter_long', 'enter_tag']] = (1, 'min200')
dataframe.loc[
(
# (dataframe['rsi_1h'] < 70)
# & (dataframe['rsi_diff_1h'] > -5)
(dataframe["bb_width"] > 0.01)
& (dataframe['down_count'].shift(1) < - 6)
& (dataframe['down_count'] == 0)
& (dataframe['down_pct'].shift(1) <= -0.5)
), ['enter_long', 'enter_tag']] = (1, 'down')
dataframe['test'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.01, np.nan)
@@ -701,7 +774,6 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze()
# prépare les données
count_of_buys = trade.nr_of_successful_entries
current_time = current_time.astimezone(timezone.utc)
open_date = trade.open_date.astimezone(timezone.utc)
dispo = round(self.wallets.get_available_stake_amount())
@@ -712,12 +784,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
pair = trade.pair
if pair not in ('BTC/USDT', 'DOGE/USDT', 'ETH/USDT'):
return None
max_buys = 7
filled_buys = trade.select_filled_orders('buy')
count_of_buys = len(filled_buys)
if count_of_buys >= max_buys:
return None
count_of_buys = trade.nr_of_successful_entries
# if 'buy' in last_candle:
# condition = (last_candle['buy'] == 1)
@@ -725,43 +792,58 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# condition = False
# self.protection_nb_buy_lost.value
limit = last_candle['limit']
stake_amount = min(200, self.adjust_stake_amount(pair, last_candle) * self.fibo[count_of_buys])
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_first = round((last_candle['close'] - self.pairs[pair]['first_buy']) / self.pairs[pair]['first_buy'], 3)
pct_max = round((last_candle['close'] - self.pairs[trade.pair]['last_buy']) / self.pairs[trade.pair]['last_buy'], 4)
pct = 0.012
stake_amount = min(self.wallets.get_available_stake_amount(), self.adjust_stake_amount(pair, last_candle) - 20 * pct_first / pct) #min(200, self.adjust_stake_amount(pair, last_candle) * self.fibo[count_of_buys])
# if (days_since_open > count_of_buys) & (0 < count_of_buys <= max_buys) & (current_rate <= limit) & (last_candle['enter_long'] == 1):
limit_buy = 5
limit_buy = 20
if (count_of_buys < limit_buy) \
and ((last_candle['enter_long'] == 1) or last_candle['percent48'] < - 0.03) \
and (current_profit < -0.015 * count_of_buys) \
and (last_candle['enter_long'] == 1):
and ((last_candle['enter_long'] == 1) or last_candle['percent48'] < - 0.03) \
and (last_candle['enter_long'] == 1) \
and (pct_max < - pct - (count_of_buys * 0.001)):
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}")
trade_type = last_candle['enter_tag'] if last_candle['enter_long'] == 1 else 'pct48'
self.log_trade(
last_candle=last_candle,
date=current_time,
action="Loss -",
dispo=dispo,
pair=trade.pair,
rate=current_rate,
trade_type=trade_type,
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)
return None
return None
def adjust_stake_amount(self, pair: str, dataframe: DataFrame):
def adjust_stake_amount(self, pair: str, last_candle: DataFrame):
# Calculer le minimum des 14 derniers jours
current_price = dataframe['close']
current_price = last_candle['close']
# trade = self.getTrade(pair)
# if trade:
# current_price = trade.open_rate
base_stake_amount = self.config.get('stake_amount', 50) # Montant de base configuré
base_stake_amount = self.config.get('stake_amount', 100) # Montant de base configuré
# Calculer le max des 14 derniers jours
min_14_days_4 = dataframe['lowest_4_1d']
max_14_days_4 = dataframe['highest_4_1d']
min_14_days_4 = last_candle['lowest_4_1d']
max_14_days_4 = last_candle['highest_4_1d']
percent_4 = 1 - (current_price - min_14_days_4) / (max_14_days_4 - min_14_days_4)
factor_4 = 1 / ((current_price - min_14_days_4) / (max_14_days_4 - min_14_days_4))
max_min_4 = max_14_days_4 / min_14_days_4
@@ -773,7 +855,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# max_min = max_14_days / min_14_days
# Stack amount ajusté price=2473.47 min_max=0.15058074985054215 percent=0.8379141364642171 amount=20.0
adjusted_stake_amount = max(base_stake_amount / 2.5, min(100, base_stake_amount * percent_4))
adjusted_stake_amount = max(base_stake_amount, min(100, base_stake_amount * percent_4))
# if pair in ('BTC/USDT', 'ETH/USDT'):
# if percent_4 > 0.5:
# adjusted_stake_amount = 300
@@ -1236,3 +1318,13 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# print(asks_with_sma)
return asks_with_sma, bids_with_sma
def calculateUpDownPct(self, dataframe, key):
down_pct_values = np.full(len(dataframe), np.nan)
# Remplir la colonne avec les bons calculs
for i in range(len(dataframe)):
shift_value = abs(int(dataframe[key].iloc[i])) # Récupérer le shift actuel
if i - shift_value > 1: # Vérifier que le shift ne dépasse pas l'index
down_pct_values[i] = 100 * (dataframe['close'].iloc[i] - dataframe['close'].iloc[i - shift_value]) / \
dataframe['close'].iloc[i - shift_value]
return down_pct_values

69
tools/chute.py Normal file
View File

@@ -0,0 +1,69 @@
import pandas as pd
def detect_btc_crashes_and_rebounds(df, drop_threshold=-10, rebound_threshold=5):
"""
Identifie les plus grosses chutes du BTC et le rebond suivant.
Paramètres :
- df : DataFrame contenant une colonne 'close' avec les prix du BTC.
- drop_threshold : Seuil de chute en % (ex: -10 pour une chute > 10%).
- rebound_threshold : Seuil de rebond en % après la chute.
Retourne :
- Une liste des chutes avec le pourcentage de rebond correspondant.
"""
df['return'] = df['close'].pct_change() * 100 # Variation en %
crashes = []
in_crash = False
crash_start, crash_end, bottom, rebound_end = None, None, None, None
for i in range(1, len(df)):
change = df.loc[i, 'return']
# Début d'une chute
if change < drop_threshold and not in_crash:
crash_start = i - 1
in_crash = True
# En pleine chute, trouver le creux
if in_crash:
if bottom is None or df.loc[i, 'close'] < df.loc[bottom, 'close']:
bottom = i
# Fin de la chute et début du rebond
if in_crash and change > 0:
crash_end = i
# Identifier un rebond
if in_crash and crash_end:
rebound_percent = (df.loc[i, 'close'] - df.loc[bottom, 'close']) / df.loc[bottom, 'close'] * 100
if rebound_percent > rebound_threshold:
rebound_end = i
crashes.append({
'crash_start': df.index[crash_start],
'crash_end': df.index[crash_end],
'bottom': df.index[bottom],
'rebound_end': df.index[rebound_end],
'drop_percent': (df.loc[bottom, 'close'] - df.loc[crash_start, 'close']) / df.loc[
crash_start, 'close'] * 100,
'rebound_percent': rebound_percent
})
in_crash = False # Reset pour détecter une nouvelle chute
return crashes
import yfinance as yf
df = yf.download("BTC-USD", start="2020-01-01", end="2025-01-01", interval="1d")
df.to_csv("btc_prices.csv")
print("Données enregistrées !")
# Exemple d'utilisation avec un DataFrame BTC (OHLCV)
df = pd.read_csv("btc_prices.csv", parse_dates=["date"], index_col="date")
crashes = detect_btc_crashes_and_rebounds(df)
for crash in crashes:
print(crash)