From 5b1e8bede432dc70724247f1329077cd9e95c96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Delacotte?= Date: Sat, 28 Mar 2026 20:47:50 +0100 Subject: [PATCH] TEST SHORT --- EmptyShort.py | 256 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 169 insertions(+), 87 deletions(-) diff --git a/EmptyShort.py b/EmptyShort.py index 9db44c5..ec40dde 100644 --- a/EmptyShort.py +++ b/EmptyShort.py @@ -151,7 +151,8 @@ class EmptyShort(IStrategy): 'current_trade': None, 'last_trade': None, 'force_stop': False, - 'count_of_lost': 0 + 'count_of_lost': 0, + 'take_profit': 0.01 } for pair in ["BTC/USDC", "BTC/USDT", 'BTC/USDT:USDT'] } @@ -261,7 +262,7 @@ class EmptyShort(IStrategy): # if last_candle['enter_tag'] in ['fall', 'bear', 'Force', 'Range-']: # amount = self.wallets.get_available_stake_amount() / self.mises_bear.value # else: - amount = self.wallets.get_available_stake_amount() / self.mises_bull.value # / (2 * self.pairs[pair]['count_of_lost'] + 1) + amount = self.wallets.get_available_stake_amount() #/ self.mises_bull.value # / (2 * self.pairs[pair]['count_of_lost'] + 1) # factor = 1 # @@ -439,6 +440,21 @@ class EmptyShort(IStrategy): self.pairs[pair]['total_amount'] = stake_amount # print(f"Buy {pair} {current_time} {entry_tag} dispo={dispo} amount={stake_amount} rate={rate} rate={rate}") + + # sl_price = rate * (1 - last_candle['up_pct_1h'] / 2) + # + # self.custom_trade_info[pair] = { + # "custom_exit": last_candle['up_pct_1h'] / 200 + # } + + # trade = kwargs.get("trade", None) + # if trade: + # trade.set_custom_data({ + # # "stoploss": rate * 0.95, + # "takeprofit": last_candle['up_pct_1h'] / 200 + # }) + self.pairs[pair]['take_profit'] = last_candle['up_pct_1h'] / 200 + self.log_trade( last_candle=last_candle, date=current_time, @@ -477,7 +493,7 @@ class EmptyShort(IStrategy): profit = trade.calc_profit(rate) force = self.pairs[pair]['force_sell'] allow_to_sell = (last_candle['hapercent'] < 0 and profit > 0) or force \ - or (trade.enter_tag == 'short' and profit > 0 and last_candle['hapercent'] > 0) or (exit_reason == 'force_exit') or (exit_reason == 'stop_loss') or (exit_reason == 'trailing_stop_loss') + or (trade.enter_tag == 'short' ) or (exit_reason == 'force_exit') or (exit_reason == 'stop_loss') or (exit_reason == 'trailing_stop_loss') minutes = int(round((current_time - trade.date_last_filled_utc).total_seconds() / 60, 0)) @@ -547,12 +563,13 @@ class EmptyShort(IStrategy): is_short = (trade.enter_tag == 'short') if trade.enter_tag == 'short': - if current_profit < self.sell_force_sell.value \ - and last_candle[f"close"] > last_candle[self.sell_indicator.value]: - self.pairs[pair]['force_sell'] = True - return 'sma' - - if current_profit > 0.01 and \ + tp_price = self.pairs[pair]['take_profit'] + # if current_profit < self.sell_force_sell.value \ + # and last_candle[f"close"] > last_candle[self.sell_indicator.value]: + # self.pairs[pair]['force_sell'] = True + # return 'sma' + # + if current_profit > tp_price and \ (baisse > self.baisse.value and last_candle[f"close"] > last_candle[self.b30_indicateur.value]) \ and last_candle['hapercent'] > 0: self.pairs[pair]['force_sell'] = True @@ -572,30 +589,23 @@ class EmptyShort(IStrategy): # stake=0 # ) else: - if self.pairs[pair]['current_trade'].enter_tag in ['bear', 'Force', 'Range-']: - if current_profit < - 0.02 and last_candle[f"close"] <= last_candle['sma60'] and self.wallets.get_available_stake_amount() < 50: - self.pairs[pair]['force_sell'] = True - return 'smaBF' - else: - if current_profit < self.sell_force_sell.value \ - and last_candle[f"close"] <= last_candle[self.sell_indicator.value]: - self.pairs[pair]['force_sell'] = True - return 'sma' + # if self.pairs[pair]['current_trade'].enter_tag in ['bear', 'Force', 'Range-']: + # if current_profit < - 0.02 and last_candle[f"close"] <= last_candle['sma60'] and self.wallets.get_available_stake_amount() < 50: + # self.pairs[pair]['force_sell'] = True + # return 'smaBF' + # else: + # if current_profit < self.sell_force_sell.value \ + # and last_candle[f"close"] <= last_candle[self.sell_indicator.value]: + # self.pairs[pair]['force_sell'] = True + # return 'sma' - if is_short: - if current_profit > 0.005 and \ - (baisse > self.baisse.value and last_candle[f"close"] > last_candle[self.b30_indicateur.value]) \ - and last_candle['hapercent'] > 0: - self.pairs[pair]['force_sell'] = True - return 'B30Sht' - else: - if current_profit > 0.00 and \ - (baisse > self.baisse.value and last_candle[f"close"] <= last_candle[self.b30_indicateur.value]) \ - and last_candle['hapercent'] <0 : - if current_profit > 0.01: - self.pairs[pair]['force_buy'] = True - self.pairs[pair]['force_sell'] = True - return 'B30' + if current_profit > 0.00 and \ + (baisse > self.baisse.value and last_candle[f"close"] <= last_candle[self.b30_indicateur.value]) \ + and last_candle['hapercent'] <0 : + if current_profit > 0.01: + self.pairs[pair]['force_buy'] = True + self.pairs[pair]['force_sell'] = True + return 'B30' # if profit > 0 and baisse > 0.5 and last_candle['hapercent'] <0 and last_candle[f"close"] <= last_candle['sma12']: # self.pairs[pair]['force_sell'] = True @@ -699,12 +709,15 @@ class EmptyShort(IStrategy): dataframe['zero'] = 0 dataframe[f"percent"] = dataframe['close'].pct_change() - for timeperiod in timeperiods: + for timeperiod in timeperiods + long_timeperiods: dataframe[f"mid_smooth{timeperiod}"] = dataframe['mid'].rolling(timeperiod).mean() dataframe[f'max{timeperiod}'] = talib.MAX(dataframe['close'], timeperiod=timeperiod) dataframe[f'min{timeperiod}'] = talib.MIN(dataframe['close'], timeperiod=timeperiod) dataframe[f"percent{timeperiod}"] = dataframe['close'].pct_change(timeperiod) - dataframe[f"sma{timeperiod}"] = dataframe['mid'].ewm(span=timeperiod, adjust=False).mean() + # dataframe[f"sma{timeperiod}"] = dataframe['mid'].ewm(span=timeperiod, adjust=False).mean() + ema = dataframe['mid'].ewm(span=timeperiod, adjust=False).mean() + dataframe[f"sma{timeperiod}"] = ema.ewm(span=int(timeperiod / 2), adjust=False).mean() + # dataframe[f"high{timeperiod}"] = dataframe['high'].ewm(span=timeperiod, adjust=False).mean() # dataframe[f"low{timeperiod}"] = dataframe['low'].ewm(span=timeperiod, adjust=False).mean() # dataframe = self.calculateRegression(dataframe, column=f"high{timeperiod}", window=10, degree=1, future_offset=12) @@ -712,9 +725,9 @@ class EmptyShort(IStrategy): self.calculeDerivees(dataframe, f"sma{timeperiod}", timeframe=self.timeframe, ema_period=timeperiod) - dataframe = self.calculateRegression(dataframe, column='mid', window=30, degree=1, future_offset=12) - dataframe = self.calculateRegression(dataframe, column='sma24', window=30, degree=1, future_offset=12) - self.calculeDerivees(dataframe, "sma24_regression", timeframe=self.timeframe, ema_period=12) + dataframe = self.calculateRegression(dataframe, column='mid', window=30, degree=1, future_offset=6) + dataframe = self.calculateRegression(dataframe, column='sma120', window=60, degree=2, future_offset=30) + # self.calculeDerivees(dataframe, "sma24_regression", timeframe=self.timeframe, ema_period=12) dataframe["percent"] = dataframe["mid"].pct_change(1) dataframe["percent3"] = dataframe["mid"].pct_change(3) @@ -738,7 +751,7 @@ class EmptyShort(IStrategy): informative['haclose'] = heikinashi['close'] informative['hapercent'] = (informative['haclose'] - informative['haopen']) / informative['haclose'] informative['mid'] = informative['open'] + (informative['close'] - informative['open']) / 2 - for timeperiod in timeperiods: + for timeperiod in [3, 5, 12]: informative[f'max{timeperiod}'] = talib.MAX(informative['close'], timeperiod=timeperiod) informative[f'min{timeperiod}'] = talib.MIN(informative['close'], timeperiod=timeperiod) # informative[f"range{timeperiod}"] = ((informative["close"] - informative[f'min{timeperiod}']) / (informative[f'max{timeperiod}'] - informative[f'min{timeperiod}'])) @@ -746,9 +759,9 @@ class EmptyShort(IStrategy): informative[f"sma{timeperiod}"] = informative['mid'].ewm(span=timeperiod, adjust=False).mean() self.calculeDerivees(informative, f"sma{timeperiod}", timeframe=self.timeframe, ema_period=timeperiod) - informative = self.calculateRegression(informative, column='mid', window=10, degree=1, future_offset=12) - informative = self.calculateRegression(informative, column='sma3', window=10, degree=1, future_offset=12) - informative = self.calculateRegression(informative, column='low', window=10, degree=1, future_offset=12) + informative = self.calculateRegression(informative, column='mid', window=10, degree=1, future_offset=2) + informative = self.calculateRegression(informative, column='sma3', window=10, degree=1, future_offset=2) + informative = self.calculateRegression(informative, column='low', window=10, degree=1, future_offset=2) for timeperiod in long_timeperiods: informative[f"sma{timeperiod}"] = informative['mid'].ewm(span=timeperiod, adjust=False).mean() @@ -758,20 +771,22 @@ class EmptyShort(IStrategy): self.calculeDerivees(informative, f"rsi", timeframe=self.timeframe, ema_period=14) informative['max_rsi_12'] = talib.MAX(informative['rsi'], timeperiod=12) informative['max_rsi_24'] = talib.MAX(informative['rsi'], timeperiod=24) + informative['min_rsi_12'] = talib.MIN(informative['rsi'], timeperiod=12) + informative['min_rsi_24'] = talib.MIN(informative['rsi'], timeperiod=24) - informative[f'stop_buying_deb'] = qtpylib.crossed_below(informative[f"sma12"], informative['sma36']) & (informative['close'] < informative['sma100']) - informative[f'stop_buying_end'] = qtpylib.crossed_above(informative[f"sma12"], informative['sma36']) & (informative['close'] > informative['sma100']) + # informative[f'stop_buying_deb'] = qtpylib.crossed_below(informative[f"sma12"], informative['sma36']) & (informative['close'] < informative['sma100']) + # informative[f'stop_buying_end'] = qtpylib.crossed_above(informative[f"sma12"], informative['sma36']) & (informative['close'] > informative['sma100']) - latched = np.zeros(len(informative), dtype=bool) - - for i in range(1, len(informative)): - if informative['stop_buying_deb'].iloc[i]: - latched[i] = True - elif informative['stop_buying_end'].iloc[i]: - latched[i] = False - else: - latched[i] = latched[i - 1] - informative['stop_buying'] = latched + # latched = np.zeros(len(informative), dtype=bool) + # + # for i in range(1, len(informative)): + # if informative['stop_buying_deb'].iloc[i]: + # latched[i] = True + # elif informative['stop_buying_end'].iloc[i]: + # latched[i] = False + # else: + # latched[i] = latched[i - 1] + # informative['stop_buying'] = latched informative = self.calculateDownAndUp(informative, limit=0.0001) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True) @@ -787,7 +802,7 @@ class EmptyShort(IStrategy): # informative['haclose'] = heikinashi['close'] # informative['hapercent'] = (informative['haclose'] - informative['haopen']) / informative['haclose'] informative['mid'] = informative['open'] + (informative['close'] - informative['open']) / 2 - for timeperiod in timeperiods: + for timeperiod in [3, 5, 12]: informative[f'max{timeperiod}'] = talib.MAX(informative['close'], timeperiod=timeperiod) informative[f'min{timeperiod}'] = talib.MIN(informative['close'], timeperiod=timeperiod) # informative[f"range{timeperiod}"] = ((informative["close"] - informative[f'min{timeperiod}']) / (informative[f'max{timeperiod}'] - informative[f'min{timeperiod}'])) @@ -804,19 +819,23 @@ class EmptyShort(IStrategy): informative['max_rsi_12'] = talib.MAX(informative['rsi'], timeperiod=12) informative['max_rsi_24'] = talib.MAX(informative['rsi'], timeperiod=24) - informative[f'stop_buying_deb'] = qtpylib.crossed_below(informative[f"sma12"], informative['sma36']) & (informative['close'] < informative['sma100']) - informative[f'stop_buying_end'] = qtpylib.crossed_above(informative[f"sma12"], informative['sma36']) & (informative['close'] > informative['sma100']) + # informative = self.calculateRegression(informative, column='mid', window=10, degree=1, future_offset=2) + informative = self.calculateRegression(informative, column='sma3', window=10, degree=1, future_offset=2) + # informative = self.calculateRegression(informative, column='low', window=10, degree=1, future_offset=2) - latched = np.zeros(len(informative), dtype=bool) - - for i in range(1, len(informative)): - if informative['stop_buying_deb'].iloc[i]: - latched[i] = True - elif informative['stop_buying_end'].iloc[i]: - latched[i] = False - else: - latched[i] = latched[i - 1] - informative['stop_buying'] = latched + # informative[f'stop_buying_deb'] = qtpylib.crossed_below(informative[f"sma12"], informative['sma36']) & (informative['close'] < informative['sma100']) + # informative[f'stop_buying_end'] = qtpylib.crossed_above(informative[f"sma12"], informative['sma36']) & (informative['close'] > informative['sma100']) + # + # latched = np.zeros(len(informative), dtype=bool) + # + # for i in range(1, len(informative)): + # if informative['stop_buying_deb'].iloc[i]: + # latched[i] = True + # elif informative['stop_buying_end'].iloc[i]: + # latched[i] = False + # else: + # latched[i] = latched[i - 1] + # informative['stop_buying'] = latched dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True) # ###################################################################################################### @@ -979,14 +998,14 @@ class EmptyShort(IStrategy): # ['enter_long', 'enter_tag'] # ] = (1, 'cross_min') - conditions = list() - conditions.append(dataframe['sma12_deriv1'] > 0.00) - conditions.append(dataframe['sma60_deriv1'] > 0.0) - conditions.append(dataframe['sma5_deriv1_1h'] > 0.0) - conditions.append(dataframe['sma12_deriv1_1h'] > 0.0) - conditions.append(dataframe['sma24_deriv1_1h'] > 0.0) - conditions.append(dataframe['sma100_deriv1_1h'] > 0.0) - conditions.append(dataframe[f"range_pos"] < 0.025) + # conditions = list() + # conditions.append(dataframe['sma12_deriv1'] > 0.00) + # conditions.append(dataframe['sma60_deriv1'] > 0.0) + # conditions.append(dataframe['sma5_deriv1_1h'] > 0.0) + # conditions.append(dataframe['sma12_deriv1_1h'] > 0.0) + # conditions.append(dataframe['sma24_deriv1_1h'] > 0.0) + # conditions.append(dataframe['sma100_deriv1_1h'] > 0.0) + # conditions.append(dataframe[f"range_pos"] < 0.025) # conditions.append(dataframe['sma12_deriv1_1h'] > 0.0) # # conditions.append(dataframe['close_1h'] < dataframe[f'sma{self.buy_longue.value}_1h']) # # conditions.append(dataframe['has_cross_min'].rolling(6).max() == 1) @@ -1022,10 +1041,9 @@ class EmptyShort(IStrategy): # dataframe.loc[ # ( - # (qtpylib.crossed_above( - # dataframe['sma60'], - # dataframe['mid_regression_1h']) - # ) + # # (qtpylib.crossed_above(dataframe['sma60'], dataframe['mid_regression_1h'])) + # (dataframe['rsi_1h'] <= 30) + # & (dataframe['min_rsi_12_1h'] == dataframe['rsi_1h']) # ), # ['enter_long', 'enter_tag'] # ] = (1, 'long') @@ -1037,13 +1055,34 @@ class EmptyShort(IStrategy): # dataframe['mid_regression_1h']) # ) & ( - (dataframe['close'] > dataframe['max5_1h']) - & (dataframe['sma12'] < dataframe['sma12'].shift(1)) + # (dataframe['close'] > dataframe['max5_1h']) + # & (dataframe['sma12'] < dataframe['sma12'].shift(1)) + # # & (dataframe['sma120_inv'] == 1) + # & (dataframe['close'] > dataframe['close_1h']) + # & (dataframe['close'] > dataframe['close_1d']) + # (dataframe['rsi_1h'] >= 65) + # & (dataframe['max_rsi_12_1h'] == dataframe['rsi_1h']) + # & (dataframe['hapercent'] < 0) + # & (dataframe['sma60'] < dataframe['sma60'].shift(1)) + (dataframe['sma12_1h'] < dataframe['sma12_1h'].shift(61)) + & (dataframe['close'] > dataframe['close_1d']) ) ), ['enter_short', 'enter_tag'] ] = (1, 'short') + # dataframe.loc[ + # ( + # (dataframe['close'] >= dataframe['max5_1h']) + # & (dataframe['close'] >= dataframe['max12_1d']) + # & (dataframe['sma12_1h'] <= dataframe['max12_1d']) + # & (dataframe['mid_1h'] <= dataframe['mid_1h'].shift(61)) + # & (dataframe['hapercent'] < 0) + # # & (dataframe['sma60'] < dataframe['sma60'].shift(1)) + # ), + # ['enter_short', 'enter_tag'] + # ] = (1, 'short') + return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: @@ -1102,15 +1141,31 @@ class EmptyShort(IStrategy): # if conditions: # dataframe.loc[reduce(lambda x, y: x & y, conditions), ['exit_long', 'exit_tag']] = (1, 'god') + # dataframe.loc[ + # ( + # # (qtpylib.crossed_above( + # # dataframe['sma'], + # # dataframe['mid_regression_1h']) + # # ) + # (dataframe['rsi_1h'] >= 70) + # & (dataframe['max_rsi_12_1h'] == dataframe['rsi_1h']) + # ), + # ['exit_long', 'exit_tag'] + # ] = (1, 'long') + dataframe.loc[ ( - (qtpylib.crossed_above( - dataframe['sma60'], - dataframe['mid_regression_1h']) - ) + # (qtpylib.crossed_above( + # dataframe['sma'], + # dataframe['mid_regression_1h']) + # ) + (dataframe['rsi_1h'] <= 30) + & (dataframe['min_rsi_12_1h'] == dataframe['rsi_1h']) + & (dataframe['hapercent'] > 0) + & (dataframe['sma60'] >= dataframe['sma60'].shift(1)) ), ['exit_short', 'exit_tag'] - ] = (1, 'long') + ] = (1, 'short') return dataframe @@ -1143,7 +1198,34 @@ class EmptyShort(IStrategy): dataframe[d1_col] = (dataframe[name] - dataframe[name].shift(3)) / dataframe[name].shift(3) dataframe[d2_col] = (dataframe[d1_col] - dataframe[d1_col].shift(1)) - dataframe[f"{name}{suffixe}_inv"] = np.where(cond_bas, -1, np.where(cond_haut, 1, 0)) + # dataframe[f"{name}{suffixe}_inv"] = np.where(cond_bas, -1, np.where(cond_haut, 1, 0)) + + # col = f"{name}{suffixe}" + # slope = dataframe[col].diff() + # threshold = 0.02 #slope.rolling(20).std() * 0.1 + # sign = np.sign(slope.where(slope.abs() > threshold, 0)) + # turn = sign.diff() + # dataframe[f"{name}{suffixe}_inv"] = np.where(turn == -2, 1, np.where(turn == 2, -1, 0)) + # # dataframe[f"{name}{suffixe}_inv"] = ( + # # (dataframe[f"{name}{suffixe}_inv"] != 0) & + # # (dataframe['slope'].abs() > dataframe['slope'].rolling(20).mean()) + # # ) + + col = f"{name}{suffixe}" + # pente (variation) + dataframe['slope'] = dataframe[col].diff() + # signe de la pente + dataframe['sign'] = dataframe['slope'].apply(lambda x: 1 if x > 0 else (-1 if x < 0 else 0)) + # changement de signe = inversion + dataframe[f"{name}{suffixe}_turn"] = dataframe['sign'].diff() + # mapping : + # +2 -> passage -1 → +1 => creux => inversion haussière + # -2 -> passage +1 → -1 => sommet => inversion baissière + col_inv = f"{name}{suffixe}_inv" + dataframe[col_inv] = 0 + dataframe.loc[dataframe[f"{name}{suffixe}_turn"] == -2, col_inv] = 1 # sommet (max) + dataframe.loc[dataframe[f"{name}{suffixe}_turn"] == 2, col_inv] = -1 # creux (min) + short = d1.rolling(pmin).mean() long = d1.rolling(ema_period).mean() @@ -1446,7 +1528,7 @@ class EmptyShort(IStrategy): # 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 + 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)