Synchronise

This commit is contained in:
Jérôme Delacotte
2025-03-09 16:53:02 +01:00
parent 9449d25384
commit 8a1c69e53a
4 changed files with 486 additions and 211 deletions

View File

@@ -395,6 +395,8 @@ class DecisionTreeStrategy(IStrategy):
current_entry_profit: float, current_exit_profit: float, current_entry_profit: float, current_exit_profit: float,
**kwargs **kwargs
) -> float | None | tuple[float | None, str | None]: ) -> float | None | tuple[float | None, str | None]:
if trade.has_open_orders:
return None
# Obtain pair dataframe (just to show how to access it) # Obtain pair dataframe (just to show how to access it)
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)

View File

@@ -18,6 +18,15 @@ class HammerReversalStrategy(IStrategy):
"main_plot": { "main_plot": {
"enter_tag": { "enter_tag": {
"color": "#197260" "color": "#197260"
},
'sma5_1d': {
'color': 'green'
},
'bb_upperband_1d': {
'color': 'blue'
},
'bb_lowerband_1d': {
'color': 'red'
} }
}, },
"subplots": { "subplots": {
@@ -25,10 +34,40 @@ class HammerReversalStrategy(IStrategy):
"hammer": { "hammer": {
"color": "blue" "color": "blue"
}, },
"inv_hammer": { "loose_hammer": {
"color": "#c1b255"
},
"hammer_1h": {
"color": "blue"
},
"loose_hammer_1h": {
"color": "#c1b255"
},
"hammer_1d": {
"color": "blue"
},
"loose_hammer_1d": {
"color": "#c1b255" "color": "#c1b255"
} }
},
'Percent': {
'percent3_1d': {
"color": 'pink'
},
'percent3': {
"color": 'red'
},
'percent5': {
"color": 'green'
},
'percent12': {
"color": 'blue'
},
'percent48': {
"color": 'yellow'
}
} }
} }
} }
minimal_roi = { minimal_roi = {
@@ -51,58 +90,67 @@ class HammerReversalStrategy(IStrategy):
position_adjustment_enable = True position_adjustment_enable = True
columns_logged = False columns_logged = False
max_entry_position_adjustment = 20 max_entry_position_adjustment = 20
startup_candle_count = 288
def new_adjust_trade_position(self, trade, current_time, current_rate, current_profit, min_stake, max_stake, # def new_adjust_trade_position(self, trade, current_time, current_rate, current_profit, min_stake, max_stake,
**kwargs) -> float: # **kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe) # dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() # last_candle = dataframe.iloc[-1].squeeze()
#
count_of_buys, hours, days, first_price, last_price = self.getTradeInfos(current_time, trade) # count_of_buys, hours, days, first_price, last_price = self.getTradeInfos(current_time, trade)
#
# Initialisation des user_data (backtest compatible) # # Initialisation des user_data (backtest compatible)
if 'dynamic_stoploss' not in trade.user_data: # if 'dynamic_stoploss' not in trade.user_data:
trade.user_data['dynamic_stoploss'] = first_price * 0.98 # Stoploss initial à -2% # trade.user_data['dynamic_stoploss'] = first_price * 0.98 # Stoploss initial à -2%
#
if hours < 1 or trade.stake_amount >= max_stake: # if hours < 1 or trade.stake_amount >= max_stake:
return 0 # return 0
#
# Ajustement en cas de perte : renfort à la baisse # # Ajustement en cas de perte : renfort à la baisse
if (last_candle['close'] < first_price) and (last_candle['touch_support']) and (current_profit < -0.015 * count_of_buys): # if (last_candle['close'] < first_price) and (last_candle['touch_support']) and (current_profit < -0.015 * count_of_buys):
additional_stake = self.config['stake_amount'] # additional_stake = self.config['stake_amount']
print(f"Adjust Loss - {current_time} rate={current_rate:.3f} stake={additional_stake} count={count_of_buys}") # print(f"Adjust Loss - {current_time} rate={current_rate:.3f} stake={additional_stake} count={count_of_buys}")
return max(additional_stake, 0) # return max(additional_stake, 0)
#
# Ajustement en cas de gain : renfort à la hausse # # Ajustement en cas de gain : renfort à la hausse
if (last_candle['close'] > first_price) and (current_profit > 0.01 * count_of_buys): # if (last_candle['close'] > first_price) and (current_profit > 0.01 * count_of_buys):
additional_stake = self.config['stake_amount'] # additional_stake = self.config['stake_amount']
#
# Mise à jour du stoploss dynamique (on lock un profit partiel par exemple) # # Mise à jour du stoploss dynamique (on lock un profit partiel par exemple)
new_stoploss = current_rate * 0.99 # Stoploss dynamique à -1% sous le prix actuel # new_stoploss = current_rate * 0.99 # Stoploss dynamique à -1% sous le prix actuel
trade.user_data['dynamic_stoploss'] = max(trade.user_data['dynamic_stoploss'], new_stoploss) # trade.user_data['dynamic_stoploss'] = max(trade.user_data['dynamic_stoploss'], new_stoploss)
#
print(f"Adjust Gain + {current_time} rate={current_rate:.3f} stake={additional_stake} count={count_of_buys}") # print(f"Adjust Gain + {current_time} rate={current_rate:.3f} stake={additional_stake} count={count_of_buys}")
return max(additional_stake, 0) # return max(additional_stake, 0)
#
return 0 # return 0
def adjust_trade_position(self, trade, current_time, current_rate, current_profit, min_stake, max_stake, def adjust_trade_position(self, trade, current_time, current_rate, current_profit, min_stake, max_stake,
**kwargs) -> float: **kwargs) -> float:
if trade.has_open_orders:
return None
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
last_candle_288 = dataframe.iloc[-288].squeeze()
""" """
Ajuste la position suite à un signal de sortie partielle. Ajuste la position suite à un signal de sortie partielle.
""" """
count_of_buys, hours, days, first_price, last_price = self.getTradeInfos(current_time, trade) count_of_buys, hours, days, first_price, last_price = self.getTradeInfos(current_time, trade)
if hours < 1 or trade.stake_amount >= max_stake: # (hours < 1) or
if (self.wallets.get_available_stake_amount() < 50): # or trade.stake_amount >= max_stake:
return 0 return 0
dispo = round(self.wallets.get_available_stake_amount()) dispo = round(self.wallets.get_available_stake_amount())
factor = 1
if (count_of_buys > 4):
factor = count_of_buys / 4
if (count_of_buys > 1) \ if (count_of_buys > 1) \
and (current_profit > 0.01) \ and (current_profit > 0.01) \
and (last_candle['close'] < self.pairs[trade.pair]['max_touch'] * 0.99) \ and (last_candle['haclose'] < self.pairs[trade.pair]['max_touch'] * 0.99) \
and (last_candle['percent5'] < 0): and (last_candle['percent5'] < 0) and (last_candle['percent12'] < 0):
# print(f"Adjust Sell all {current_time} rate={current_rate:.3f} stake={trade.stake_amount} count={count_of_buys} profit={profit:.1f}") # print(f"Adjust Sell all {current_time} rate={current_rate:.3f} stake={trade.stake_amount} count={count_of_buys} profit={profit:.1f}")
self.log_trade( self.log_trade(
@@ -113,14 +161,22 @@ class HammerReversalStrategy(IStrategy):
pair=trade.pair, pair=trade.pair,
rate=current_rate, rate=current_rate,
trade_type='Sell', trade_type='Sell',
profit=round(trade.calc_profit(current_rate, trade.amount), 2), # round(current_profit * trade.stake_amount, 2), profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2),
buys=trade.nr_of_successful_entries, buys=trade.nr_of_successful_entries,
stake=round(- trade.stake_amount, 2) stake=round(- trade.stake_amount, 2)
) )
self.pairs[trade.pair]['last_max'] = max(last_candle['haclose'], self.pairs[trade.pair]['last_max'])
self.pairs[trade.pair]['max_touch'] = last_candle['haclose']
self.pairs[trade.pair]['last_buy'] = last_candle['haclose']
self.pairs[trade.pair]['last_sell'] = 0
return - trade.stake_amount return - trade.stake_amount
if (last_candle['close'] < first_price) and (last_candle['touch_support']) and (current_profit < -0.015 * count_of_buys): if (last_candle['close'] < first_price) \
additional_stake = self.calculate_stake(trade.pair, last_candle) and (last_candle['touch_support']) \
and ((count_of_buys <= 4 and last_candle_288['sma5_1h'] <= last_candle['sma5_1h'])
or (count_of_buys > 4 and last_candle_288['sma5_1d'] <= last_candle['sma5_1d'])) \
and (current_profit < -0.015 * count_of_buys * factor):
additional_stake = self.calculate_stake(trade.pair, last_candle, factor)
# print(f"Adjust Loss - {current_time} rate={current_rate:.3f} stake={additional_stake} count={count_of_buys} profit={profit:.1f}") # print(f"Adjust Loss - {current_time} rate={current_rate:.3f} stake={additional_stake} count={count_of_buys} profit={profit:.1f}")
self.log_trade( self.log_trade(
@@ -135,11 +191,14 @@ class HammerReversalStrategy(IStrategy):
buys=trade.nr_of_successful_entries, buys=trade.nr_of_successful_entries,
stake=round(additional_stake, 2) stake=round(additional_stake, 2)
) )
self.pairs[trade.pair]['last_max'] = last_candle['haclose']
self.pairs[trade.pair]['max_touch'] = last_candle['haclose']
self.pairs[trade.pair]['last_buy'] = 0
self.pairs[trade.pair]['last_sell'] = last_candle['haclose']
return max(additional_stake, 0) return max(additional_stake, 0)
if (last_candle['close'] > first_price) and (current_profit > 0.01 * count_of_buys): if (last_candle['close'] > first_price) and (current_profit > 0.01 * count_of_buys):
additional_stake = self.calculate_stake(trade.pair, last_candle) additional_stake = self.calculate_stake(trade.pair, last_candle, 1)
self.log_trade( self.log_trade(
last_candle=last_candle, last_candle=last_candle,
date=current_time, date=current_time,
@@ -152,7 +211,10 @@ class HammerReversalStrategy(IStrategy):
buys=count_of_buys, buys=count_of_buys,
stake=round(additional_stake, 2) stake=round(additional_stake, 2)
) )
self.pairs[trade.pair]['last_max'] = last_candle['haclose']
self.pairs[trade.pair]['max_touch'] = last_candle['haclose']
self.pairs[trade.pair]['last_buy'] = last_candle['haclose']
self.pairs[trade.pair]['last_sell'] = 0
# print(f"Adjust Gain + {current_time} rate={current_rate:.3f} stake={additional_stake} count={count_of_buys} profit={profit:.1f}") # print(f"Adjust Gain + {current_time} rate={current_rate:.3f} stake={additional_stake} count={count_of_buys} profit={profit:.1f}")
return max(additional_stake, 0) return max(additional_stake, 0)
@@ -160,17 +222,17 @@ class HammerReversalStrategy(IStrategy):
use_custom_stoploss = True use_custom_stoploss = True
def new_custom_stoploss(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float, # def new_custom_stoploss(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
current_profit: float, **kwargs) -> float: # current_profit: float, **kwargs) -> float:
#
if 'dynamic_stoploss' in trade.user_data: # if 'dynamic_stoploss' in trade.user_data:
stoploss_price = trade.user_data['dynamic_stoploss'] # stoploss_price = trade.user_data['dynamic_stoploss']
if current_rate < stoploss_price: # if current_rate < stoploss_price:
print(f"Stoploss touché ! Vente forcée {pair} à {current_rate}") # print(f"Stoploss touché ! Vente forcée {pair} à {current_rate}")
return 0.001 # on force une sortie immédiate (stop très proche) # return 0.001 # on force une sortie immédiate (stop très proche)
#
# Sinon on reste sur le stoploss standard de la stratégie # # Sinon on reste sur le stoploss standard de la stratégie
return -1 # Exemple: 5% de perte max # return -1 # Exemple: 5% de perte max
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float, proposed_stake: float, min_stake: float, max_stake: float,
@@ -179,24 +241,26 @@ class HammerReversalStrategy(IStrategy):
# Obtenir les données actuelles pour cette paire # Obtenir les données actuelles pour cette paire
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
return self.calculate_stake(pair, last_candle) return self.calculate_stake(pair, last_candle, 1)
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, # def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float: # current_rate: float, current_profit: float, **kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) # dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
#
# Obtenir les données actuelles pour cette paire # # Obtenir les données actuelles pour cette paire
last_candle = dataframe.iloc[-1].squeeze() # last_candle = dataframe.iloc[-1].squeeze()
# self.getTradeInfos(current_time, trade) # # self.getTradeInfos(current_time, trade)
# print(f"current_profit={current_profit} mises=" + str(round(self.pairs[pair]['trade_info']['mises'], 4))) # # print(f"current_profit={current_profit} mises=" + str(round(self.pairs[pair]['trade_info']['mises'], 4)))
limit_sell = (last_candle['close'] - self.pairs[trade.pair]['max_touch']) / self.pairs[trade.pair]['max_touch'] # limit_sell = (last_candle['close'] - self.pairs[trade.pair]['max_touch']) / self.pairs[trade.pair]['max_touch']
#
if (current_profit > 0.01) & (limit_sell < -0.01) & (last_candle['percent12'] < 0): # & (limit_sell < -0.01) & (last_candle['DI+_1h'] < 10): # if (current_profit > 0.01) & (limit_sell < -0.01) & (last_candle['percent12'] < 0): # & (limit_sell < -0.01) & (last_candle['DI+_1h'] < 10):
sl_profit = 0.85 * current_profit # n% du profit en cours # sl_profit = 0.85 * current_profit # n% du profit en cours
else: # print(f"Stoploss {current_time} {current_rate} set to {sl_profit} / {limit_sell} / {self.pairs[trade.pair]['max_touch']}")
sl_profit = -1 # Hard stop-loss #
stoploss = stoploss_from_open(sl_profit, current_profit) # else:
return stoploss # sl_profit = -1 # Hard stop-loss
# stoploss = stoploss_from_open(sl_profit, current_profit)
# return stoploss
def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float, def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
current_profit: float, **kwargs) -> 'Optional[Union[str, bool]]': current_profit: float, **kwargs) -> 'Optional[Union[str, bool]]':
@@ -204,16 +268,20 @@ class HammerReversalStrategy(IStrategy):
Custom exit function for dynamic trade exits. Custom exit function for dynamic trade exits.
""" """
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
self.pairs[pair]['max_touch'] = max(current_rate, self.pairs[pair]['max_touch']) last_candle = dataframe.iloc[-1].squeeze()
# Calcul de la "distance de sécurité" avant stockage dans max_touch
limit_sell = (last_candle['haclose'] - self.pairs[pair]['max_touch']) / self.pairs[pair]['max_touch']
# # Obtenir les données actuelles pour cette paire self.pairs[pair]['max_touch'] = max(last_candle['haclose'], self.pairs[pair]['max_touch'])
# last_candle = dataframe.iloc[-1].squeeze()
# previous_last_candle = dataframe.iloc[-2].squeeze()
# if (last_candle['percent'] > 0) | (last_candle['percent3'] > 0.0) | (last_candle['percent5'] > 0.0): # On ne déclenche le trailing stop que si un profit mini a déjà été atteint
# return None # and (limit_sell < -0.01)
# if (current_profit > 0.01) and (last_candle['percent12'] < 0) and (last_candle['percent5'] < 0):
# if current_profit > 0 and last_candle['inv_hammer'] > 0: print(f"Custom Exit Triggered - {current_time} - Price: {current_rate:.2f} - Profit: {current_profit:.2%}")
# return 'Sell_Hammer' print(f"Max touch: {self.pairs[pair]['max_touch']:.2f}, Limit sell: {limit_sell:.2%}")
return 'trailing_stop_exit'
return None return None
@@ -222,12 +290,15 @@ class HammerReversalStrategy(IStrategy):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
dispo = round(self.wallets.get_available_stake_amount()) dispo = round(self.wallets.get_available_stake_amount())
stake_amount = self.calculate_stake(pair, last_candle) stake_amount = self.calculate_stake(pair, last_candle, 1)
self.pairs[pair]['last_max'] = max(rate, self.pairs[pair]['last_max'])
self.pairs[pair]['max_touch'] = rate
self.pairs[pair]['last_buy'] = rate
# if (self.pairs[pair]['last_sell'] > 0) and \
# (self.pairs[pair]['last_sell'] - last_candle['close']) / self.pairs[pair]['last_sell'] < 0.012:
# return False
self.pairs[pair]['last_max'] = max(last_candle['haclose'], self.pairs[pair]['last_max'])
self.pairs[pair]['max_touch'] = last_candle['haclose']
self.pairs[pair]['last_buy'] = last_candle['haclose']
self.pairs[pair]['last_sell'] = 0
#print(f"Buy {current_time} {entry_tag} rate={rate:.3f} amount={amount}") #print(f"Buy {current_time} {entry_tag} rate={rate:.3f} amount={amount}")
self.log_trade( self.log_trade(
last_candle=last_candle, last_candle=last_candle,
@@ -255,6 +326,7 @@ class HammerReversalStrategy(IStrategy):
# self.pairs[pair]['last_max'] = 0 # self.pairs[pair]['last_max'] = 0
# self.pairs[pair]['max_touch'] = 0 # self.pairs[pair]['max_touch'] = 0
self.pairs[pair]['last_buy'] = 0 self.pairs[pair]['last_buy'] = 0
self.pairs[pair]['last_sell'] = rate
self.log_trade( self.log_trade(
last_candle=last_candle, last_candle=last_candle,
date=current_time, date=current_time,
@@ -270,10 +342,16 @@ class HammerReversalStrategy(IStrategy):
return ok return ok
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
heikinashi = qtpylib.heikinashi(dataframe)
dataframe['haopen'] = heikinashi['open']
dataframe['haclose'] = heikinashi['close']
dataframe['hapercent'] = dataframe['haclose'].pct_change()
dataframe['hammer'] = ta.CDLHAMMER(dataframe['open'], dataframe['high'], dataframe['low'], dataframe['close']) dataframe['hammer'] = ta.CDLHAMMER(dataframe['open'], dataframe['high'], dataframe['low'], dataframe['close'])
dataframe['inv_hammer'] = ta.CDLINVERTEDHAMMER(dataframe['open'], dataframe['high'], dataframe['low'], dataframe['inv_hammer'] = ta.CDLINVERTEDHAMMER(dataframe['open'], dataframe['high'], dataframe['low'],
dataframe['close']) dataframe['close'])
# Volume # Volume
dataframe['volume_mean'] = ta.SMA(dataframe['volume'], timeperiod=20) dataframe['volume_mean'] = ta.SMA(dataframe['volume'], timeperiod=20)
dataframe['volume_above_avg'] = dataframe['volume'] > 1.2 * dataframe['volume_mean'] dataframe['volume_above_avg'] = dataframe['volume'] > 1.2 * dataframe['volume_mean']
@@ -320,22 +398,41 @@ class HammerReversalStrategy(IStrategy):
dataframe["percent3"] = dataframe['close'].pct_change(3) dataframe["percent3"] = dataframe['close'].pct_change(3)
dataframe["percent5"] = dataframe['close'].pct_change(5) dataframe["percent5"] = dataframe['close'].pct_change(5)
dataframe["percent12"] = dataframe['close'].pct_change(12) dataframe["percent12"] = dataframe['close'].pct_change(12)
dataframe["percent48"] = dataframe['close'].pct_change(48)
dataframe = self.pattern_hammer(dataframe) dataframe = self.pattern_hammer(dataframe)
dataframe = self.detect_hammer_with_context(dataframe) dataframe = self.detect_hammer_with_context(dataframe)
dataframe = self.detect_loose_hammer(dataframe) dataframe = self.detect_loose_hammer(dataframe)
#dataframe = self.detect_squeeze_pump(dataframe) #dataframe = self.detect_squeeze_pump(dataframe)
# ======================================================================================
################### INFORMATIVE 1h
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
# informative['hammer'] = ta.CDLHAMMER(informative['open'], informative['high'], informative['low'], informative['close'])
informative = self.detect_loose_hammer(informative)
informative = self.detect_hammer_with_context(informative)
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2)
informative['bb_lowerband'] = bollinger['lower']
informative['bb_middleband'] = bollinger['mid']
informative['bb_upperband'] = bollinger['upper']
informative['sma5'] = ta.SMA(informative, timeperiod=5)
informative["percent3"] = informative['close'].pct_change(3)
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
# ====================================================================================== # ======================================================================================
################### INFORMATIVE 1d ################### INFORMATIVE 1d
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d") informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d")
# informative['hammer'] = ta.CDLHAMMER(informative['open'], informative['high'], informative['low'], informative['close']) # informative['hammer'] = ta.CDLHAMMER(informative['open'], informative['high'], informative['low'], informative['close'])
informative = self.detect_loose_hammer(informative) informative = self.detect_loose_hammer(informative)
informative['max7'] = ta.MAX(informative['close'], timeperiod=7) informative = self.detect_hammer_with_context(informative)
informative['sma5'] = ta.SMA(informative, timeperiod=5)
informative["percent3"] = informative['sma5'].pct_change(3)
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2)
informative['bb_lowerband'] = bollinger['lower']
informative['bb_middleband'] = bollinger['mid']
informative['bb_upperband'] = bollinger['upper']
informative['bb_upperband'], informative['bb_middleband'], informative['bb_lowerband'] = ta.BBANDS(
informative['close'], timeperiod=20
)
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True)
dataframe['hammer_marker'] = np.where(dataframe['hammer_signal'], dataframe['low'] * 0.99, np.nan) dataframe['hammer_marker'] = np.where(dataframe['hammer_signal'], dataframe['low'] * 0.99, np.nan)
@@ -355,7 +452,7 @@ class HammerReversalStrategy(IStrategy):
, # Divergence possible , # Divergence possible
['enter_long', 'enter_tag']] = [1, 'buy_hammer'] ['enter_long', 'enter_tag']] = [1, 'buy_hammer']
# dataframe.loc[ # d ataframe.loc[
# (dataframe['hammer2'] > 0) # (dataframe['hammer2'] > 0)
# # & (dataframe['close'] < dataframe['bb_middleband']) # # & (dataframe['close'] < dataframe['bb_middleband'])
# # (dataframe['volume_above_avg']) & # # (dataframe['volume_above_avg']) &
@@ -367,7 +464,8 @@ class HammerReversalStrategy(IStrategy):
# , # Divergence possible # , # Divergence possible
# ['enter_long', 'enter_tag']] = [1, 'buy_hammer2'] # ['enter_long', 'enter_tag']] = [1, 'buy_hammer2']
dataframe.loc[ dataframe.loc[
(dataframe['loose_hammer'] > 0) (dataframe['percent3'] < - 0.005)
& (dataframe['percent48'] < 0.02)
, # Divergence possible , # Divergence possible
['enter_long', 'enter_tag']] = [1, 'buy_loose_hammer'] ['enter_long', 'enter_tag']] = [1, 'buy_loose_hammer']
@@ -585,17 +683,61 @@ class HammerReversalStrategy(IStrategy):
sma5 = str(sma5_1d) + ' ' + str(sma5_1h) sma5 = str(sma5_1d) + ' ' + str(sma5_1h)
first_rate = self.pairs[pair]['last_max'] first_rate = self.pairs[pair]['last_max']
if action != 'Sell': # if action != 'Sell':
profit = round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 2) # profit = round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 2)
limit_sell = rsi_pct # round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 4) limit_sell = rsi_pct # round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 4)
max7_1d = last_candle['max7_1d'] #round(100 * (last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 1) max7_1d = round(self.pairs[pair]['max_touch'], 1) #last_candle['max7_1d'] #round(100 * (last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 1)
pct_max = round(100 * (last_candle['close'] - max7_1d) / max7_1d, 1) pct_max = round(100 * (last_candle['close'] - max7_1d) / max7_1d, 1)
print( 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} | {max7_1d or '-':>11} | {self.pairs[pair]['max_touch'] or '-':>12} | {self.pairs[pair]['last_max'] or '-':>12} | {buys or '-':>5} | {stake or '-':>10} |" f"| {date:<16} | {action:<10} | {pair:<10} | {trade_type or '-':<18} | {rate or '-':>12} | {dispo or '-':>6} | {profit or '-':>8} | {pct_max or '-':>5} | {max7_1d or '-':>11} | {round(self.pairs[pair]['max_touch'], 2) or '-':>12} | {round(self.pairs[pair]['last_max'],2) or '-':>12} | {buys or '-':>5} | {stake or '-':>10} |"
) )
def calculate_stake(self, pair, last_candle): def calculate_stake(self, pair, last_candle, factor=1):
factor = 1 - 2 * (last_candle['close'] - last_candle['max7_1d']) / last_candle['max7_1d']
amount = self.config['stake_amount'] * factor #1000 / self.first_stack_factor.value self.protection_stake_amount.value # amount = self.config['stake_amount'] * factor #1000 / self.first_stack_factor.value self.protection_stake_amount.value #
return amount return amount
@property
def protections(self):
return [
{
"method": "CooldownPeriod",
"stop_duration_candles": 12
}
# {
# "method": "MaxDrawdown",
# "lookback_period_candles": self.lookback.value,
# "trade_limit": self.trade_limit.value,
# "stop_duration_candles": self.protection_stop.value,
# "max_allowed_drawdown": self.protection_max_allowed_dd.value,
# "only_per_pair": False
# },
# {
# "method": "StoplossGuard",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": self.protection_stoploss_stop.value,
# "only_per_pair": False
# },
# {
# "method": "StoplossGuard",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": 2,
# "only_per_pair": False
# },
# {
# "method": "LowProfitPairs",
# "lookback_period_candles": 6,
# "trade_limit": 2,
# "stop_duration_candles": 60,
# "required_profit": 0.02
# },
# {
# "method": "LowProfitPairs",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": 2,
# "required_profit": 0.01
# }
]

127
HeikinAshi.py Normal file
View File

@@ -0,0 +1,127 @@
# Heracles Strategy: Strongest Son of GodStra
# ( With just 1 Genome! its a bacteria :D )
# Author: @Mablue (Masoud Azizi)
# github: https://github.com/mablue/
# IMPORTANT:Add to your pairlists inside config.json (Under StaticPairList):
# {
# "method": "AgeFilter",
# "min_days_listed": 100
# },
# IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta)
#
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces roi buy --strategy Heracles
# ######################################################################
# --- Do not remove these libs ---
from freqtrade.strategy.parameters import IntParameter, DecimalParameter
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# Add your lib to import here
# import talib.abstract as ta
import pandas as pd
import ta
from ta.utils import dropna
import freqtrade.vendor.qtpylib.indicators as qtpylib
from functools import reduce
import numpy as np
class Heracles(IStrategy):
########################################## RESULT PASTE PLACE ##########################################
# 10/100: 25 trades. 18/4/3 Wins/Draws/Losses. Avg profit 5.92%. Median profit 6.33%. Total profit 0.04888306 BTC ( 48.88Σ%). Avg duration 4 days, 6:24:00 min. Objective: -11.42103
# Buy hyperspace params:
buy_params = {
"buy_crossed_indicator_shift": 9,
"buy_div_max": 0.75,
"buy_div_min": 0.16,
"buy_indicator_shift": 15,
}
# Sell hyperspace params:
sell_params = {
}
# ROI table:
minimal_roi = {
"0": 0.598,
"644": 0.166,
"3269": 0.115,
"7289": 0
}
# Stoploss:
stoploss = -0.256
# Optimal timeframe use it in your config
timeframe = '4h'
# Trailing stoploss
trailing_stop = True
trailing_stop_positive = 0.001
trailing_stop_positive_offset = 0.015
trailing_only_offset_is_reached = True
########################################## END RESULT PASTE PLACE ######################################
# buy params
buy_div_min = DecimalParameter(0, 1, default=0.16, decimals=2, space='buy')
buy_div_max = DecimalParameter(0, 1, default=0.75, decimals=2, space='buy')
buy_indicator_shift = IntParameter(0, 20, default=16, space='buy')
buy_crossed_indicator_shift = IntParameter(0, 20, default=9, space='buy')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe = dropna(dataframe)
dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
dataframe['high'],
dataframe['low'],
dataframe['close'],
window=20,
window_atr=10,
fillna=False,
original_version=True
)
dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
dataframe['high'],
dataframe['low'],
dataframe['close'],
window=10,
offset=0,
fillna=False
)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Buy strategy Hyperopt will build and use.
"""
conditions = []
IND = 'volatility_dcp'
CRS = 'volatility_kcw'
DFIND = dataframe[IND]
DFCRS = dataframe[CRS]
d = DFIND.shift(self.buy_indicator_shift.value).div(
DFCRS.shift(self.buy_crossed_indicator_shift.value))
# print(d.min(), "\t", d.max())
conditions.append(
d.between(self.buy_div_min.value, self.buy_div_max.value))
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy']=1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Sell strategy Hyperopt will build and use.
"""
dataframe.loc[:, 'sell'] = 0
return dataframe

View File

@@ -24,6 +24,7 @@ import ta
import talib.abstract as talib import talib.abstract as talib
import freqtrade.vendor.qtpylib.indicators as qtpylib import freqtrade.vendor.qtpylib.indicators as qtpylib
import requests import requests
from datetime import timezone, timedelta
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -233,7 +234,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# allow_to_buy = rate <= dataframe['lbp_3'] # allow_to_buy = rate <= dataframe['lbp_3']
self.trades = list() self.trades = list()
dispo = round(self.wallets.get_available_stake_amount()) dispo = round(self.wallets.get_available_stake_amount())
logger.info(f"{pair} allow_to_buy {allow_to_buy} limit={limit} Buy {entry_tag} {current_time} dispo={dispo}") logger.info(f"BUY {pair} allow_to_buy {allow_to_buy} limit={limit} Buy {entry_tag} {current_time} dispo={dispo}")
return allow_to_buy return allow_to_buy
@@ -250,14 +251,14 @@ class Zeus_8_3_2_B_4_2(IStrategy):
if allow_to_sell: if allow_to_sell:
self.trades = list() self.trades = list()
logger.info('Sell trade ' + exit_reason + ' ' + str(current_time) + ' ' + pair + " dispo=" + str( logger.info('Sell ' + exit_reason + ' ' + str(current_time) + ' ' + pair + " dispo=" + str(
round(self.wallets.get_available_stake_amount())) # "+ str(amount) + ' ' + str(rate) round(self.wallets.get_available_stake_amount())) # "+ str(amount) + ' ' + str(rate)
+ " open_rate=" + str(trade.open_rate) + " rate=" + str(rate) + " profit=" + str( + " open_rate=" + str(trade.open_rate) + " rate=" + str(rate) + " profit=" + str(
trade.calc_profit(rate, amount)) trade.calc_profit(rate, amount))
+ " " + string) + " " + string)
# del self.max_profit_pairs[pair] # del self.max_profit_pairs[pair]
else: else:
logger.info('Cancel Sell trade ' + exit_reason + ' ' + str(current_time) + ' ' + pair) logger.info('Cancel Sell ' + exit_reason + ' ' + str(current_time) + ' ' + pair)
return (allow_to_sell) | (exit_reason == 'force_exit') return (allow_to_sell) | (exit_reason == 'force_exit')
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
@@ -272,36 +273,35 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# Use default stake amount. # Use default stake amount.
return adjusted_stake_amount return adjusted_stake_amount
#
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, # def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float: # current_rate: float, current_profit: float, **kwargs) -> float:
#
# # hard stoploss profit # # # hard stoploss profit
# HSL = self.pHSL.value # # HSL = self.pHSL.value
# PF_1 = self.pPF_1.value # # PF_1 = self.pPF_1.value
# SL_1 = self.pSL_1.value # # SL_1 = self.pSL_1.value
# PF_2 = self.pPF_2.value # # PF_2 = self.pPF_2.value
# SL_2 = self.pSL_2.value # # SL_2 = self.pSL_2.value
# # #
# # For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated # # # For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated
# # between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value # # # between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value
# # rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used. # # # rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used.
# # #
# if current_profit > PF_2: # # if current_profit > PF_2:
# sl_profit = SL_2 + (current_profit - PF_2) # # sl_profit = SL_2 + (current_profit - PF_2)
# elif current_profit > PF_1: # # elif current_profit > PF_1:
# sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1)) # # sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1))
# else: # # else:
# sl_profit = HSL # # sl_profit = HSL
#
#print(f"entry_tag={trade.entry_tag} max={trade.max_rate} min={trade.min_rate} ") # #print(f"entry_tag={trade.entry_tag} max={trade.max_rate} min={trade.min_rate} ")
if current_profit > 0.0125: # if current_profit > 0.0125:
sl_profit = 0.75 * current_profit # 75% du profit en cours # sl_profit = 0.75 * current_profit # 75% du profit en cours
else: # else:
sl_profit = self.pHSL.value # Hard stop-loss # sl_profit = self.pHSL.value # Hard stop-loss
stoploss = stoploss_from_open(sl_profit, current_profit) # stoploss = stoploss_from_open(sl_profit, current_profit)
logger.info(f"stoploss={stoploss}") # return stoploss
return stoploss
# #
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) # dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
@@ -347,33 +347,33 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# print('current_profit=' + str(current_profit) + ' stop from open=' + str(slfo)) # print('current_profit=' + str(current_profit) + ' stop from open=' + str(slfo))
# return slfo # return slfo
# def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs): def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs):
#
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
#
# # self.analyze_conditions(pair, dataframe) # self.analyze_conditions(pair, dataframe)
#
# print("---------------" + pair + "----------------") # print("---------------" + pair + "----------------")
# expected_profit = self.expectedProfit(pair, last_candle) expected_profit = self.expectedProfit(pair, last_candle)
#
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# last_candle = dataframe.iloc[-1] last_candle = dataframe.iloc[-1]
#
# # Calcul du prix cible basé sur l'ATR # Calcul du prix cible basé sur l'ATR
# atr_take_profit = trade.open_rate + (last_candle['atr'] * 2) # Prendre profit à 2x l'ATR atr_take_profit = trade.open_rate + (last_candle['atr'] * 2) # Prendre profit à 2x l'ATR
#
# logger.info(f"{pair} Custom exit atr_take_profit={atr_take_profit:.4f}") # logger.info(f"{pair} Custom exit atr_take_profit={atr_take_profit:.4f}")
# # if current_rate >= atr_take_profit: # if current_rate >= atr_take_profit:
# # return 'sell_atr_take_profit' # return 'sell_atr_take_profit'
#
# if (last_candle['percent3'] < -0.002) & (last_candle['percent12'] < 0) & ( if (last_candle['percent3'] < -0.002) & (last_candle['percent12'] < 0) & (
# current_profit > last_candle['min_max200'] / 2): current_profit > last_candle['min_max200'] / 2):
# self.trades = list() self.trades = list()
# return 'min_max200' return 'min_max200'
# if (last_candle['percent12'] <= -0.01) & (current_profit >= expected_profit): if (last_candle['percent12'] <= -0.01) & (current_profit >= expected_profit):
# self.trades = list() self.trades = list()
# return 'profit' return 'profit'
def informative_pairs(self): def informative_pairs(self):
# get access to all pairs available in whitelist. # get access to all pairs available in whitelist.
@@ -548,6 +548,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe['limit'] = dataframe['last_price'] * (1 - self.baisse[count] / 100) dataframe['limit'] = dataframe['last_price'] * (1 - self.baisse[count] / 100)
dataframe['amount'] = amount dataframe['amount'] = amount
print(f"amount= {amount}") print(f"amount= {amount}")
# trades = Trade.get_trades([Trade.is_open is False]).all() # trades = Trade.get_trades([Trade.is_open is False]).all()
trades = Trade.get_trades_proxy(is_open=False, pair=metadata['pair']) trades = Trade.get_trades_proxy(is_open=False, pair=metadata['pair'])
if trades: if trades:
@@ -627,19 +628,19 @@ class Zeus_8_3_2_B_4_2(IStrategy):
self.trades = Trade.get_open_trades() self.trades = Trade.get_open_trades()
return self.trades return self.trades
def getTrade(self, pair): # def getTrade(self, pair):
trades = self.getOpenTrades() # trades = self.getOpenTrades()
trade_for_pair = None # trade_for_pair = None
for trade in trades: # for trade in trades:
if trade.pair == pair: # if trade.pair == pair:
trade_for_pair = trade # trade_for_pair = trade
break # break
return trade_for_pair # return trade_for_pair
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
pair = metadata['pair'] pair = metadata['pair']
self.getOpenTrades() # self.getOpenTrades()
expected_profit = self.expectedProfit(pair, dataframe.iloc[-1]) expected_profit = self.expectedProfit(pair, dataframe.iloc[-1])
# self.getBinanceOrderBook(pair, dataframe) # self.getBinanceOrderBook(pair, dataframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
@@ -648,7 +649,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# self.updateLastValue(dataframe, 'expected_profit', expected_profit) # self.updateLastValue(dataframe, 'expected_profit', expected_profit)
print("---------------" + pair + "----------------") print("---------------" + pair + "----------------")
print('adjust stake amount ' + str(self.adjust_stake_amount(pair, dataframe.iloc[-1]))) 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('adjust exit price ' + str(self.adjust_exit_price(dataframe.iloc[-1])))
print('calcul expected_profit ' + str(expected_profit)) 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)
@@ -705,7 +706,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
) )
& (dataframe['percent'] >= -0.0005) & (dataframe['percent'] >= -0.0005)
& (dataframe['min12'].shift(2) == dataframe['min12']) & (dataframe['min12'].shift(2) == dataframe['min12'])
), ['buy', 'enter_tag']] = (1, 'buy_min_max200_2') ), ['enter_long', 'enter_tag']] = (1, 'buy_min_max200_2')
dataframe.loc[ dataframe.loc[
( (
((dataframe['count_buys'] > 0) & (dataframe['close'] <= dataframe['limit'])) ((dataframe['count_buys'] > 0) & (dataframe['close'] <= dataframe['limit']))
@@ -715,7 +716,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
(dataframe['min12'].shift(2) == dataframe['min12']) | (dataframe['min12'].shift(2) == dataframe['min12']) |
(dataframe['min200'].shift(60) >= dataframe['min200'] * 1.03) (dataframe['min200'].shift(60) >= dataframe['min200'] * 1.03)
) )
), ['buy', 'enter_tag']] = (1, 'buy_count_buy') ), ['enter_long', 'enter_tag']] = (1, 'buy_count_buy')
dataframe.loc[ dataframe.loc[
( (
@@ -737,7 +738,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
| (dataframe['percent12'] < -0.022) | (dataframe['percent12'] < -0.022)
| (dataframe['percent24'] < -0.022) | (dataframe['percent24'] < -0.022)
) )
), ['buy', 'enter_tag']] = (1, 'buy_0_percent12') ), ['enter_long', 'enter_tag']] = (1, 'buy_0_percent12')
dataframe.loc[ dataframe.loc[
( (
# (dataframe['percent12'] < -0.015) # (dataframe['percent12'] < -0.015)
@@ -745,7 +746,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
& (dataframe['open'] < dataframe['average_line_50']) & (dataframe['open'] < dataframe['average_line_50'])
& (dataframe['close'] < dataframe['min12'] * 1.002) & (dataframe['close'] < dataframe['min12'] * 1.002)
& (dataframe['min12'].shift(2) == dataframe['min12']) & (dataframe['min12'].shift(2) == dataframe['min12'])
), ['buy', 'enter_tag']] = (1, 'buy_percent12') ), ['enter_long', 'enter_tag']] = (1, 'buy_percent12')
dataframe.loc[ dataframe.loc[
( (
@@ -755,7 +756,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
& (dataframe['min50'].shift(3) == dataframe['min50']) & (dataframe['min50'].shift(3) == dataframe['min50'])
& (dataframe['close'] <= dataframe['min50'] * 1.002) & (dataframe['close'] <= dataframe['min50'] * 1.002)
& (dataframe['open'] < dataframe['average_line_288']) & (dataframe['open'] < dataframe['average_line_288'])
), ['buy', 'enter_tag']] = (1, 'buy_percent_max_144') ), ['enter_long', 'enter_tag']] = (1, 'buy_percent_max_144')
dataframe.loc[ dataframe.loc[
( (
(dataframe['close'] <= dataframe['min200'] * 1.002) (dataframe['close'] <= dataframe['min200'] * 1.002)
@@ -763,7 +764,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
& (dataframe['pct_change'] < 0) & (dataframe['pct_change'] < 0)
& (dataframe['haopen'] < buy_level) & (dataframe['haopen'] < buy_level)
& (dataframe['open'] < dataframe['average_line_288']) & (dataframe['open'] < dataframe['average_line_288'])
), ['buy', 'enter_tag']] = (1, 'buy_min_max_200') ), ['enter_long', 'enter_tag']] = (1, 'buy_min_max_200')
dataframe.loc[ dataframe.loc[
( (
(dataframe['percent_max_144'] <= -0.02) (dataframe['percent_max_144'] <= -0.02)
@@ -773,21 +774,21 @@ class Zeus_8_3_2_B_4_2(IStrategy):
& (dataframe['close'] <= dataframe['average_line_288_099']) & (dataframe['close'] <= dataframe['average_line_288_099'])
& (dataframe['min50'].shift(3) == dataframe['min50']) & (dataframe['min50'].shift(3) == dataframe['min50'])
& (dataframe['close'] <= dataframe['min50'] * 1.002) & (dataframe['close'] <= dataframe['min50'] * 1.002)
), ['buy', 'enter_tag']] = (1, 'buy_close_02') ), ['enter_long', 'enter_tag']] = (1, 'buy_close_02')
dataframe.loc[ # dataframe.loc[
( # (
(dataframe['close'] <= dataframe['lowest_4_average'] * 1.002) # (dataframe['close'] <= dataframe['lowest_4_average'] * 1.002)
& (dataframe['haopen'] >= dataframe['lbp_3']) # & (dataframe['haopen'] >= dataframe['lbp_3'])
& (dataframe['haclose'] <= dataframe['lbp_3']) # & (dataframe['haclose'] <= dataframe['lbp_3'])
& (dataframe['haopen'] < buy_level) # & (dataframe['haopen'] < buy_level)
), ['buy', 'enter_tag']] = (1, 'buy_lbp_3') # ), ['enter_long', 'enter_tag']] = (1, 'buy_lbp_3')
dataframe.loc[ dataframe.loc[
( (
(dataframe['close'] <= dataframe['lowest_4_average'] * 1.002) (dataframe['close'] <= dataframe['lowest_4_average'] * 1.002)
& (dataframe['haopen'] >= dataframe['average_line_288_098']) & (dataframe['haopen'] >= dataframe['average_line_288_098'])
& (dataframe['haclose'] <= dataframe['average_line_288_098']) & (dataframe['haclose'] <= dataframe['average_line_288_098'])
& (dataframe['haopen'] < buy_level) & (dataframe['haopen'] < buy_level)
), ['buy', 'enter_tag']] = (1, 'buy_average_line_288_098') ), ['enter_long', 'enter_tag']] = (1, 'buy_average_line_288_098')
dataframe.loc[ dataframe.loc[
( (
(dataframe['close'].shift(2) <= dataframe['min200']) (dataframe['close'].shift(2) <= dataframe['min200'])
@@ -797,9 +798,9 @@ class Zeus_8_3_2_B_4_2(IStrategy):
& (dataframe['count_buys'] == 0 | & (dataframe['count_buys'] == 0 |
((dataframe['count_buys'] > 0) & (dataframe['close'] <= dataframe['limit'])) ((dataframe['count_buys'] > 0) & (dataframe['close'] <= dataframe['limit']))
) )
), ['buy', 'enter_tag']] = (1, 'buy_min200') ), ['enter_long', 'enter_tag']] = (1, 'buy_min200')
dataframe['test'] = np.where(dataframe['buy'] == 1, dataframe['close'] * 1.01, np.nan) dataframe['test'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.01, np.nan)
return dataframe return dataframe
@@ -810,7 +811,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# for trade in self.trades: # for trade in self.trades:
# if trade.pair != pair: # if trade.pair != pair:
# continue # continue
# filled_buys = trade.select_filled_orders('buy') # filled_buys = trade.select_filled_orders('enter_long')
# print('populate_buy_trend filled_buys : ' + str(len(filled_buys))) # print('populate_buy_trend filled_buys : ' + str(len(filled_buys)))
# # Affichez les valeurs # # Affichez les valeurs
# print(pair, limit) # print(pair, limit)
@@ -848,10 +849,10 @@ class Zeus_8_3_2_B_4_2(IStrategy):
if count_of_buys >= max_buys: if count_of_buys >= max_buys:
return None return None
if 'buy' in last_candle: # if 'buy' in last_candle:
condition = (last_candle['buy'] == 1) # condition = (last_candle['buy'] == 1)
else: # else:
condition = False # condition = False
# self.protection_nb_buy_lost.value # self.protection_nb_buy_lost.value
# limits = ['lbp_3', 'lbp_6', 'lbp_9', 'lbp_12', 'lbp_20'] # limits = ['lbp_3', 'lbp_6', 'lbp_9', 'lbp_12', 'lbp_20']
# limit = last_candle[limits[count_of_buys]] # limit = last_candle[limits[count_of_buys]]
@@ -859,17 +860,20 @@ class Zeus_8_3_2_B_4_2(IStrategy):
stake_amount = min(200, self.adjust_stake_amount(pair, last_candle) * self.fibo[count_of_buys]) stake_amount = min(200, self.adjust_stake_amount(pair, last_candle) * self.fibo[count_of_buys])
# print("Adjust " + trade.pair + " time=" + str(current_time) + ' rate=' + str(current_rate) + " buys=" + str(count_of_buys) + " limit=" + str(limit) + " stake=" + str(stake_amount)) # print("Adjust " + trade.pair + " time=" + str(current_time) + ' rate=' + str(current_rate) + " buys=" + str(count_of_buys) + " limit=" + str(limit) + " stake=" + str(stake_amount))
logger.info( # logger.info(
f"Adjust price={trade.pair} buy={condition} rate={current_rate:.4f} buys={count_of_buys} limit={limit:.4f} stake={stake_amount:.4f}") # f"Adjust price={trade.pair} buy={condition} rate={current_rate:.4f} buys={count_of_buys} limit={limit:.4f} stake={stake_amount:.4f}")
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
if (0 < count_of_buys <= max_buys) & (current_rate <= limit) & (condition): if (days_since_open > count_of_buys) & (0 < count_of_buys <= max_buys) & (current_rate <= limit) & (last_candle['enter_long'] == 1):
try: try:
# This then calculates current safety order size # This then calculates current safety order size
# stake_amount = stake_amount * pow(1.5, count_of_buys) # stake_amount = stake_amount * pow(1.5, count_of_buys)
# print("Effective Adjust " + trade.pair + " time=" + str(current_time) + ' rate=' + str(current_rate) + " buys=" + str(count_of_buys) + " limit=" + str(limit) + " stake=" + str(stake_amount)) # print("Effective Adjust " + trade.pair + " time=" + str(current_time) + ' rate=' + str(current_rate) + " buys=" + str(count_of_buys) + " limit=" + str(limit) + " stake=" + str(stake_amount))
logger.info( logger.info(
f"Effective Adjust price={trade.pair} rate={current_rate:.4f} buys={count_of_buys} limit={limit:.4f} stake={stake_amount:.4f}") f"Adjust {current_time} price={trade.pair} rate={current_rate:.4f} buys={count_of_buys} limit={limit:.4f} stake={stake_amount:.4f}")
return stake_amount return stake_amount
except Exception as exception: except Exception as exception:
@@ -907,24 +911,24 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# adjusted_stake_amount_2 = max(base_stake_amount / 2.5, min(75, base_stake_amount * percent)) # adjusted_stake_amount_2 = max(base_stake_amount / 2.5, min(75, base_stake_amount * percent))
print( # print(
f"Stack amount ajusté price={current_price} max_min={max_min_4:.4f} min_14={min_14_days_4:.4f} max_14={max_14_days_4:.4f} factor={factor_4:.4f} percent={percent_4:.4f} amount={adjusted_stake_amount:.4f}") # f"Stack amount ajusté price={current_price} max_min={max_min_4:.4f} min_14={min_14_days_4:.4f} max_14={max_14_days_4:.4f} factor={factor_4:.4f} percent={percent_4:.4f} amount={adjusted_stake_amount:.4f}")
# print(f"Stack amount ajusté price={current_price} max_min={max_min:.4f} min_14={min_14_days:.4f} max_14={max_14_days:.4f} factor={factor:.4f} percent={percent:.4f} amount={adjusted_stake_amount_2:.4f}") # print(f"Stack amount ajusté price={current_price} max_min={max_min:.4f} min_14={min_14_days:.4f} max_14={max_14_days:.4f} factor={factor:.4f} percent={percent:.4f} amount={adjusted_stake_amount_2:.4f}")
return adjusted_stake_amount return adjusted_stake_amount
def adjust_exit_price(self, dataframe: DataFrame): # def adjust_exit_price(self, dataframe: DataFrame):
# Calculer le max des 14 derniers jours # # Calculer le max des 14 derniers jours
min_14_days = dataframe['lowest_1d'] # min_14_days = dataframe['lowest_1d']
max_14_days = dataframe['highest_1d'] # max_14_days = dataframe['highest_1d']
entry_price = dataframe['fbp'] # entry_price = dataframe['fbp']
current_price = dataframe['close'] # current_price = dataframe['close']
percent = 0.5 * (max_14_days - min_14_days) / min_14_days # percent = 0.5 * (max_14_days - min_14_days) / min_14_days
exit_price = (1 + percent) * entry_price # exit_price = (1 + percent) * entry_price
#
print(f"Exit price ajusté price={current_price:.4f} max_14={max_14_days:.4f} exit_price={exit_price:.4f}") # print(f"Exit price ajusté price={current_price:.4f} max_14={max_14_days:.4f} exit_price={exit_price:.4f}")
#
return exit_price # return exit_price
def adjust_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def adjust_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float: current_rate: float, current_profit: float, **kwargs) -> float:
@@ -954,8 +958,8 @@ class Zeus_8_3_2_B_4_2(IStrategy):
min_max = dataframe['pct_min_max_1d'] # (max_14_days - min_14_days) / min_14_days min_max = dataframe['pct_min_max_1d'] # (max_14_days - min_14_days) / min_14_days
expected_profit = min(0.1, max(0.01, dataframe['min_max200'] * 0.5)) expected_profit = min(0.1, max(0.01, dataframe['min_max200'] * 0.5))
print( # 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}") # 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}")
# self.analyze_conditions(pair, dataframe) # self.analyze_conditions(pair, dataframe)
return expected_profit return expected_profit