Frictrade

This commit is contained in:
Jérôme Delacotte
2025-11-25 21:53:18 +01:00
parent 8bf0a0e2c3
commit 51ca009751

View File

@@ -56,10 +56,10 @@ class Frictrade(IStrategy):
# Custom stoploss
use_custom_stoploss = False
trailing_stop = True
trailing_stop = False
trailing_stop_positive = 0.15
trailing_stop_positive_offset = 0.1
trailing_only_offset_is_reached = False
trailing_stop_positive_offset = 0.5
trailing_only_offset_is_reached = True
# Buy hypers
timeframe = '1m'
@@ -170,7 +170,6 @@ class Frictrade(IStrategy):
self.pairs[pair]['last_count_of_buys'] = trade.nr_of_successful_entries # self.pairs[pair]['count_of_buys']
self.pairs[pair]['last_sell'] = rate
self.pairs[pair]['last_candle'] = last_candle
self.pairs[pair]['max_profit'] = 0
self.pairs[pair]['previous_profit'] = 0
self.trades = list()
dispo = round(self.wallets.get_available_stake_amount())
@@ -185,6 +184,7 @@ class Frictrade(IStrategy):
dispo=dispo,
profit=round(profit, 2)
)
self.pairs[pair]['max_profit'] = 0
self.pairs[pair]['force_sell'] = False
self.pairs[pair]['has_gain'] = 0
self.pairs[pair]['current_profit'] = 0
@@ -438,6 +438,32 @@ class Frictrade(IStrategy):
count_buys = count
self.pairs[pair]['total_amount'] = amount
dataframe['absolute_min'] = dataframe['mid'].rolling(1440, min_periods=1).min()
for i in [1, 2, 3, 4]:
dataframe[f"lvl_{i}_pct"] = dataframe['absolute_min'] * (1 + 0.01 * i)
# dataframe['absolute_max'] = dataframe['mid'].rolling(1440, min_periods=1).max()
#
# absolute_min = dataframe['absolute_min'].min()
# absolute_max = dataframe['absolute_max'].max()
#
# # Écart total
# diff = absolute_max - absolute_min
#
# # Nombre de lignes intermédiaires (1% steps)
# steps = int((absolute_max - absolute_min) / (absolute_min * 0.01))
#
# # Niveaux de prix à 1%, 2%, ..., steps%
# levels = [absolute_min * (1 + i / 100) for i in range(1, steps + 1)]
# levels = [lvl for lvl in levels if lvl < absolute_max] # évite le dernier niveau exact
#
# # ajout dans le DataFrame
# for i, lvl in enumerate(levels, start=1):
# dataframe[f"lvl_{i}_pct"] = lvl
# # Indices correspondants
# indices = [(dataframe['mid'] - lvl).abs().idxmin() for lvl in levels]
return dataframe
def getOpenTrades(self):
@@ -464,25 +490,39 @@ class Frictrade(IStrategy):
return dataframe
# def adjust_stake_amount(self, pair: str, last_candle: DataFrame):
# # Calculer le minimum des 14 derniers jours
# nb_pairs = len(self.dp.current_whitelist())
#
# base_stake_amount = self.config.get('stake_amount')
#
# if True : #self.pairs[pair]['count_of_buys'] == 0:
# factor = 1 #65 / min(65, last_candle['rsi_1d'])
# # if last_candle['min_max_60'] > 0.04:
# # factor = 2
#
# adjusted_stake_amount = base_stake_amount #max(base_stake_amount / 5, base_stake_amount * factor)
# else:
# adjusted_stake_amount = self.pairs[pair]['first_amount']
#
# if self.pairs[pair]['count_of_buys'] == 0:
# self.pairs[pair]['first_amount'] = adjusted_stake_amount
#
# return adjusted_stake_amount
def adjust_stake_amount(self, pair: str, last_candle: DataFrame):
# Calculer le minimum des 14 derniers jours
nb_pairs = len(self.dp.current_whitelist())
# Calcule max/min 180
low180 = last_candle["min180"]
high180 = last_candle["max180"]
base_stake_amount = self.config.get('stake_amount')
mult = 1 - ((last_candle["mid"] - low180) / (high180 - low180))
if True : #self.pairs[pair]['count_of_buys'] == 0:
factor = 1 #65 / min(65, last_candle['rsi_1d'])
# if last_candle['min_max_60'] > 0.04:
# factor = 2
adjusted_stake_amount = base_stake_amount #max(base_stake_amount / 5, base_stake_amount * factor)
else:
adjusted_stake_amount = self.pairs[pair]['first_amount']
if self.pairs[pair]['count_of_buys'] == 0:
self.pairs[pair]['first_amount'] = adjusted_stake_amount
return adjusted_stake_amount
print(f"low={low180} mid={last_candle['mid']} high={high180} mult={mult}")
# base_size = montant de base que tu veux utiliser (ex: stake_amount ou autre)
base_size = 2 * self.config.get('stake_amount') # exemple fraction du portefeuille; adapte selon ton code
# new stake proportionnel à mult
new_stake = base_size * mult
return new_stake
def adjust_trade_position(self, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, min_stake: float,
@@ -544,10 +584,9 @@ class Frictrade(IStrategy):
# stake_amount = last_amount * current_rate * 0.5
# return stake_amount
condition = last_candle['hapercent'] > 0
condition = last_candle['hapercent'] > 0 and last_candle['sma60_deriv1'] > 0
limit_buy = 40
if decline >= dca_threshold:
if decline >= dca_threshold and condition:
try:
if self.pairs[pair]['has_gain'] and profit > 0:
self.pairs[pair]['force_sell'] = True
@@ -594,7 +633,8 @@ class Frictrade(IStrategy):
self.printLog(exception)
return None
if (increase >= dca_threshold and self.wallets.get_available_stake_amount() > 0):
if current_profit > 0 and (increase >= dca_threshold and self.wallets.get_available_stake_amount() > 0) \
and (last_candle['max_rsi_24'] < 60):
try:
self.pairs[pair]['previous_profit'] = profit
stake_amount = min(self.wallets.get_available_stake_amount(), self.adjust_stake_amount(pair, last_candle))
@@ -649,8 +689,17 @@ class Frictrade(IStrategy):
count_of_buys = trade.nr_of_successful_entries
profit = trade.calc_profit(current_rate) #round(current_profit * trade.stake_amount, 1)
if current_profit > 0:
self.pairs[pair]['max_profit'] = max(self.pairs[pair]['max_profit'], profit)
# else:
# self.pairs[pair]['max_profit'] = 0
max_profit = self.pairs[pair]['max_profit']
# if current_profit > 0:
# print(f"profit={profit} max_profit={max_profit} current_profit={current_profit}")
baisse = 0
if profit > 0:
baisse = 1 - (profit / max_profit)
@@ -668,11 +717,14 @@ class Frictrade(IStrategy):
self.pairs[pair]['max_touch'] = max(last_candle['close'], self.pairs[pair]['max_touch'])
# ----- 3) Calcul du profit max atteint -----
profit_max = (max_price - trade.open_rate) / trade.open_rate
# profit_max = (max_price - trade.open_rate) / trade.open_rate
# ----- 5) Calcul du trailing stop dynamique -----
# Exemple : offset=0.321 => stop à +24.8%
trailing_stop = max_price * (1 - self.trailing_stop_positive)
trailing_stop = max_profit * (1.0 - self.trailing_stop_positive)
baisse = 0
if max_profit:
baisse = (max_profit - profit) / max_profit
if minutes % 15 == 0:
self.log_trade(
@@ -682,7 +734,7 @@ class Frictrade(IStrategy):
dispo=dispo,
pair=pair,
rate=last_candle['close'],
trade_type=f"{round(profit_max * 100, 2)} - {round(trailing_stop,0)}",
trade_type=f"{round(profit, 2)} {round(max_profit, 2)} {round(trailing_stop,2)}",
profit=round(profit, 2),
buys=count_of_buys,
stake=0
@@ -690,12 +742,14 @@ class Frictrade(IStrategy):
# ----- 4) OFFSET : faut-il attendre de dépasser trailing_stop_positive_offset ? -----
if self.trailing_only_offset_is_reached:
if profit_max < self.trailing_stop_positive_offset:
# Max profit pas atteint ET perte < 2 * self.trailing_stop_positive
if max_profit < min(2, self.trailing_stop_positive_offset * (count_of_buys - self.pairs[pair]['has_gain']))\
and (baisse < 0.5 and max_profit > self.trailing_stop_positive_offset): #2 * self.trailing_stop_positive:
return None # ne pas activer le trailing encore
# Sinon : trailing actif dès le début
# ----- 6) Condition de vente -----
if current_rate <= trailing_stop and self.wallets.get_available_stake_amount() < 300:
if profit > 0 and profit <= trailing_stop:
return f"stop_{count_of_buys}"
return None