optimisation

This commit is contained in:
Jérôme Delacotte
2026-01-13 16:29:24 +01:00
parent 8210b5c0b3
commit 978f062991
2 changed files with 57 additions and 30 deletions

View File

@@ -19,7 +19,7 @@
"protection": { "protection": {
"allow_decrease_rate": 0.4, "allow_decrease_rate": 0.4,
"first_adjust_param": 0.005, "first_adjust_param": 0.005,
"max_steps": 45 "max_steps": 30
}, },
"buy": { "buy": {
"hours_force": 44, "hours_force": 44,

View File

@@ -93,7 +93,7 @@ class FrictradeLearning(IStrategy):
indic_1h_force_buy = CategoricalParameter(indicators, default="sma60_deriv1", space='buy') indic_1h_force_buy = CategoricalParameter(indicators, default="sma60_deriv1", space='buy')
allow_decrease_rate = DecimalParameter(0.1, 0.8, decimals=1, default=0.4, space='protection', optimize=False, allow_decrease_rate = DecimalParameter(0.1, 0.8, decimals=1, default=0.4, space='protection', optimize=False,
load=False) load=True)
first_adjust_param = DecimalParameter(0.001, 0.01, decimals=3, default=0.005, space='protection', optimize=False, first_adjust_param = DecimalParameter(0.001, 0.01, decimals=3, default=0.005, space='protection', optimize=False,
load=False) load=False)
max_steps = IntParameter(10, 50, default=40, space='protection', optimize=True, load=True) max_steps = IntParameter(10, 50, default=40, space='protection', optimize=True, load=True)
@@ -114,7 +114,7 @@ class FrictradeLearning(IStrategy):
use_custom_stoploss = False use_custom_stoploss = False
trailing_stop = False trailing_stop = False
trailing_stop_positive = 0.15 trailing_stop_positive = 0.25
trailing_stop_positive_offset = 1 trailing_stop_positive_offset = 1
trailing_only_offset_is_reached = True trailing_only_offset_is_reached = True
@@ -192,6 +192,11 @@ class FrictradeLearning(IStrategy):
# OFFSET_MIN = self.offset_min.value # OFFSET_MIN = self.offset_min.value
# OFFSET_MAX = self.offset_min.value + self.offset_max.value # OFFSET_MAX = self.offset_min.value + self.offset_max.value
# if self.pairs[pair]['has_gain'] > 0:
# return 0
# if self.pairs[pair]['has_gain']:
# stake = (stake - self.pairs[pair]['first_amount'])
if last_candle['sma180_deriv1'] < 0.005: if last_candle['sma180_deriv1'] < 0.005:
return stake / 200 return stake / 200
@@ -266,9 +271,9 @@ class FrictradeLearning(IStrategy):
buys=1, buys=1,
stake=round(stake_amount, 2) stake=round(stake_amount, 2)
) )
else: # else:
self.printLog( # self.printLog(
f"{current_time} BUY triggered for {pair} (cooldown={cooldown} minutes={minutes} percent={round(last_candle['hapercent'], 4)}) but condition blocked") # f"{current_time} BUY triggered for {pair} (cooldown={cooldown} minutes={minutes} percent={round(last_candle['hapercent'], 4)}) but condition blocked")
return allow_to_buy return allow_to_buy
@@ -302,7 +307,7 @@ class FrictradeLearning(IStrategy):
val = self.pairs[pair]['first_price'] if self.pairs[pair]['first_price'] > 0 else last_candle['mid'] val = self.pairs[pair]['first_price'] if self.pairs[pair]['first_price'] > 0 else last_candle['mid']
if self.pairs[pair]['last_ath'] == 0: if self.pairs[pair]['last_ath'] == 0:
ath = max(val, self.get_last_ath_before_candle(last_candle['date'])) ath = max(val, self.get_last_ath_before_candle(last_candle))
self.pairs[pair]['last_ath'] = ath self.pairs[pair]['last_ath'] = ath
ath = self.pairs[pair]['last_ath'] ath = self.pairs[pair]['last_ath']
@@ -654,6 +659,8 @@ class FrictradeLearning(IStrategy):
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1d') informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1d')
informative['mid'] = informative['open'] + (informative['close'] - informative['open']) / 2 informative['mid'] = informative['open'] + (informative['close'] - informative['open']) / 2
informative['rsi'] = talib.RSI(informative['mid'], timeperiod=5) informative['rsi'] = talib.RSI(informative['mid'], timeperiod=5)
informative['min30'] = talib.MIN(informative['mid'], timeperiod=30)
informative['max30'] = talib.MAX(informative['mid'], timeperiod=30)
# informative = self.rsi_trend_probability(informative) # informative = self.rsi_trend_probability(informative)
# informative = self.calculateRegression(informative, 'mid', lookback=15) # informative = self.calculateRegression(informative, 'mid', lookback=15)
# self.calculateConfiance(informative) # self.calculateConfiance(informative)
@@ -956,7 +963,7 @@ class FrictradeLearning(IStrategy):
# f"pct={(round(val - (ath * (1 - self.allow_decrease_rate.value))) / val, 4)}") # f"pct={(round(val - (ath * (1 - self.allow_decrease_rate.value))) / val, 4)}")
# print(dca_thresholds) # print(dca_thresholds)
if self.pairs[pair]['last_ath'] == 0: if self.pairs[pair]['last_ath'] == 0:
ath = max(val, self.get_last_ath_before_candle(last_candle['date'])) ath = max(val, self.get_last_ath_before_candle(last_candle))
self.pairs[pair]['last_ath'] = ath self.pairs[pair]['last_ath'] = ath
if len(self.pairs[pair]['dca_thresholds']) == 0: if len(self.pairs[pair]['dca_thresholds']) == 0:
self.calculateStepsDcaThresholds(last_candle, pair) self.calculateStepsDcaThresholds(last_candle, pair)
@@ -1070,7 +1077,7 @@ class FrictradeLearning(IStrategy):
& (dataframe['sma5_deriv2'] > 0) & (dataframe['sma5_deriv2'] > 0)
& (dataframe['rsi'] < 77) & (dataframe['rsi'] < 77)
& (dataframe['heat_score_1h'] < 0.5) & (dataframe['heat_score_1h'] < 0.5)
& (dataframe['sma180_deriv1'] > 0) # & (dataframe['sma180_deriv1'] > 0)
# & (dataframe['open'] < dataframe['max180'] * 0.997) # & (dataframe['open'] < dataframe['max180'] * 0.997)
# & (dataframe['min180'].shift(3) == dataframe['min180']) # & (dataframe['min180'].shift(3) == dataframe['min180'])
, ['enter_long', 'enter_tag'] , ['enter_long', 'enter_tag']
@@ -1209,7 +1216,7 @@ class FrictradeLearning(IStrategy):
count = self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] count = self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain']
return mises[count] if count < len(mises) else self.pairs[pair]['first_amount'] return mises[count] if count < len(mises) else self.pairs[pair]['first_amount']
ath = max(self.pairs[pair]['last_max'], self.get_last_ath_before_candle(last_candle['date'])) ath = max(self.pairs[pair]['last_max'], self.get_last_ath_before_candle(last_candle))
full, mises, steps = self.calculateMises(pair, ath, last_candle['mid']) full, mises, steps = self.calculateMises(pair, ath, last_candle['mid'])
base_stake = mises[self.pairs[pair]['count_of_buys']] if self.pairs[pair]['count_of_buys'] < len( base_stake = mises[self.pairs[pair]['count_of_buys']] if self.pairs[pair]['count_of_buys'] < len(
@@ -1217,7 +1224,7 @@ class FrictradeLearning(IStrategy):
return base_stake return base_stake
def calculateMises(self, pair, ath, val): def calculateMises(self, pair, ath, val):
# ath = max(self.pairs[pair]['last_max'], self.get_last_ath_before_candle(last_candle['date'])) # ath = max(self.pairs[pair]['last_max'], self.get_last_ath_before_candle(last_candle))
self.pairs[pair]['last_ath'] = ath self.pairs[pair]['last_ath'] = ath
full = self.wallets.get_total_stake_amount() full = self.wallets.get_total_stake_amount()
steps = self.calculateNumberOfSteps(val, ath, max_steps=self.max_steps.value) steps = self.calculateNumberOfSteps(val, ath, max_steps=self.max_steps.value)
@@ -1313,7 +1320,7 @@ class FrictradeLearning(IStrategy):
increase = - decline increase = - decline
# FIN ########################## ALGO ATH # FIN ########################## ALGO ATH
force = False #hours > self.hours_force.value and last_candle[self.indic_1h_force_buy.value] > 0 force = hours > 12 #self.hours_force.value and last_candle[self.indic_1h_force_buy.value] > 0
condition = last_candle['percent'] > 0 \ condition = last_candle['percent'] > 0 \
and ((count_of_buys <= 4 and last_candle['sma24_deriv1'] > 0) or (count_of_buys > 4 and last_candle['sma60_deriv1'] > 0))\ and ((count_of_buys <= 4 and last_candle['sma24_deriv1'] > 0) or (count_of_buys > 4 and last_candle['sma60_deriv1'] > 0))\
and last_candle['close'] < self.pairs[pair]['first_price'] and last_candle['close'] < self.pairs[pair]['first_price']
@@ -1373,7 +1380,7 @@ class FrictradeLearning(IStrategy):
increase_dca_threshold = 0.003 increase_dca_threshold = 0.003
if current_profit > increase_dca_threshold \ if current_profit > increase_dca_threshold \
and (increase >= increase_dca_threshold and self.wallets.get_available_stake_amount() > 0) \ and (increase >= increase_dca_threshold and self.wallets.get_available_stake_amount() > 0) \
and last_candle['sma5_deriv1'] > 0 and last_candle['sma5_deriv2'] > 0 and last_candle['max_rsi_12'] < 88: and last_candle['sma5_deriv1'] > 0 and last_candle['sma5_deriv2'] > 0 and last_candle['max_rsi_12'] < 80:
try: try:
print(f"decline={decline} last_fill_price={last_fill_price} current_rate={current_rate}") print(f"decline={decline} last_fill_price={last_fill_price} current_rate={current_rate}")
@@ -1466,7 +1473,9 @@ class FrictradeLearning(IStrategy):
current_trailing_only_offset_is_reached = self.trailing_only_offset_is_reached current_trailing_only_offset_is_reached = self.trailing_only_offset_is_reached
current_trailing_stop_positive_offset = self.trailing_stop_positive_offset current_trailing_stop_positive_offset = self.trailing_stop_positive_offset
current_trailing_stop_positive_offset = self.dynamic_trailing_offset(pair, self.pairs[pair]['total_amount'], last_candle, price=current_rate, current_trailing_stop_positive_offset = self.dynamic_trailing_offset(
pair, self.pairs[pair]['total_amount'], last_candle,
price=current_rate,
ath=self.pairs[pair]['last_ath'], ath=self.pairs[pair]['last_ath'],
count_of_buys=count_of_buys) count_of_buys=count_of_buys)
@@ -1489,10 +1498,10 @@ class FrictradeLearning(IStrategy):
# Exemple : offset=0.321 => stop à +24.8% # Exemple : offset=0.321 => stop à +24.8%
trailing_stop = max_profit * (1.0 - current_trailing_stop_positive) trailing_stop = max_profit * (1.0 - current_trailing_stop_positive)
# baisse = 0 baisse = 0
# if max_profit: if max_profit:
# baisse = (max_profit - profit) / max_profit baisse = (max_profit - profit) / max_profit
# print(f"baisse={baisse}")
# if minutes % 1 == 0: # if minutes % 1 == 0:
# self.log_trade( # self.log_trade(
# last_candle=last_candle, # last_candle=last_candle,
@@ -1506,15 +1515,19 @@ class FrictradeLearning(IStrategy):
# buys=count_of_buys, # buys=count_of_buys,
# stake=0 # stake=0
# ) # )
if profit < 0: if profit < 0.65: #5 or last_candle['rsi_1d'] < 30:
return None return None
if last_candle['max_rsi_24'] > 88 and last_candle['hapercent'] < 0\ if last_candle['max_rsi_24'] > 88 and last_candle['hapercent'] < 0\
and last_candle['sma5_deriv2'] < -0.1: and last_candle['sma5_deriv2'] < -0.1:
return f"rsi_{count_of_buys}_{self.pairs[pair]['has_gain']}" return f"rsi_{count_of_buys}_{self.pairs[pair]['has_gain']}"
if last_candle['sma12_deriv1'] > 0: # and last_candle['rsi'] < 85: limit = max_profit * (1 - current_trailing_stop_positive)
return None # if profit < limit and baisse > 0.2:
# return f"lim_{count_of_buys}_{self.pairs[pair]['has_gain']}"
# if last_candle['ml_prob'] > 0.5:
# if last_candle['sma12_deriv1'] > 0: # and last_candle['rsi'] < 85:
# return None
# if last_candle['sma24_deriv1'] > 0 : #and minutes < 180 and baisse < 30: # and last_candle['sma5_deriv1'] > -0.15: # if last_candle['sma24_deriv1'] > 0 : #and minutes < 180 and baisse < 30: # and last_candle['sma5_deriv1'] > -0.15:
# if (minutes < 180): # if (minutes < 180):
@@ -1525,16 +1538,21 @@ class FrictradeLearning(IStrategy):
# ----- 4) OFFSET : faut-il attendre de dépasser trailing_stop_positive_offset ? ----- # ----- 4) OFFSET : faut-il attendre de dépasser trailing_stop_positive_offset ? -----
if current_trailing_only_offset_is_reached and max_profit > current_trailing_stop_positive_offset: if current_trailing_only_offset_is_reached and max_profit > current_trailing_stop_positive_offset:
# Max profit pas atteint ET perte < 2 * current_trailing_stop_positive # Max profit pas atteint ET perte < 2 * current_trailing_stop_positive
if profit > max_profit * (1 - current_trailing_stop_positive): # 2 * current_trailing_stop_positive: if profit > limit: # 2 * current_trailing_stop_positive:
print( print(
f"{current_time} trailing non atteint trailing_stop={round(trailing_stop, 4)} profit={round(profit, 4)} " f"{current_time} trailing non atteint trailing_stop={round(trailing_stop, 4)} profit={round(profit, 4)} "
f"max={round(max_profit, 4)} offset={current_trailing_stop_positive_offset}") f"max={round(max_profit, 4)} offset={round(current_trailing_stop_positive_offset, 4)} baisse={round(baisse,2)}")
return None # ne pas activer le trailing encore return None # ne pas activer le trailing encore
else: else:
print( print(
f"{current_time} trailing atteint trailing_stop={round(trailing_stop, 4)} profit={round(profit, 4)} " f"{current_time} trailing atteint trailing_stop={round(trailing_stop, 4)} profit={round(profit, 4)} "
f"max={round(max_profit, 4)} offset={current_trailing_stop_positive_offset}") f"max={round(max_profit, 4)} offset={round(current_trailing_stop_positive_offset, 4)} baisse={round(baisse,2)}")
else: else:
# print(
# f"1 - {current_time} trailing_stop={round(trailing_stop, 4)} profit={round(profit, 4)} max={round(max_profit, 4)} "
# f"limit={round(limit, 4)} offset={round(current_trailing_stop_positive_offset, 4)}"
# f" baisse={round(baisse,2)} {round(last_candle['sma180_deriv1'], 4)} {round(last_candle['sma60_deriv1'], 4)} {round(last_candle['sma24_deriv1'], 4)}")
return None return None
# Sinon : trailing actif dès le début # Sinon : trailing actif dès le début
@@ -1543,9 +1561,16 @@ class FrictradeLearning(IStrategy):
self.pairs[pair]['force_buy'] = True self.pairs[pair]['force_buy'] = True
print( print(
f"{current_time} Condition de vente trailing_stop={round(trailing_stop, 4)} profit={round(profit, 4)} max={round(max_profit, 4)} " f"{current_time} Condition de vente trailing_stop={round(trailing_stop, 4)} profit={round(profit, 4)} max={round(max_profit, 4)} "
f"{round(min(2, max_profit * (1 - current_trailing_stop_positive)), 4)} offset={current_trailing_stop_positive_offset}") f"{round(limit, 4)} offset={round(current_trailing_stop_positive_offset, 4)} "
f"baisse={round(baisse,2)}")
return f"stop_{count_of_buys}_{self.pairs[pair]['has_gain']}" return f"stop_{count_of_buys}_{self.pairs[pair]['has_gain']}"
print(
f"2 - {current_time} trailing_stop={round(trailing_stop, 4)} profit={round(profit, 4)} max={round(max_profit, 4)} "
f"{round(limit, 4)} offset={round(current_trailing_stop_positive_offset, 4)} "
f"baisse={round(baisse,2)} {round(last_candle['sma180_deriv1'], 4)} {round(last_candle['sma60_deriv1'], 4)} {round(last_candle['sma24_deriv1'], 4)}")
return None return None
def informative_pairs(self): def informative_pairs(self):
@@ -1643,9 +1668,9 @@ class FrictradeLearning(IStrategy):
return pd.to_datetime(x, utc=True) return pd.to_datetime(x, utc=True)
# suppose self.btc_ath_history exists (liste de dict) # suppose self.btc_ath_history exists (liste de dict)
def get_last_ath_before_candle(self, date): def get_last_ath_before_candle(self, last_candle):
# return last_candle['max30_1d']
candle_date = self.to_utc_ts(date) # ou to_utc_ts(last_candle.name) candle_date = self.to_utc_ts(last_candle['date']) # ou to_utc_ts(last_candle.name)
best = None best = None
for a in self.btc_ath_history: # getattr(self, "btc_ath_history", []): for a in self.btc_ath_history: # getattr(self, "btc_ath_history", []):
ath_date = self.to_utc_ts(a["date"]) ath_date = self.to_utc_ts(a["date"])
@@ -2353,6 +2378,8 @@ class FrictradeLearning(IStrategy):
and not c.startswith('price_change') and not c.startswith('price_change')
and not c.startswith('price_score') and not c.startswith('price_score')
and not c.startswith('heat_score') and not c.startswith('heat_score')
and not c.startswith('min30_1d')
and not c.startswith('max30_1d')
] ]
# Étape 3 : remplacer inf et NaN par 0 # Étape 3 : remplacer inf et NaN par 0
dataframe[usable_cols] = dataframe[usable_cols].replace([np.inf, -np.inf], 0).fillna(0) dataframe[usable_cols] = dataframe[usable_cols].replace([np.inf, -np.inf], 0).fillna(0)