Frictrade
This commit is contained in:
112
Frictrade.py
112
Frictrade.py
@@ -56,10 +56,10 @@ class Frictrade(IStrategy):
|
|||||||
# Custom stoploss
|
# Custom stoploss
|
||||||
use_custom_stoploss = False
|
use_custom_stoploss = False
|
||||||
|
|
||||||
trailing_stop = True
|
trailing_stop = False
|
||||||
trailing_stop_positive = 0.15
|
trailing_stop_positive = 0.15
|
||||||
trailing_stop_positive_offset = 0.1
|
trailing_stop_positive_offset = 0.5
|
||||||
trailing_only_offset_is_reached = False
|
trailing_only_offset_is_reached = True
|
||||||
|
|
||||||
# Buy hypers
|
# Buy hypers
|
||||||
timeframe = '1m'
|
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_count_of_buys'] = trade.nr_of_successful_entries # self.pairs[pair]['count_of_buys']
|
||||||
self.pairs[pair]['last_sell'] = rate
|
self.pairs[pair]['last_sell'] = rate
|
||||||
self.pairs[pair]['last_candle'] = last_candle
|
self.pairs[pair]['last_candle'] = last_candle
|
||||||
self.pairs[pair]['max_profit'] = 0
|
|
||||||
self.pairs[pair]['previous_profit'] = 0
|
self.pairs[pair]['previous_profit'] = 0
|
||||||
self.trades = list()
|
self.trades = list()
|
||||||
dispo = round(self.wallets.get_available_stake_amount())
|
dispo = round(self.wallets.get_available_stake_amount())
|
||||||
@@ -185,6 +184,7 @@ class Frictrade(IStrategy):
|
|||||||
dispo=dispo,
|
dispo=dispo,
|
||||||
profit=round(profit, 2)
|
profit=round(profit, 2)
|
||||||
)
|
)
|
||||||
|
self.pairs[pair]['max_profit'] = 0
|
||||||
self.pairs[pair]['force_sell'] = False
|
self.pairs[pair]['force_sell'] = False
|
||||||
self.pairs[pair]['has_gain'] = 0
|
self.pairs[pair]['has_gain'] = 0
|
||||||
self.pairs[pair]['current_profit'] = 0
|
self.pairs[pair]['current_profit'] = 0
|
||||||
@@ -438,6 +438,32 @@ class Frictrade(IStrategy):
|
|||||||
count_buys = count
|
count_buys = count
|
||||||
self.pairs[pair]['total_amount'] = amount
|
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
|
return dataframe
|
||||||
|
|
||||||
def getOpenTrades(self):
|
def getOpenTrades(self):
|
||||||
@@ -464,25 +490,39 @@ class Frictrade(IStrategy):
|
|||||||
|
|
||||||
return dataframe
|
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):
|
def adjust_stake_amount(self, pair: str, last_candle: DataFrame):
|
||||||
# Calculer le minimum des 14 derniers jours
|
# Calcule max/min 180
|
||||||
nb_pairs = len(self.dp.current_whitelist())
|
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:
|
print(f"low={low180} mid={last_candle['mid']} high={high180} mult={mult}")
|
||||||
factor = 1 #65 / min(65, last_candle['rsi_1d'])
|
# base_size = montant de base que tu veux utiliser (ex: stake_amount ou autre)
|
||||||
# if last_candle['min_max_60'] > 0.04:
|
base_size = 2 * self.config.get('stake_amount') # exemple fraction du portefeuille; adapte selon ton code
|
||||||
# factor = 2
|
# new stake proportionnel à mult
|
||||||
|
new_stake = base_size * mult
|
||||||
adjusted_stake_amount = base_stake_amount #max(base_stake_amount / 5, base_stake_amount * factor)
|
return new_stake
|
||||||
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_trade_position(self, trade: Trade, current_time: datetime,
|
def adjust_trade_position(self, trade: Trade, current_time: datetime,
|
||||||
current_rate: float, current_profit: float, min_stake: float,
|
current_rate: float, current_profit: float, min_stake: float,
|
||||||
@@ -544,10 +584,9 @@ class Frictrade(IStrategy):
|
|||||||
# stake_amount = last_amount * current_rate * 0.5
|
# stake_amount = last_amount * current_rate * 0.5
|
||||||
# return stake_amount
|
# return stake_amount
|
||||||
|
|
||||||
|
condition = last_candle['hapercent'] > 0 and last_candle['sma60_deriv1'] > 0
|
||||||
condition = last_candle['hapercent'] > 0
|
|
||||||
limit_buy = 40
|
limit_buy = 40
|
||||||
if decline >= dca_threshold:
|
if decline >= dca_threshold and condition:
|
||||||
try:
|
try:
|
||||||
if self.pairs[pair]['has_gain'] and profit > 0:
|
if self.pairs[pair]['has_gain'] and profit > 0:
|
||||||
self.pairs[pair]['force_sell'] = True
|
self.pairs[pair]['force_sell'] = True
|
||||||
@@ -594,7 +633,8 @@ class Frictrade(IStrategy):
|
|||||||
self.printLog(exception)
|
self.printLog(exception)
|
||||||
return None
|
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:
|
try:
|
||||||
self.pairs[pair]['previous_profit'] = profit
|
self.pairs[pair]['previous_profit'] = profit
|
||||||
stake_amount = min(self.wallets.get_available_stake_amount(), self.adjust_stake_amount(pair, last_candle))
|
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
|
count_of_buys = trade.nr_of_successful_entries
|
||||||
|
|
||||||
profit = trade.calc_profit(current_rate) #round(current_profit * trade.stake_amount, 1)
|
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)
|
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']
|
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
|
baisse = 0
|
||||||
if profit > 0:
|
if profit > 0:
|
||||||
baisse = 1 - (profit / max_profit)
|
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'])
|
self.pairs[pair]['max_touch'] = max(last_candle['close'], self.pairs[pair]['max_touch'])
|
||||||
|
|
||||||
# ----- 3) Calcul du profit max atteint -----
|
# ----- 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 -----
|
# ----- 5) Calcul du trailing stop dynamique -----
|
||||||
# Exemple : offset=0.321 => stop à +24.8%
|
# 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:
|
if minutes % 15 == 0:
|
||||||
self.log_trade(
|
self.log_trade(
|
||||||
@@ -682,7 +734,7 @@ class Frictrade(IStrategy):
|
|||||||
dispo=dispo,
|
dispo=dispo,
|
||||||
pair=pair,
|
pair=pair,
|
||||||
rate=last_candle['close'],
|
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),
|
profit=round(profit, 2),
|
||||||
buys=count_of_buys,
|
buys=count_of_buys,
|
||||||
stake=0
|
stake=0
|
||||||
@@ -690,12 +742,14 @@ class Frictrade(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 self.trailing_only_offset_is_reached:
|
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
|
return None # ne pas activer le trailing encore
|
||||||
# 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 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 f"stop_{count_of_buys}"
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user