Frictrade

This commit is contained in:
Jérôme Delacotte
2025-11-26 18:26:54 +01:00
parent 51ca009751
commit a7b09858f4

View File

@@ -343,7 +343,9 @@ class Frictrade(IStrategy):
f"| {date:<16} |{action:<10} | {pair[0:3]:<3} | {trade_type or '-':<18} |{rate or '-':>9}| {dispo or '-':>6} " f"| {date:<16} |{action:<10} | {pair[0:3]:<3} | {trade_type or '-':<18} |{rate or '-':>9}| {dispo or '-':>6} "
f"|{color}{profit or '-':>10}{RESET}| {pct_max or '-':>6} | {round(self.pairs[pair]['max_touch'], 2) or '-':>11} | {last_lost or '-':>12} " f"|{color}{profit or '-':>10}{RESET}| {pct_max or '-':>6} | {round(self.pairs[pair]['max_touch'], 2) or '-':>11} | {last_lost or '-':>12} "
f"| {last_max or '-':>7} | {last_min or '-':>7} |{total_counts or '-':>5}|{stake or '-':>7}" f"| {last_max or '-':>7} | {last_min or '-':>7} |{total_counts or '-':>5}|{stake or '-':>7}"
f"{round(last_candle['max_rsi_24'], 1) or '-' :>6}|" f"{round(last_candle['max_rsi_24'], 1) or '-' :>6}|{round(last_candle['rsi_1h'], 1) or '-' :>6}|{round(last_candle['rsi_1d'], 1) or '-' :>6}|"
f"{round(last_candle['rtp_1h'] * 100, 0) or '-' :>6}|{round(last_candle['rtp_1d'] * 100, 0) or '-' :>6}|"
) )
def printLineLog(self): def printLineLog(self):
@@ -404,11 +406,22 @@ class Frictrade(IStrategy):
dataframe['min180'] = talib.MIN(dataframe['mid'], timeperiod=180) dataframe['min180'] = talib.MIN(dataframe['mid'], timeperiod=180)
dataframe['max180'] = talib.MAX(dataframe['mid'], timeperiod=180) dataframe['max180'] = talib.MAX(dataframe['mid'], timeperiod=180)
# # ################### INFORMATIVE 1h # ################### INFORMATIVE 1h
# informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1h') informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1h')
informative['mid'] = informative['open'] + (informative['close'] - informative['open']) / 2
# informative = self.populate1hIndicators(df=informative, metadata=metadata) # informative = self.populate1hIndicators(df=informative, metadata=metadata)
# # informative = self.calculateRegression(informative, 'mid', lookback=15) informative['rsi'] = talib.RSI(informative['mid'], timeperiod=14)
# dataframe = merge_informative_pair(dataframe, informative, '1m', '1h', ffill=True) informative = self.rsi_trend_probability(informative)
# informative = self.calculateRegression(informative, 'mid', lookback=15)
dataframe = merge_informative_pair(dataframe, informative, '1m', '1h', ffill=True)
# ################### INFORMATIVE 1d
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1d')
informative['mid'] = informative['open'] + (informative['close'] - informative['open']) / 2
informative['rsi'] = talib.RSI(informative['mid'], timeperiod=5)
informative = self.rsi_trend_probability(informative)
# informative = self.calculateRegression(informative, 'mid', lookback=15)
dataframe = merge_informative_pair(dataframe, informative, '1m', '1d', ffill=True)
dataframe['last_price'] = dataframe['close'] dataframe['last_price'] = dataframe['close']
dataframe['first_price'] = dataframe['close'] dataframe['first_price'] = dataframe['close']
@@ -439,10 +452,16 @@ class Frictrade(IStrategy):
self.pairs[pair]['total_amount'] = amount self.pairs[pair]['total_amount'] = amount
dataframe['absolute_min'] = dataframe['mid'].rolling(1440, min_periods=1).min() dataframe['absolute_min'] = dataframe['mid'].rolling(1440, min_periods=1).min()
for i in [1, 2, 3, 4]: dataframe['absolute_max'] = dataframe['mid'].rolling(1440, min_periods=1).max()
# steps = (dataframe['absolute_max'] - dataframe['absolute_min']) / (dataframe['absolute_min'] * 0.01)
# levels = [dataframe['absolute_min'] * (1 + i / 100) for i in range(1, steps + 1)]
#
# print(levels)
# print(f"min={dataframe['absolute_min'].min()} max={dataframe['absolute_max'].max()}")
for i in [0, 1, 2, 3]:
dataframe[f"lvl_{i}_pct"] = dataframe['absolute_min'] * (1 + 0.01 * i) 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_min = dataframe['absolute_min'].min()
# absolute_max = dataframe['absolute_max'].max() # absolute_max = dataframe['absolute_max'].max()
@@ -475,6 +494,7 @@ class Frictrade(IStrategy):
dataframe.loc[ dataframe.loc[
( (
(dataframe['sma5_inv'] == 1) (dataframe['sma5_inv'] == 1)
# & (dataframe['max_rsi_24'] < 80)
# & ( # & (
# (dataframe['percent3'] <= -0.003) # (dataframe['percent3'] <= -0.003)
# | (dataframe['percent12'] <= -0.003) # | (dataframe['percent12'] <= -0.003)
@@ -719,9 +739,26 @@ class Frictrade(IStrategy):
# ----- 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
current_trailing_stop_positive = self.trailing_stop_positive
current_trailing_only_offset_is_reached = self.trailing_only_offset_is_reached
current_trailing_stop_positive_offset = self.trailing_stop_positive_offset
max_ = last_candle['max180']
min_ = last_candle['min180']
mid = last_candle['mid']
# éviter division par zéro
position = (mid - min_) / (max_ - min_)
zone = int(position * 3) # 0 à 2
if zone == 0:
current_trailing_stop_positive = True
current_trailing_stop_positive_offset = self.trailing_stop_positive_offset * 2
# if zone == 1:
# ----- 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_profit * (1.0 - self.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
@@ -741,10 +778,10 @@ 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 current_trailing_only_offset_is_reached:
# Max profit pas atteint ET perte < 2 * self.trailing_stop_positive # Max profit pas atteint ET perte < 2 * current_trailing_stop_positive
if max_profit < min(2, self.trailing_stop_positive_offset * (count_of_buys - self.pairs[pair]['has_gain']))\ if max_profit < min(2, current_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: and (baisse < 0.5 and max_profit > current_trailing_stop_positive_offset): #2 * current_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
@@ -757,7 +794,7 @@ class Frictrade(IStrategy):
# get access to all pairs available in whitelist. # get access to all pairs available in whitelist.
pairs = self.dp.current_whitelist() pairs = self.dp.current_whitelist()
informative_pairs = [(pair, '1h') for pair in pairs] informative_pairs = [(pair, '1h') for pair in pairs]
# informative_pairs += [(pair, '1d') for pair in pairs] informative_pairs += [(pair, '1d') for pair in pairs]
return informative_pairs return informative_pairs
@@ -825,3 +862,23 @@ class Frictrade(IStrategy):
# #
# return df # return df
def rsi_trend_probability(self, dataframe):
dataframe = dataframe.copy()
dataframe['rsi14'] = talib.RSI(dataframe['mid'], 14)
dataframe['rsi60'] = talib.RSI(dataframe['mid'], 60)
dataframe['cross_soft'] = np.tanh((dataframe['rsi14'] - dataframe['rsi60']) / 7)
dataframe['gap'] = (dataframe['rsi14'] - dataframe['rsi60']) / 100
dataframe['trend'] = (dataframe['rsi60'] - 50) / 50
dataframe['rtp'] = (
0.6 * dataframe['cross_soft'] +
0.25 * dataframe['gap'] +
0.15 * dataframe['trend']
).clip(-1, 1)
return dataframe