Compare commits

...

5 Commits

Author SHA1 Message Date
Jérôme Delacotte
a925a28389 TEST Learning 2026-04-08 21:46:21 +02:00
Jérôme Delacotte
3302266b4a TEST SHORT 2026-04-02 20:17:55 +02:00
Jérôme Delacotte
7954c518bd ┏━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃   Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃   Avg Duration ┃  Win  Draw  Loss  Win% ┃            Drawdown ┃
┡━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ EmptyShort │     54 │         0.75 │         422.136 │        42.21 │ 1 day, 5:07:00 │   25     0    29  46.3 │ 142.938 USDT  9.86% │
└────────────┴────────┴──────────────┴─────────────────┴──────────────┴────────────────┴────────────────────────┴─────────────────────┘
2026-03-29 23:32:09 +02:00
Jérôme Delacotte
a599160501 ┏━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
┃   Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃    Avg Duration ┃  Win  Draw  Loss  Win% ┃           Drawdown ┃
┡━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩
│ EmptyShort │     34 │         1.08 │         379.432 │        37.94 │ 1 day, 10:30:00 │   18     0    16  52.9 │ 81.299 USDT  6.08% │
└────────────┴────────┴──────────────┴─────────────────┴──────────────┴─────────────────┴────────────────────────┴────────────────────┘
2026-03-29 18:16:38 +02:00
Jérôme Delacotte
8b030f46f0 TEST SHORT 2026-03-28 21:51:37 +01:00
5 changed files with 2051 additions and 615 deletions

View File

@@ -4,9 +4,6 @@
"roi": {
"0": 5
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": null,
@@ -25,8 +22,11 @@
"protection": {
"drop_from_last_entry": 0.0,
"mises_bull": 4
},
"stoploss": {
"stoploss": -0.02
}
},
"ft_stratparam_v": 1,
"export_time": "2026-03-07 20:20:17.895644+00:00"
"export_time": "2026-03-29 18:29:54.986316+00:00"
}

View File

@@ -103,7 +103,7 @@ class EmptyShort(IStrategy):
# trailing_only_offset_is_reached = False
position_adjustment_enable = True
use_custom_stoploss = True
use_custom_stoploss = False
#max_open_trades = 3
@@ -373,24 +373,25 @@ class EmptyShort(IStrategy):
last_candle_2 = dataframe.iloc[-2].squeeze()
last_candle_3 = dataframe.iloc[-3].squeeze()
if entry_tag == 'Range-':
self.pairs[pair]['count_of_lost'] = 0
if entry_tag == 'Force':
if self.pairs[pair]['count_of_lost'] >= 1:
self.pairs[pair]['count_of_lost'] = 0
condition = False
else:
condition = False if self.pairs[pair]['count_of_lost'] >= 1 \
and (last_candle['sma12_deriv1_1h'] < 0.00) \
and entry_tag != 'dist' else True
reason = ''
if not condition:
reason = 'lost'
if condition:
if last_candle['range_pos'] > 0.05:# and self.pairs[pair]['force_stop']:
condition = last_candle['sma5'] > last_candle['sma60']
if not condition:
reason = 'range'
condition = True
# if entry_tag == 'Range-':
# self.pairs[pair]['count_of_lost'] = 0
# if entry_tag == 'Force':
# if self.pairs[pair]['count_of_lost'] >= 1:
# self.pairs[pair]['count_of_lost'] = 0
# condition = False
# else:
# condition = False if self.pairs[pair]['count_of_lost'] >= 1 \
# and (last_candle['sma12_deriv1_1h'] < 0.00) \
# and entry_tag != 'dist' else True
# reason = ''
# if not condition:
# reason = 'lost'
# if condition:
# if last_candle['range_pos'] > 0.05:# and self.pairs[pair]['force_stop']:
# condition = last_candle['sma5'] > last_candle['sma60']
# if not condition:
# reason = 'range'
# if self.pairs[pair]['force_stop'] and last_candle['range_pos'] < 0.02:
# self.pairs[pair]['force_stop'] = False
@@ -458,7 +459,7 @@ class EmptyShort(IStrategy):
self.log_trade(
last_candle=last_candle,
date=current_time,
action=("🟩Buy" if allow_to_buy else "Canceled") + " " + str(minutes),
action=("🟩Buy") + " " + str(minutes),
pair=pair,
rate=rate,
dispo=dispo,
@@ -471,7 +472,7 @@ class EmptyShort(IStrategy):
self.log_trade(
last_candle=last_candle,
date=current_time,
action=("🟩Buy" if allow_to_buy else "Canceled") + " " + reason,
action=("Canceled") + " " + reason,
pair=pair,
rate=rate,
dispo=dispo,
@@ -493,7 +494,7 @@ class EmptyShort(IStrategy):
profit = trade.calc_profit(rate)
force = self.pairs[pair]['force_sell']
allow_to_sell = (last_candle['hapercent'] < 0 and profit > 0) or force \
or (trade.enter_tag == 'short' ) or (exit_reason == 'force_exit') or (exit_reason == 'stop_loss') or (exit_reason == 'trailing_stop_loss')
or (trade.is_short) or (exit_reason == 'force_exit') or (exit_reason == 'stop_loss') or (exit_reason == 'trailing_stop_loss')
minutes = int(round((current_time - trade.date_last_filled_utc).total_seconds() / 60, 0))
@@ -561,21 +562,28 @@ class EmptyShort(IStrategy):
dispo = round(self.wallets.get_available_stake_amount() + self.pairs[pair]['total_amount'])
is_short = (trade.enter_tag == 'short')
if trade.enter_tag == 'short':
tp_price = self.pairs[pair]['take_profit']
if trade.is_short:
tp_price = max(0.02, self.pairs[pair]['take_profit'])
# if current_profit < self.sell_force_sell.value \
# and last_candle[f"close"] > last_candle[self.sell_indicator.value]:
# self.pairs[pair]['force_sell'] = True
# return 'sma'
#
if current_profit > tp_price and \
(baisse > self.baisse.value and last_candle[f"close"] > last_candle[self.b30_indicateur.value]) \
and last_candle['hapercent'] > 0:
(baisse > last_candle[f"range_pos"] and last_candle[f"close"] > last_candle[self.b30_indicateur.value]) \
and last_candle['hapercent'] > 0: # and last_candle['sma12_deriv2_1h'] > 0.0:
self.pairs[pair]['force_sell'] = True
return 'B30Sht'
return None
# if current_profit < - 0.01 and last_candle['sma60_deriv1'] > 0 and last_candle['sma60_deriv2'] > 0:
# self.pairs[pair]['force_sell'] = True
# return 'StpSht'
# if last_candle['sma12_inv_1h'] == -1:
# return 'InvSht'
# return None
# self.log_trade(
# last_candle=last_candle,
# date=current_time,
@@ -598,12 +606,12 @@ class EmptyShort(IStrategy):
# and last_candle[f"close"] <= last_candle[self.sell_indicator.value]:
# self.pairs[pair]['force_sell'] = True
# return 'sma'
if current_profit > 0.00 and \
(baisse > self.baisse.value and last_candle[f"close"] <= last_candle[self.b30_indicateur.value]) \
and last_candle['hapercent'] <0 :
if current_profit > 0.01:
self.pairs[pair]['force_buy'] = True
tp_price = max(0.02, self.pairs[pair]['take_profit'])
if current_profit > tp_price and \
(baisse > min(last_candle[f"range_pos"], 0.5) and last_candle[f"close"] <= last_candle[self.b30_indicateur.value]) \
and last_candle['hapercent'] <0 : #and last_candle['sma12_deriv1_1h'] < 0.004:
# if current_profit > 0.01:
# self.pairs[pair]['force_buy'] = True
self.pairs[pair]['force_sell'] = True
return 'B30'
@@ -611,9 +619,9 @@ class EmptyShort(IStrategy):
# self.pairs[pair]['force_sell'] = True
# return 'B50'
if current_profit > - self.sell_force_sell.value and last_candle['has_cross_sma3_1h'] == 1:
self.pairs[pair]['force_sell'] = True
return 'Cross'
# if current_profit > - self.sell_force_sell.value and last_candle['has_cross_sma3_1h'] == 1:
# self.pairs[pair]['force_sell'] = True
# return 'Cross'
# if profit > max(5, expected_profit) and last_candle['sma5_deriv1_1h'] < 0 and baisse > 0.15:
# self.pairs[pair]['force_sell'] = True
@@ -654,41 +662,41 @@ class EmptyShort(IStrategy):
return None
def custom_stoploss(self, pair, trade, current_time, current_rate, current_profit, **kwargs):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1]
profit = trade.calc_profit(current_rate)
candle_at_buy = self.pairs[pair]['last_candle']
# if candle_at_buy['range_pos'] > self.range_pos_stoploss.value and candle_at_buy[self.stoploss_indicator.value] < 0:
# return self.stoploss_force.value
# # print(f'test stop loss {self.stoploss} {last_candle["stop_buying12_1h"]}')
# if last_candle[self.stoploss_indicator.value] and (trade.nr_of_successful_entries >= 4 or self.wallets.get_available_stake_amount() < 300): # and profit < - 30 :
# range_min = last_candle[f"min{self.stoploss_timeperiod.value}_1h"]
# range_max = last_candle[f"max{self.stoploss_timeperiod.value}_1h"]
# def custom_stoploss(self, pair, trade, current_time, current_rate, current_profit, **kwargs):
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# last_candle = dataframe.iloc[-1]
# profit = trade.calc_profit(current_rate)
#
# if range_max == range_min:
# print(f'ranges={range_min}')
# return -0.1 # sécurité
# candle_at_buy = self.pairs[pair]['last_candle']
#
# range_pos = (current_rate - range_min) / (range_max - range_min)
# # if candle_at_buy['range_pos'] > self.range_pos_stoploss.value and candle_at_buy[self.stoploss_indicator.value] < 0:
# # return self.stoploss_force.value
#
# # # print(f'test stop loss {self.stoploss} {last_candle["stop_buying12_1h"]}')
# # if last_candle[self.stoploss_indicator.value] and (trade.nr_of_successful_entries >= 4 or self.wallets.get_available_stake_amount() < 300): # and profit < - 30 :
# # range_min = last_candle[f"min{self.stoploss_timeperiod.value}_1h"]
# # range_max = last_candle[f"max{self.stoploss_timeperiod.value}_1h"]
# #
# # if range_max == range_min:
# # print(f'ranges={range_min}')
# # return -0.1 # sécurité
# #
# # range_pos = (current_rate - range_min) / (range_max - range_min)
# #
# # if (range_pos > 1):
# # return -1
# #
# # sl_min = -0.02
# # sl_max = -0.1 #self.stoploss
# #
# # dynamic_sl = (sl_min + (1 - range_pos) * (sl_max - sl_min))
# #
# # print(f'{current_time} Loss ranges={round(range_min,0)} {round(range_max, 0)} range_pos={round(range_pos, 3)} dynamic_sl={round(dynamic_sl, 3)} '
# # f'profit={profit} current={current_profit} {self.stoploss_indicator.value} {self.stoploss_timeperiod.value} {last_candle[self.stoploss_indicator.value]}')
# #
# # return dynamic_sl
#
# if (range_pos > 1):
# return -1
#
# sl_min = -0.02
# sl_max = -0.1 #self.stoploss
#
# dynamic_sl = (sl_min + (1 - range_pos) * (sl_max - sl_min))
#
# print(f'{current_time} Loss ranges={round(range_min,0)} {round(range_max, 0)} range_pos={round(range_pos, 3)} dynamic_sl={round(dynamic_sl, 3)} '
# f'profit={profit} current={current_profit} {self.stoploss_indicator.value} {self.stoploss_timeperiod.value} {last_candle[self.stoploss_indicator.value]}')
#
# return dynamic_sl
return -1
def informative_pairs(self):
# get access to all pairs available in whitelist.
@@ -734,6 +742,10 @@ class EmptyShort(IStrategy):
dataframe["volume_mean"] = dataframe["volume"].rolling(20).mean()
dataframe["volume_ratio"] = dataframe["volume"] / dataframe["volume_mean"]
dataframe['volume2'] = dataframe['volume']
dataframe.loc[dataframe['hapercent'] < 0, 'volume2'] *= -1
dataframe['volume_spike'] = (abs(dataframe['volume2']) > abs(dataframe['volume2'].rolling(window=20).mean() * 5)) \
& (dataframe['volume'].rolling(window=5).max() > 1000)
dataframe["market_state"] = 0
@@ -751,7 +763,7 @@ class EmptyShort(IStrategy):
informative['haclose'] = heikinashi['close']
informative['hapercent'] = (informative['haclose'] - informative['haopen']) / informative['haclose']
informative['mid'] = informative['open'] + (informative['close'] - informative['open']) / 2
for timeperiod in [3, 5, 12]:
for timeperiod in [3, 5, 12, 50, 200]:
informative[f'max{timeperiod}'] = talib.MAX(informative['close'], timeperiod=timeperiod)
informative[f'min{timeperiod}'] = talib.MIN(informative['close'], timeperiod=timeperiod)
# informative[f"range{timeperiod}"] = ((informative["close"] - informative[f'min{timeperiod}']) / (informative[f'max{timeperiod}'] - informative[f'min{timeperiod}']))
@@ -763,9 +775,9 @@ class EmptyShort(IStrategy):
informative = self.calculateRegression(informative, column='sma3', window=10, degree=1, future_offset=2)
informative = self.calculateRegression(informative, column='low', window=10, degree=1, future_offset=2)
for timeperiod in long_timeperiods:
informative[f"sma{timeperiod}"] = informative['mid'].ewm(span=timeperiod, adjust=False).mean()
self.calculeDerivees(informative, f"sma{timeperiod}", timeframe=self.timeframe, ema_period=timeperiod)
# for timeperiod in long_timeperiods:
# informative[f"sma{timeperiod}"] = informative['mid'].ewm(span=timeperiod, adjust=False).mean()
# self.calculeDerivees(informative, f"sma{timeperiod}", timeframe=self.timeframe, ema_period=timeperiod)
informative['rsi'] = talib.RSI(informative['close'], timeperiod=14)
self.calculeDerivees(informative, f"rsi", timeframe=self.timeframe, ema_period=14)
@@ -810,9 +822,9 @@ class EmptyShort(IStrategy):
informative[f"sma{timeperiod}"] = informative['mid'].ewm(span=timeperiod, adjust=False).mean()
self.calculeDerivees(informative, f"sma{timeperiod}", timeframe=self.timeframe, ema_period=timeperiod)
for timeperiod in long_timeperiods:
informative[f"sma{timeperiod}"] = informative['mid'].ewm(span=timeperiod, adjust=False).mean()
self.calculeDerivees(informative, f"sma{timeperiod}", timeframe=self.timeframe, ema_period=timeperiod)
# for timeperiod in long_timeperiods:
# informative[f"sma{timeperiod}"] = informative['mid'].ewm(span=timeperiod, adjust=False).mean()
# self.calculeDerivees(informative, f"sma{timeperiod}", timeframe=self.timeframe, ema_period=timeperiod)
informative['rsi'] = talib.RSI(informative['close'], timeperiod=14)
self.calculeDerivees(informative, f"rsi", timeframe=self.timeframe, ema_period=14)
@@ -840,10 +852,12 @@ class EmptyShort(IStrategy):
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True)
# ######################################################################################################
range_min = dataframe[f"min12_1h"]
range_max = dataframe[f"max48"]
range_min = dataframe[f"min12_1d"]
range_max = dataframe[f"max12_1d"]
dataframe[f"range_pos"] = ((dataframe['mid'] - range_min) / (range_max)).rolling(5).mean()
dataframe[f"range_pos"] = ((dataframe['mid'] - range_min) / (range_max - range_min)) #.rolling(5).mean()
dataframe['min_max_12_1d'] = ((range_max - dataframe['close']) / range_min)
dataframe['pct_min_max_12_1d'] = ((range_max - range_min) / range_min)
# dataframe['cross_sma60'] = qtpylib.crossed_below(dataframe[self.sell_sma_indicators.value], dataframe[self.sell_crossed_sma_indicators.value])
@@ -864,6 +878,8 @@ class EmptyShort(IStrategy):
# Compter les baisses / hausses consécutives
dataframe = self.calculateDownAndUp(dataframe, limit=0.0001)
dataframe['sma5_1h'] = dataframe['sma5_1h'].rolling(window=60).mean()
# récupérer le dernier trade fermé
trades = Trade.get_trades_proxy(pair=pair,is_open=False)
if trades:
@@ -875,297 +891,139 @@ class EmptyShort(IStrategy):
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
pair = metadata['pair']
conditions = list()
# #####################################################################################
# CA MONTE !!
# #####################################################################################
# conditions.append(dataframe[f"{self.start_bull_indicator.value}_deriv1_1h" ] > self.start_bull_deriv1.value)
# conditions.append(dataframe[f"{self.start_bull_indicator.value}_deriv2_1h"] > self.start_bull_deriv2.value)
# conditions.append(dataframe['sma12_deriv1'] > self.buy_deriv1_sma60.value)
# conditions.append(dataframe['sma5_deriv1_1h'] > self.buy_deriv1_sma5d.value)
# conditions.append(dataframe['sma12_deriv1_1h'] > self.buy_deriv1_sma12d.value)
# conditions.append(dataframe['sma36_deriv2'] > self.buy_deriv2_sma60.value)
# conditions.append(dataframe['sma5_deriv2_1h'] > self.buy_deriv2_sma5d.value)
# conditions.append(dataframe['sma12_deriv2_1h'] > self.buy_deriv2_sma12d.value)
conditions.append(dataframe['hapercent'] > 0)
# conditions.append(dataframe['percent12'] < 0.01)
# conditions.append(dataframe['percent5'] < 0.01)
# conditions.append(dataframe['max_rsi_24'] < 80)
# dynamic_rsi_threshold = 70 + 15 * np.tanh(dataframe["dist_sma200_1h"] * 5)
# conditions.append((dataframe['max_rsi_12_1h'] < dynamic_rsi_threshold))
# conditions.append(dataframe[f"close"] > dataframe['sma60'])
# conditions.append(((dataframe[f"range_pos"] < 0.05) ) | ((dataframe['sma12_deriv1'] > 0) & (dataframe['sma12_deriv2'] > 0)))
#
# conditions.append(
# (dataframe['close_1h'] > dataframe[f'sma{self.buy_longue.value}_1h'])
# | (dataframe['sma60_inv_1h'] == -1)
dataframe.loc[
(
# (dataframe['sma5_1h'] > dataframe['close'])
# & (dataframe['sma12_deriv1_1h'] > 0)
# & (dataframe['max_rsi_12'] > 45)
# & (
# (
# (dataframe['max_rsi_24_1h'] < 45) & (dataframe['range_pos'] < 0.3)
# | (dataframe['sma12_deriv1_1d'] > 0)
# )
# if conditions:
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'bull')
# #####################################################################################
# conditions = list()
# conditions.append(dataframe['dist_sma200_1h'] < -0.05)
# conditions.append(dataframe['sma12_inv'] == 1)
# # conditions.append(dataframe['sma100_deriv1_1h'] > 0)
# if conditions:
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'dist')
# #####################################################################################
# conditions = list()
# conditions.append(dataframe['close'] < dataframe['sma100_1h'])
# conditions.append(dataframe['mid_smooth12'] > dataframe['mid_smooth12'].shift(1))
# conditions.append(dataframe['sma100_deriv1_1h'] > 0)
# conditions.append(dataframe[f"range_pos"] < 0.01)
# if conditions:
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'dist')
# #####################################################################################
# CA BAISSE !!
# "buy": {
# "buy_deriv1_sma12d": 0.0,
# "buy_deriv1_sma5d": 0.0,
# "buy_deriv1_sma60": 0.003,
# "buy_deriv2_sma12d": -0.03,
# "buy_deriv2_sma5d": 0.0,
# "buy_deriv2_sma60": -0.002,
# "buy_longue": 200,
# "buy_longue_derive": "sma160_deriv1_1h"
# },
# "protection": {
# "drop_from_last_entry": -0.03,
# "b30_indicateur": "sma3",
# "baisse": 0.31
# },
# #####################################################################################
conditions = list()
# conditions.append(dataframe[f"{self.start_bull_indicator.value}_deriv1_1h" ] < self.start_bull_deriv1.value)
# conditions.append(dataframe[f"{self.start_bull_indicator.value}_deriv2_1h"] < self.start_bull_deriv2.value)
# conditions.append(dataframe[f"{self.start_bear_indicator.value}_deriv1_1h" ] > self.start_bear_deriv1.value)
# conditions.append(dataframe[f"{self.start_bear_indicator.value}_deriv2_1h"] > self.start_bear_deriv2.value)
# conditions.append(dataframe['sma12_deriv1'] > self.buy_deriv1_sma60.value)
# conditions.append(dataframe['sma5_deriv1_1h'] > self.buy_deriv1_sma5d.value)
# conditions.append(dataframe['sma12_deriv1_1h'] > self.buy_deriv1_sma12d.value)
#
# # conditions.append(dataframe['sma12_deriv2'] > -0.002)
# # conditions.append(dataframe['sma5_deriv2_1h'] > 0)
# # conditions.append(dataframe['sma12_deriv2_1h'] > -0.03)
#
# conditions.append(dataframe['hapercent'] > 0)
# # conditions.append(dataframe['percent12'] < 0.01)
# # conditions.append(dataframe['percent5'] < 0.01)
# conditions.append(dataframe['max_rsi_24'] < 80)
#
# dynamic_rsi_threshold = 70 + 15 * np.tanh(dataframe["dist_sma200_1h"] * 5)
# conditions.append((dataframe['max_rsi_12_1h'] < dynamic_rsi_threshold))
# conditions.append(dataframe[f"close"] > dataframe['sma60'])
# conditions.append(((dataframe[f"range_pos"] < 0.05) ) | ((dataframe['sma12_deriv1'] > 0) & (dataframe['sma12_deriv2'] > 0)))
#
# conditions.append(
# (dataframe['close_1h'] > dataframe[f'sma{self.buy_longue.value}_1h'])
# | (dataframe['sma60_inv_1h'] == -1)
# )
# if conditions:
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'bear')
# conditions = list()
# conditions.append(dataframe['close_1h'] < dataframe[f'sma{self.buy_longue.value}_1h'])
# conditions.append(dataframe['has_cross_min'].rolling(6).max() == 1)
# conditions.append(dataframe['mid_smooth5'] > dataframe['mid_smooth5'].shift(1))
# conditions.append(dataframe['hapercent'] > 0)
# conditions.append(dataframe['percent5'] < 0.01)
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'cross_min')
# conditions = list()
# conditions.append(dataframe['sma12_deriv1'] > 0.00)
# conditions.append(dataframe['sma60_deriv1'] > 0.0)
# conditions.append(dataframe['sma5_deriv1_1h'] > 0.0)
# conditions.append(dataframe['sma12_deriv1_1h'] > 0.0)
# conditions.append(dataframe['sma24_deriv1_1h'] > 0.0)
# conditions.append(dataframe['sma100_deriv1_1h'] > 0.0)
# conditions.append(dataframe[f"range_pos"] < 0.025)
# conditions.append(dataframe['sma12_deriv1_1h'] > 0.0)
# # conditions.append(dataframe['close_1h'] < dataframe[f'sma{self.buy_longue.value}_1h'])
# # conditions.append(dataframe['has_cross_min'].rolling(6).max() == 1)
# # conditions.append(dataframe['mid_smooth5'] > dataframe['mid_smooth5'].shift(1))
# conditions.append(dataframe['min12'] == dataframe['min12'].shift(3))
# conditions.append((dataframe['percent24'] < -0.025) | (dataframe['percent12'] < -0.025))
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'Rise')
# conditions = list()
# conditions.append(dataframe['has_cross_min_6'] == True)
# conditions.append(dataframe['min36'] == dataframe['min36'].shift(3))
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'Force')
conditions = list()
# conditions.append(dataframe['mid_regression'].shift(2) > dataframe['mid_regression'].shift(1))
# conditions.append(dataframe['mid_regression'].shift(1) < dataframe['mid_regression'])
conditions.append(dataframe['close'] <= dataframe['min12_1h'])
conditions.append(dataframe['min60'] == dataframe['min60'].shift(5))
conditions.append(dataframe['has_cross_min_6'] == 1)
conditions.append(dataframe['down_count'] <= 5)
conditions.append(dataframe['down_count'] <= 5)
# conditions.append(dataframe['sma12_deriv1'] >= 0)
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'Mid')
(dataframe['sma60_deriv1'] > 0)
& (dataframe['sma60_deriv2'] > 0)
# & (dataframe['sma5_deriv1_1h'] > 0)
& (dataframe['hapercent'] > 0)
& (dataframe['up_count'] >= 3)
& (dataframe['up_count'] <= 7)
# & (dataframe['open'] < dataframe['sma5_1h'] * 1.01)
),
['enter_long', 'enter_tag']
] = (1, 'long')
# dataframe.loc[
# (
# # (qtpylib.crossed_above(dataframe['sma60'], dataframe['mid_regression_1h']))
# (dataframe['rsi_1h'] <= 30)
# & (dataframe['min_rsi_12_1h'] == dataframe['rsi_1h'])
# # (dataframe['sma5_1h'] > dataframe['close'])
# (dataframe['sma60_deriv1'] < 0)
# & (dataframe['sma60_deriv2'] < 0)
# & (dataframe['sma12_deriv1_1h'] > 0)
# & (dataframe['volume_spike'] == 1)
# & (dataframe['down_count'] >= 3)
# & (dataframe['down_count'] < 15)
# & (dataframe['hapercent'] > 0)
# & (dataframe['sma60'] > dataframe['sma60'].shift(1))
# ),
# ['enter_long', 'enter_tag']
# ] = (1, 'long')
# ] = (1, 'long_spike')
dataframe.loc[
(
# (qtpylib.crossed_below(
# dataframe['sma60'],
# dataframe['mid_regression_1h'])
# ) &
(
# (dataframe['close'] > dataframe['max5_1h'])
# & (dataframe['sma12'] < dataframe['sma12'].shift(1))
# # & (dataframe['sma120_inv'] == 1)
# & (dataframe['close'] > dataframe['close_1h'])
# & (dataframe['close'] > dataframe['close_1d'])
# (dataframe['rsi_1h'] >= 65)
# & (dataframe['max_rsi_12_1h'] == dataframe['rsi_1h'])
# & (dataframe['hapercent'] < 0)
# & (dataframe['sma60'] < dataframe['sma60'].shift(1))
(dataframe['sma12_1h'] < dataframe['sma12_1h'].shift(61))
& (dataframe['close'] > dataframe['close_1d'])
)
# (dataframe['sma5_1h'] < dataframe['close'])
# & (dataframe['sma12_deriv1_1h'] < -0.0005)
# & (dataframe['max_rsi_12'] < 60)
# & (
# (
# (dataframe['max_rsi_24_1h'] > 60) & (dataframe['range_pos'] > 0.8)
# | (dataframe['sma12_deriv1_1d'] < -0.01)
# )
# )
(dataframe['sma60_deriv1'] < 0)
& (dataframe['sma60_deriv2'] < 0)
# & (dataframe['sma5_deriv1_1h'] < 0)
& (dataframe['hapercent'] < 0)
# & (dataframe['pct_min_max_12_1d'] > 0.04)
& (dataframe['down_count'] <= -3)
& (dataframe['down_count'] >= -7)
# & (dataframe['open'] > dataframe['sma5_1h'] * 1.01)
),
['enter_short', 'enter_tag']
] = (1, 'short')
# dataframe.loc[
# (
# (dataframe['close'] >= dataframe['max5_1h'])
# & (dataframe['close'] >= dataframe['max12_1d'])
# & (dataframe['sma12_1h'] <= dataframe['max12_1d'])
# & (dataframe['mid_1h'] <= dataframe['mid_1h'].shift(61))
# (dataframe['sma5_1h'] < dataframe['close'])
# & (dataframe['volume_spike'] == 1)
# & (dataframe['down_count'] <= -3)
# & (dataframe['down_count'] > -15)
# & (dataframe['hapercent'] < 0)
# # & (dataframe['sma60'] < dataframe['sma60'].shift(1))
# & (dataframe['sma60'] < dataframe['sma60'].shift(1))
# ),
# ['enter_short', 'enter_tag']
# ] = (1, 'short')
# ] = (1, 'short_spike')
dataframe['short'] = np.where(dataframe['enter_short'] == 1, dataframe['close'] * 0.99, np.nan)
dataframe['long'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.01, np.nan)
# no_trade = (
# # range
# (abs(dataframe['sma50_1h'] - dataframe['sma200_1h']) / dataframe['close'] < 0.002)
# # momentum faible
# | (abs(dataframe['sma12_deriv1']) < 0.0002)
# # RSI neutre
# | ((dataframe['rsi'] > 45) & (dataframe['rsi'] < 55))
# # faible volatilité
# | (dataframe['atr'] / dataframe['close'] < 0.003)
# # milieu de range
# | (dataframe['range_pos'].between(0.4, 0.6))
# )
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# # TODO: Its not dry code!
# sell_indicator = self.sell_indicator0.value
# sell_crossed_indicator = self.sell_crossed_indicator0.value
# sell_operator = self.sell_operator0.value
# sell_real_num = self.sell_real_num0.value
# condition, dataframe = condition_generator(
# dataframe,
# sell_operator,
# sell_indicator,
# sell_crossed_indicator,
# sell_real_num
# )
# conditions.append(condition)
#
# sell_indicator = self.sell_indicator1.value
# sell_crossed_indicator = self.sell_crossed_indicator1.value
# sell_operator = self.sell_operator1.value
# sell_real_num = self.sell_real_num1.value
# condition, dataframe = condition_generator(
# dataframe,
# sell_operator,
# sell_indicator,
# sell_crossed_indicator,
# sell_real_num
# )
# conditions.append(condition)
#
# sell_indicator = self.sell_indicator2.value
# sell_crossed_indicator = self.sell_crossed_indicator2.value
# sell_operator = self.sell_operator2.value
# sell_real_num = self.sell_real_num2.value
# condition, dataframe = condition_generator(
# dataframe,
# sell_operator,
# sell_indicator,
# sell_crossed_indicator,
# sell_real_num
# )
# conditions.append(condition)
#
#
# print(f"SELL indicators tested \n"
# f"{self.sell_indicator0.value} {self.sell_crossed_indicator0.value} {self.sell_operator0.value} {self.sell_real_num0.value} \n"
# f"{self.sell_indicator1.value} {self.sell_crossed_indicator1.value} {self.sell_operator1.value} {self.sell_real_num1.value} \n"
# f"{self.sell_indicator2.value} {self.sell_crossed_indicator2.value} {self.sell_operator2.value} {self.sell_real_num2.value} \n"
# )
#
#
# conditions.append(qtpylib.crossed_below(dataframe['mid'], dataframe['sma24']))
# conditions.append((dataframe['range_pos'] > 0.04))
#
# if conditions:
# dataframe.loc[reduce(lambda x, y: x & y, conditions), ['exit_long', 'exit_tag']] = (1, 'god')
# conditions = list()
# dataframe.loc[
# (
# # (qtpylib.crossed_above(
# # dataframe['sma'],
# # dataframe['mid_regression_1h'])
# # )
# (dataframe['rsi_1h'] >= 70)
# & (dataframe['max_rsi_12_1h'] == dataframe['rsi_1h'])
# # (dataframe['sma12_1h'] < dataframe['sma12_1h'].shift(61))
# # & (dataframe['range_pos'] > 0.5)
# # & (dataframe['close'] > dataframe['close_1d'])
# # & (dataframe['close'] > dataframe['close_1h'])
#
# (dataframe['sma12_deriv1_1h'] < -0.0005)
# # & (dataframe['max_rsi_12'] < 70)
# # & (dataframe['max_rsi_12_1h'] < 70)
# # & (dataframe['range_pos'] > 0.8)
# & (dataframe['hapercent'] < 0)
#
# ),
# ['exit_long', 'exit_tag']
# ] = (1, 'long')
dataframe.loc[
(
# (qtpylib.crossed_above(
# dataframe['sma'],
# dataframe['mid_regression_1h'])
# )
(dataframe['rsi_1h'] <= 30)
& (dataframe['min_rsi_12_1h'] == dataframe['rsi_1h'])
& (dataframe['hapercent'] > 0)
& (dataframe['sma60'] >= dataframe['sma60'].shift(1))
),
['exit_short', 'exit_tag']
] = (1, 'short')
#
# dataframe.loc[
# (
# # (qtpylib.crossed_above(
# # dataframe['sma'],
# # dataframe['mid_regression_1h'])
# # )
#
# # (dataframe['rsi_1h'] <= 30)
# # & (dataframe['min_rsi_12_1h'] == dataframe['rsi_1h'])
# # & (dataframe['hapercent'] > 0)
# # & (dataframe['sma60'] >= dataframe['sma60'].shift(1))
#
# (dataframe['sma12_deriv1_1h'] > 0.0005)
# # & (dataframe['max_rsi_12'] < 70)
# # & (dataframe['max_rsi_12_1h'] < 70)
# # & (dataframe['range_pos'] < 0.2)
# & (dataframe['hapercent'] > 0)
# ),
# ['exit_short', 'exit_tag']
# ] = (1, 'short')
return dataframe
@@ -1539,8 +1397,8 @@ class EmptyShort(IStrategy):
return df
def calculateDownAndUp(self, dataframe, limit=0.0001):
dataframe['down'] = dataframe['mid_regression'] <= dataframe['mid_regression'].shift(1)
dataframe['up'] = dataframe['mid_regression'] >= dataframe['mid_regression'].shift(1)
dataframe['down'] = dataframe['hapercent'] < 0
dataframe['up'] = dataframe['hapercent'] > 0
dataframe['down_count'] = - dataframe['down'].astype(int) * (
dataframe['down'].groupby((dataframe['down'] != dataframe['down'].shift()).cumsum()).cumcount() + 1)
dataframe['up_count'] = dataframe['up'].astype(int) * (

188
EmptyShort.txt Normal file
View File

@@ -0,0 +1,188 @@
BACKTESTING REPORT
┏━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Pair ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
┡━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ BTC/USDT:USDT │ 54 │ 0.75 │ 422.136 │ 42.21 │ 1 day, 5:07:00 │ 25 0 29 46.3 │
│ TOTAL │ 54 │ 0.75 │ 422.136 │ 42.21 │ 1 day, 5:07:00 │ 25 0 29 46.3 │
└───────────────┴────────┴──────────────┴─────────────────┴──────────────┴────────────────┴────────────────────────┘
LEFT OPEN TRADES REPORT
┏━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Pair ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
┡━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ TOTAL │ 0 │ 0.0 │ 0.000 │ 0.0 │ 0:00 │ 0 0 0 0 │
└───────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┘
ENTER TAG STATS
┏━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Enter Tag ┃ Entries ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
┡━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ short │ 28 │ 0.72 │ 211.154 │ 21.12 │ 19:27:00 │ 13 0 15 46.4 │
│ short_spike │ 25 │ 0.65 │ 174.806 │ 17.48 │ 1 day, 10:54:00 │ 11 0 14 44.0 │
│ long │ 1 │ 3.75 │ 36.176 │ 3.62 │ 6 days, 10:57:00 │ 1 0 0 100 │
│ TOTAL │ 54 │ 0.75 │ 422.136 │ 42.21 │ 1 day, 5:07:00 │ 25 0 29 46.3 │
└─────────────┴─────────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┘
EXIT REASON STATS
┏━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Exit Reason ┃ Exits ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
┡━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ B30Sht │ 24 │ 4.06 │ 1155.077 │ 115.51 │ 1 day, 10:30:00 │ 24 0 0 100 │
│ B30 │ 1 │ 3.75 │ 36.176 │ 3.62 │ 6 days, 10:57:00 │ 1 0 0 100 │
│ stop_loss │ 29 │ -2.1 │ -769.117 │ -76.91 │ 20:19:00 │ 0 0 29 0 │
│ TOTAL │ 54 │ 0.75 │ 422.136 │ 42.21 │ 1 day, 5:07:00 │ 25 0 29 46.3 │
└─────────────┴───────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┘
MIXED TAG STATS
┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Enter Tag ┃ Exit Reason ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ short │ B30Sht │ 13 │ 3.98 │ 601.641 │ 60.16 │ 1 day, 9:46:00 │ 13 0 0 100 │
│ short_spike │ B30Sht │ 11 │ 4.16 │ 553.436 │ 55.34 │ 1 day, 11:22:00 │ 11 0 0 100 │
│ long │ B30 │ 1 │ 3.75 │ 36.176 │ 3.62 │ 6 days, 10:57:00 │ 1 0 0 100 │
│ short_spike │ stop_loss │ 14 │ -2.1 │ -378.630 │ -37.86 │ 1 day, 10:32:00 │ 0 0 14 0 │
│ short │ stop_loss │ 15 │ -2.1 │ -390.487 │ -39.05 │ 7:03:00 │ 0 0 15 0 │
│ TOTAL │ │ 54 │ 0.75 │ 422.136 │ 42.21 │ 1 day, 5:07:00 │ 25 0 29 46.3 │
└─────────────┴─────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┘
DAY BREAKDOWN
┏━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Day ┃ Trades ┃ Tot Profit USDT ┃ Profit Factor ┃ Win Draw Loss Win% ┃
┡━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 07/01/2026 │ 1 │ 36.176 │ 0.0 │ 1 0 0 100 │
│ 08/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 09/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 10/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 11/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 12/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 13/01/2026 │ 1 │ -20.15 │ 0.0 │ 0 0 1 0 │
│ 14/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 15/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 16/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 17/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 18/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 19/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 20/01/2026 │ 1 │ 49.664 │ 0.0 │ 1 0 0 100 │
│ 21/01/2026 │ 1 │ 20.963 │ 0.0 │ 1 0 0 100 │
│ 22/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 23/01/2026 │ 1 │ -22.227 │ 0.0 │ 0 0 1 0 │
│ 24/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 25/01/2026 │ 1 │ 32.61 │ 0.0 │ 1 0 0 100 │
│ 26/01/2026 │ 1 │ -21.707 │ 0.0 │ 0 0 1 0 │
│ 27/01/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 28/01/2026 │ 1 │ -21.939 │ 0.0 │ 0 0 1 0 │
│ 29/01/2026 │ 1 │ 50.715 │ 0.0 │ 1 0 0 100 │
│ 30/01/2026 │ 1 │ -22.455 │ 0.0 │ 0 0 1 0 │
│ 31/01/2026 │ 1 │ 59.691 │ 0.0 │ 1 0 0 100 │
│ 01/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 02/02/2026 │ 3 │ -7.976 │ 0.83 │ 1 0 2 33.3 │
│ 03/02/2026 │ 1 │ 22.032 │ 0.0 │ 1 0 0 100 │
│ 04/02/2026 │ 1 │ 33.959 │ 0.0 │ 1 0 0 100 │
│ 05/02/2026 │ 1 │ 39.293 │ 0.0 │ 1 0 0 100 │
│ 06/02/2026 │ 4 │ 74.327 │ 1.89 │ 1 0 3 25.0 │
│ 07/02/2026 │ 2 │ 12.485 │ 1.46 │ 1 0 1 50.0 │
│ 08/02/2026 │ 2 │ -54.289 │ 0.0 │ 0 0 2 0 │
│ 09/02/2026 │ 2 │ -1.939 │ 0.93 │ 1 0 1 50.0 │
│ 10/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 11/02/2026 │ 4 │ 20.391 │ 1.38 │ 2 0 2 50.0 │
│ 12/02/2026 │ 1 │ 35.171 │ 0.0 │ 1 0 0 100 │
│ 13/02/2026 │ 1 │ -26.178 │ 0.0 │ 0 0 1 0 │
│ 14/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 15/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 16/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 17/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 18/02/2026 │ 1 │ 36.046 │ 0.0 │ 1 0 0 100 │
│ 19/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 20/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 21/02/2026 │ 1 │ -26.642 │ 0.0 │ 0 0 1 0 │
│ 22/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 23/02/2026 │ 1 │ 57.25 │ 0.0 │ 1 0 0 100 │
│ 24/02/2026 │ 2 │ 7.103 │ 1.25 │ 1 0 1 50.0 │
│ 25/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 26/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 27/02/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 28/02/2026 │ 1 │ 87.891 │ 0.0 │ 1 0 0 100 │
│ 01/03/2026 │ 1 │ -29.21 │ 0.0 │ 0 0 1 0 │
│ 02/03/2026 │ 1 │ -29.332 │ 0.0 │ 0 0 1 0 │
│ 03/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 04/03/2026 │ 2 │ -57.218 │ 0.0 │ 0 0 2 0 │
│ 05/03/2026 │ 1 │ -27.178 │ 0.0 │ 0 0 1 0 │
│ 06/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 07/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 08/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 09/03/2026 │ 1 │ 104.735 │ 0.0 │ 1 0 0 100 │
│ 10/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 11/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 12/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 13/03/2026 │ 1 │ -30.23 │ 0.0 │ 0 0 1 0 │
│ 14/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 15/03/2026 │ 1 │ -28.727 │ 0.0 │ 0 0 1 0 │
│ 16/03/2026 │ 1 │ -27.688 │ 0.0 │ 0 0 1 0 │
│ 17/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 18/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 19/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 20/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 21/03/2026 │ 1 │ 59.772 │ 0.0 │ 1 0 0 100 │
│ 22/03/2026 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
│ 23/03/2026 │ 1 │ -29.287 │ 0.0 │ 0 0 1 0 │
│ 24/03/2026 │ 1 │ 29.577 │ 0.0 │ 1 0 0 100 │
│ 25/03/2026 │ 1 │ -27.872 │ 0.0 │ 0 0 1 0 │
│ 26/03/2026 │ 1 │ 36.754 │ 0.0 │ 1 0 0 100 │
│ 27/03/2026 │ 1 │ 27.777 │ 0.0 │ 1 0 0 100 │
└────────────┴────────┴─────────────────┴───────────────┴────────────────────────┘
SUMMARY METRICS
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Metric ┃ Value ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Backtesting from │ 2026-01-01 00:00:00 │
│ Backtesting to │ 2026-03-27 15:43:00 │
│ Trading Mode │ Isolated Futures │
│ Max open trades │ 1 │
│ │ │
│ Total/Daily Avg Trades │ 54 / 0.64 │
│ Starting balance │ 1000 USDT │
│ Final balance │ 1422.136 USDT │
│ Absolute profit │ 422.136 USDT │
│ Total profit % │ 42.21% │
│ CAGR % │ 353.68% │
│ Sortino │ 36.18 │
│ Sharpe │ 2.25 │
│ Calmar │ 96.27 │
│ SQN │ 1.35 │
│ Profit factor │ 1.55 │
│ Expectancy (Ratio) │ 7.82 (0.29) │
│ Avg. daily profit │ 4.966 USDT │
│ Avg. stake amount │ 1224.501 USDT │
│ Total trade volume │ 131900.967 USDT │
│ │ │
│ Long / Short trades │ 1 / 53 │
│ Long / Short profit % │ 3.62% / 38.60% │
│ Long / Short profit USDT │ 36.176 / 385.960 │
│ │ │
│ Best Pair │ BTC/USDT:USDT 42.21% │
│ Worst Pair │ BTC/USDT:USDT 42.21% │
│ Best trade │ BTC/USDT:USDT 13.07% │
│ Worst trade │ BTC/USDT:USDT -2.14% │
│ Best day │ 104.735 USDT │
│ Worst day │ -57.218 USDT │
│ Days win/draw/lose │ 22 / 39 / 19 │
│ Min/Max/Avg. Duration Winners │ 0d 00:58 / 6d 10:57 / 1d 15:19 │
│ Min/Max/Avg. Duration Losers │ 0d 00:18 / 5d 19:41 / 0d 20:19 │
│ Max Consecutive Wins / Loss │ 4 / 5 │
│ Rejected Entry signals │ 0 │
│ Entry/Exit Timeouts │ 0 / 0 │
│ │ │
│ Min balance │ 1016.026 USDT │
│ Max balance │ 1450.263 USDT │
│ Max % of account underwater │ 9.86% │
│ Absolute drawdown │ 142.938 USDT (9.86%) │
│ Drawdown duration │ 4 days 23:26:00 │
│ Profit at drawdown start │ 450.263 USDT │
│ Profit at drawdown end │ 307.325 USDT │
│ Drawdown start │ 2026-02-28 11:00:00 │
│ Drawdown end │ 2026-03-05 10:26:00 │
│ Market change │ -24.27% │
└───────────────────────────────┴────────────────────────────────┘
Backtested 2026-01-01 00:00:00 -> 2026-03-27 15:43:00 | Max open trades : 1
STRATEGY SUMMARY
┏━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃
┡━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ EmptyShort │ 54 │ 0.75 │ 422.136 │ 42.21 │ 1 day, 5:07:00 │ 25 0 29 46.3 │ 142.938 USDT 9.86% │
└────────────┴────────┴──────────────┴─────────────────┴──────────────┴────────────────┴────────────────────────┴─────────────────────┘

View File

@@ -5,7 +5,7 @@
"0": 10
},
"stoploss": {
"stoploss": -1.0
"stoploss": -0.02
},
"trailing": {
"trailing_stop": false,

File diff suppressed because it is too large Load Diff