Frictrade progression adjust exponentielle / correction trailing

This commit is contained in:
Jérôme Delacotte
2025-12-07 19:13:55 +01:00
parent e8cdf10488
commit 3cac030f10

View File

@@ -27,6 +27,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
from datetime import timezone, timedelta from datetime import timezone, timedelta
import mpmath as mp
# Machine Learning # Machine Learning
from sklearn.ensemble import RandomForestClassifier,RandomForestRegressor from sklearn.ensemble import RandomForestClassifier,RandomForestRegressor
@@ -133,7 +134,7 @@ class FrictradeLearning(IStrategy):
trailing_stop = False trailing_stop = False
trailing_stop_positive = 0.15 trailing_stop_positive = 0.15
trailing_stop_positive_offset = 0.5 trailing_stop_positive_offset = 1
trailing_only_offset_is_reached = True trailing_only_offset_is_reached = True
# Buy hypers # Buy hypers
@@ -246,19 +247,33 @@ class FrictradeLearning(IStrategy):
return allow_to_buy return allow_to_buy
def calculateStepsDcaThresholds(self, last_candle, pair): def calculateStepsDcaThresholds(self, last_candle, pair):
def split_ratio_one_third(n, p): # def split_ratio_one_third(n, p):
a = n / (2 * p) # première valeur # a = n / (2 * p) # première valeur
d = n / (p * (p - 1)) # incrément # d = n / (p * (p - 1)) # incrément
return [round(a + i * d, 3) for i in range(p)] # return [round(a + i * d, 3) for i in range(p)]
def progressive_parts(total, n, first):
# solve for r
# S = first * (r^n - 1)/(r - 1) = total
# numeric solving
f = lambda r: first * (r ** n - 1) / (r - 1) - total
r = mp.findroot(f, 1.05) # initial guess
parts = [round(first * (r ** k), 4) for k in range(n)]
return parts
# r, parts = progressive_parts(0.4, 40, 0.004)
# print("r =", r)
# print(parts)
if self.pairs[pair]['last_ath'] == 0 : if self.pairs[pair]['last_ath'] == 0 :
ath = max(last_candle['mid'], self.get_last_ath_before_candle(last_candle)) ath = max(last_candle['mid'], self.get_last_ath_before_candle(last_candle))
self.pairs[pair]['last_ath'] = ath self.pairs[pair]['last_ath'] = ath
steps = self.approx_value(last_candle['mid'], self.pairs[pair]['last_ath']) steps = self.approx_value(last_candle['mid'], self.pairs[pair]['last_ath'])
self.pairs[pair]['dca_thresholds'] = split_ratio_one_third( self.pairs[pair]['dca_thresholds'] = progressive_parts(
(last_candle['mid'] - (self.pairs[pair]['last_ath'] * (1 - self.allow_decrease_rate))) / last_candle['mid'], (last_candle['mid'] - (self.pairs[pair]['last_ath'] * (1 - self.allow_decrease_rate))) / last_candle['mid'],
steps) steps, 0.003)
print(f"val={last_candle['mid']} steps={steps} pct={(last_candle['mid'] - (self.pairs[pair]['last_ath'] * (1 - self.allow_decrease_rate))) / last_candle['mid']}") print(f"val={last_candle['mid']} steps={steps} pct={(last_candle['mid'] - (self.pairs[pair]['last_ath'] * (1 - self.allow_decrease_rate))) / last_candle['mid']}")
print(self.pairs[pair]['dca_thresholds']) print(self.pairs[pair]['dca_thresholds'])
@@ -895,9 +910,11 @@ class FrictradeLearning(IStrategy):
# Buy = prediction > threshold # Buy = prediction > threshold
dataframe["buy"] = 0 dataframe["buy"] = 0
dataframe.loc[ dataframe.loc[
(dataframe["ml_prob"].shift(3) < 0.2) (dataframe["ml_prob"].shift(1) < dataframe["ml_prob"])
& (dataframe['low'].shift(3) < dataframe['min180'].shift(3)) & (dataframe['sma24_deriv1'] > 0)
& (dataframe['min180'].shift(3) == dataframe['min180']), & (dataframe['sma12_deriv1'] > 0)
& (dataframe['open'] < dataframe['max180'] * 0.997),
# & (dataframe['min180'].shift(3) == dataframe['min180']),
['enter_long', 'enter_tag'] ['enter_long', 'enter_tag']
] = (1, f"future") ] = (1, f"future")
dataframe['test'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.003, np.nan) dataframe['test'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.003, np.nan)
@@ -1310,6 +1327,8 @@ class FrictradeLearning(IStrategy):
# if current_profit > 0: # if current_profit > 0:
# print(f"profit={profit} max_profit={max_profit} current_profit={current_profit}") # print(f"profit={profit} max_profit={max_profit} current_profit={current_profit}")
if profit < 0:
return None
baisse = 0 baisse = 0
if profit > 0: if profit > 0:
@@ -1318,11 +1337,11 @@ class FrictradeLearning(IStrategy):
self.pairs[pair]['count_of_buys'] = count_of_buys self.pairs[pair]['count_of_buys'] = count_of_buys
self.pairs[pair]['current_profit'] = profit self.pairs[pair]['current_profit'] = profit
dispo = round(self.wallets.get_available_stake_amount()) # dispo = round(self.wallets.get_available_stake_amount())
hours_since_first_buy = (current_time - trade.open_date_utc).seconds / 3600.0 # hours_since_first_buy = (current_time - trade.open_date_utc).seconds / 3600.0
days_since_first_buy = (current_time - trade.open_date_utc).days # days_since_first_buy = (current_time - trade.open_date_utc).days
hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0 # hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
minutes = (current_time - trade.date_last_filled_utc).total_seconds() / 60.0 # minutes = (current_time - trade.date_last_filled_utc).total_seconds() / 60.0
# ----- 2) Mise à jour du max_price ----- # ----- 2) Mise à jour du max_price -----
self.pairs[pair]['max_touch'] = max(last_candle['close'], self.pairs[pair]['max_touch']) self.pairs[pair]['max_touch'] = max(last_candle['close'], self.pairs[pair]['max_touch'])
@@ -1383,14 +1402,23 @@ 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: if current_trailing_only_offset_is_reached:
# Max profit pas atteint ET perte < 2 * current_trailing_stop_positive # Max profit pas atteint ET perte < 2 * current_trailing_stop_positive
if max_profit < min(2, current_trailing_stop_positive_offset * (count_of_buys - self.pairs[pair]['has_gain']))\ if max_profit < min(2, max_profit * current_trailing_stop_positive_offset * (count_of_buys - self.pairs[pair]['has_gain'])): #2 * current_trailing_stop_positive:
and (max_profit > current_trailing_stop_positive_offset): #2 * current_trailing_stop_positive: print(f"{current_time} trailing non atteint trailing_stop={round(trailing_stop,4)} profit={round(profit, 4)} max={round(max_profit, 4)} "
f"{min(2, current_trailing_stop_positive_offset * (count_of_buys - self.pairs[pair]['has_gain']))}")
return None # ne pas activer le trailing encore return None # ne pas activer le trailing encore
else:
print(f"{current_time} trailing atteint trailing_stop={round(trailing_stop,4)} profit={round(profit, 4)} max={round(max_profit, 4)} "
f"{min(2, current_trailing_stop_positive_offset * (count_of_buys - self.pairs[pair]['has_gain']))}")
# Sinon : trailing actif dès le début # Sinon : trailing actif dès le début
# ----- 6) Condition de vente ----- # ----- 6) Condition de vente -----
if 0 < profit <= trailing_stop and last_candle['mid'] < last_candle['sma5']: if 0 < profit <= trailing_stop and last_candle['mid'] < last_candle['sma5']:
self.pairs[pair]['force_buy'] = True self.pairs[pair]['force_buy'] = True
print(
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, current_trailing_stop_positive_offset * (count_of_buys - self.pairs[pair]['has_gain'])), 4)}")
return f"stop_{count_of_buys}_{self.pairs[pair]['has_gain']}" return f"stop_{count_of_buys}_{self.pairs[pair]['has_gain']}"
return None return None