Compare commits

..

18 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
Jérôme Delacotte
2a7dd0beb4 Merge remote-tracking branch 'origin/Multiple_paires' into Multiple_paires 2026-03-28 20:48:10 +01:00
Jérôme Delacotte
5b1e8bede4 TEST SHORT 2026-03-28 20:47:50 +01:00
Jérôme Delacotte
1bc5a38796 TEST calculateMarketState 2026-03-27 20:55:00 +01:00
Jérôme Delacotte
812aa01135 TEST SHORT 2026-03-27 20:22:01 +01:00
Jérôme Delacotte
4b51cce9c7 EMPTy UP AND DOWN 2026-03-08 19:54:25 +01:00
Jérôme Delacotte
12be7e0441 Empty5m.py Hyperopt
┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDC ┃ Tot Profit % ┃ Avg Duration ┃  Win  Draw  Loss  Win% ┃           Drawdown ┃
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩
│  Empty5m │     13 │         0.36 │          44.066 │         4.41 │      5:58:00 │   12     0     1  92.3 │ 36.632 USDC  3.39% │
└──────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴────────────────────┘
2026-03-07 21:21:52 +01:00
Jérôme Delacotte
f1bad7949d TEST HYPEROPTS 2026-03-07 16:27:45 +01:00
Jérôme Delacotte
2885cf05b1 TEST HYPEROPTS 2026-03-07 15:36:28 +01:00
Jérôme Delacotte
5ce48130f4 ┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃    Avg Duration ┃  Win  Draw  Loss  Win% ┃             Drawdown ┃
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│    Empty │    108 │         2.03 │        5660.765 │       566.08 │ 4 days, 9:45:00 │   62     0    46  57.4 │ 757.488 USDT  17.40% │
└──────────┴────────┴──────────────┴─────────────────┴──────────────┴─────────────────┴────────────────────────┴──────────────────────┘
2026-03-01 20:56:59 +01:00
Jérôme Delacotte
1656ab695a ┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃     Avg Duration ┃  Win  Draw  Loss  Win% ┃             Drawdown ┃
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│    Empty │     92 │         2.23 │        4810.221 │       481.02 │ 4 days, 18:13:00 │   51     0    41  55.4 │ 778.975 USDT  20.25% │
└──────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┴──────────────────────┘
2026-03-01 11:06:09 +01:00
Jérôme Delacotte
a04b07f7ea ┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃     Avg Duration ┃  Win  Draw  Loss  Win% ┃             Drawdown ┃
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│    Empty │     71 │         3.39 │        6790.561 │       679.06 │ 6 days, 19:44:00 │   42     0    29  59.2 │ 722.969 USDT  16.42% │
2026-02-28 20:44:11 +01:00
Jérôme Delacotte
123804b5f3 ┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃     Avg Duration ┃ Win  Draw  Loss  Win% ┃             Drawdown ┃
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│    Empty │     59 │         3.30 │        4263.790 │       426.38 │ 6 days, 23:28:00 │        33     0    26 │ 603.373 USDT  18.82% │
2026-02-28 18:58:41 +01:00
Jérôme Delacotte
f5bf4a4ac1 delete CustomPerformanceLoss 2026-02-27 18:21:58 +01:00
12 changed files with 7481 additions and 670 deletions

View File

@@ -1,30 +0,0 @@
from freqtrade.optimize.hyperopt import IHyperOptLoss
from math import sqrt
class CustomPerformanceLoss(IHyperOptLoss):
@staticmethod
def hyperopt_loss_function(results, trade_count, *args, **kwargs):
total_profit = results['profit_total_abs']
max_dd = results['max_drawdown']
profit_factor = results['profit_factor']
sqn = results['sqn']
# Sécurité minimale
if trade_count < 30:
return 1000
# Éviter division par zéro
if max_dd == 0:
max_dd = 0.0001
# Score principal
performance_score = (
(profit_factor * sqn * total_profit)
/ (max_dd ** 1.5)
)
# On retourne l'inverse car hyperopt minimise
return -performance_score

View File

@@ -2,7 +2,7 @@
"strategy_name": "Empty", "strategy_name": "Empty",
"params": { "params": {
"roi": { "roi": {
"0": 10 "0": 5
}, },
"stoploss": { "stoploss": {
"stoploss": -1.0 "stoploss": -1.0
@@ -17,23 +17,33 @@
"max_open_trades": 1 "max_open_trades": 1
}, },
"buy": { "buy": {
"buy_deriv1_sma12d": -0.05, "buy_deriv1_sma12d": -0.04,
"buy_deriv1_sma5d": -0.03, "buy_deriv1_sma5d": -0.02,
"buy_deriv1_sma60": 0.0, "buy_deriv1_sma60": 0.001,
"buy_deriv2_sma12d": 0.0, "buy_deriv2_sma12d": -0.02,
"buy_deriv2_sma5d": -0.07, "buy_deriv2_sma5d": 0.0,
"buy_deriv2_sma60": -0.003, "buy_deriv2_sma60": -0.001,
"buy_longue": 200 "buy_longue": 160,
"buy_longue_derive": "sma80_deriv1_1d",
"start_bear_deriv1": 0.003,
"start_bear_deriv2": 0.003,
"start_bear_indicator": "sma24",
"start_bull_deriv1": -0.005,
"start_bull_deriv2": 0.0,
"start_bull_indicator": "sma3"
}, },
"protection": { "protection": {
"drop_from_last_entry": 0.0 "drop_from_last_entry": -0.03,
"mises": 1
}, },
"sell": { "sell": {
"sell_crossed_sma_indicators": "sma60", "b30_indicateur": "sma36",
"sell_score_indicator": "sma60_score", "baisse": 0.25,
"sell_sma_indicators": "sma48_1d" "sell_force_sell": -0.169,
"sell_indicator": "sma3",
"sell_score_indicator": "sma3_score"
} }
}, },
"ft_stratparam_v": 1, "ft_stratparam_v": 1,
"export_time": "2026-02-26 20:23:41.717021+00:00" "export_time": "2026-03-07 11:58:51.712499+00:00"
} }

629
Empty.py
View File

@@ -39,19 +39,24 @@ timeperiods = [3, 5, 12, 24, 36, 48, 60]
long_timeperiods = [80, 100, 120, 140, 160, 180, 200] long_timeperiods = [80, 100, 120, 140, 160, 180, 200]
sma_indicators = list() sma_indicators = list()
sma_indicators_h = list()
sma_indicators_d = list()
score_indicators = list() score_indicators = list()
stop_buying_indicators = list() stop_buying_indicators = list()
god_genes_with_timeperiod = list() sma_deriv1_indicators = list()
for timeperiod in timeperiods: for timeperiod in timeperiods:
sma_indicators.append(f"sma{timeperiod}") sma_indicators.append(f"sma{timeperiod}")
sma_indicators_h.append(f"sma{timeperiod}")
sma_indicators_d.append(f"sma{timeperiod}")
sma_indicators.append(f"sma{timeperiod}_1d") sma_indicators.append(f"sma{timeperiod}_1d")
# god_genes_with_timeperiod.append(f'max{timeperiod}') # god_genes_with_timeperiod.append(f'max{timeperiod}')
# god_genes_with_timeperiod.append(f'min{timeperiod}') # god_genes_with_timeperiod.append(f'min{timeperiod}')
# god_genes_with_timeperiod.append(f"percent{timeperiod}") # god_genes_with_timeperiod.append(f"percent{timeperiod}")
# god_genes_with_timeperiod.append(f"sma{timeperiod}") # god_genes_with_timeperiod.append(f"sma{timeperiod}")
god_genes_with_timeperiod.append(f"sma{timeperiod}_deriv1") # sma_deriv1_indicators.append(f"sma{timeperiod}_deriv1")
god_genes_with_timeperiod.append(f"sma{timeperiod}_deriv2") sma_deriv1_indicators.append(f"sma{timeperiod}_deriv1")
god_genes_with_timeperiod.append(f"sma{timeperiod}_score") # sma_deriv1_indicators.append(f"sma{timeperiod}_deriv2")
# sma_deriv1_indicators.append(f"sma{timeperiod}_score")
# stoploss_indicators.append(f"stop_buying{timeperiod}") # stoploss_indicators.append(f"stop_buying{timeperiod}")
stop_buying_indicators.append(f"stop_buying{timeperiod}_1d") stop_buying_indicators.append(f"stop_buying{timeperiod}_1d")
@@ -63,29 +68,10 @@ for timeperiod in timeperiods:
# god_genes_with_timeperiod.append(f"sma{timeperiod}_trend_down") # god_genes_with_timeperiod.append(f"sma{timeperiod}_trend_down")
# god_genes_with_timeperiod.append(f"sma{timeperiod}_trend_change_up") # god_genes_with_timeperiod.append(f"sma{timeperiod}_trend_change_up")
# god_genes_with_timeperiod.append(f"sma{timeperiod}_trend_change_down") # god_genes_with_timeperiod.append(f"sma{timeperiod}_trend_change_down")
for timeperiod in long_timeperiods:
sma_deriv1_indicators.append(f"sma{timeperiod}_deriv1_1d")
sma_indicators_d.append(f"sma{timeperiod}")
operators = [
"D", # Disabled gene
">", # Indicator, bigger than cross indicator
"<", # Indicator, smaller than cross indicator
"=", # Indicator, equal with cross indicator
"C", # Indicator, crossed the cross indicator
"CA", # Indicator, crossed above the cross indicator
"CB", # Indicator, crossed below the cross indicator
# ">R", # Normalized indicator, bigger than real number
# "=R", # Normalized indicator, equal with real number
# "<R", # Normalized indicator, smaller than real number
# "/>R", # Normalized indicator devided to cross indicator, bigger than real number
# "/=R", # Normalized indicator devided to cross indicator, equal with real number
# "/<R", # Normalized indicator devided to cross indicator, smaller than real number
# "UT", # Indicator, is in UpTrend status
# "DT", # Indicator, is in DownTrend status
# "OT", # Indicator, is in Off trend status(RANGE)
# "CUT", # Indicator, Entered to UpTrend status
# "CDT", # Indicator, Entered to DownTrend status
# "COT" # Indicator, Entered to Off trend status(RANGE)
]
# number of candles to check up,don,off trend. # number of candles to check up,don,off trend.
TREND_CHECK_CANDLES = 4 TREND_CHECK_CANDLES = 4
DECIMALS = 1 DECIMALS = 1
@@ -94,169 +80,6 @@ def normalize(df):
df = (df-df.min())/(df.max()-df.min()) df = (df-df.min())/(df.max()-df.min())
return df return df
def gene_calculator(dataframe, indicator):
# print(indicator)
# Cuz Timeperiods not effect calculating CDL patterns recognations
if 'CDL' in indicator:
splited_indicator = indicator.split('-')
splited_indicator[1] = "0"
new_indicator = "-".join(splited_indicator)
# print(indicator, new_indicator)
indicator = new_indicator
gene = indicator.split("-")
gene_name = gene[0]
gene_len = len(gene)
# print(f"GENE {gene_name} {gene_len} {indicator}")
if gene_name in dataframe.keys():
# print(f"{indicator}, calculated befoure")
# print(len(dataframe.keys()))
return dataframe[gene_name]
if indicator in dataframe.keys():
# print(f"{indicator}, calculated befoure")
# print(len(dataframe.keys()))
return dataframe[indicator]
else:
result = None
# For Pattern Recognations
if gene_len == 1:
# print('gene_len == 1\t', indicator)
result = getattr(talib, gene_name)(
dataframe
)
return normalize(result)
elif gene_len == 2:
# print('gene_len == 2\t', indicator)
gene_timeperiod = int(gene[1])
result = getattr(talib, gene_name)(
dataframe,
timeperiod=gene_timeperiod,
)
return normalize(result)
# For
elif gene_len == 3:
# print('gene_len == 3\t', indicator)
gene_timeperiod = int(gene[2])
gene_index = int(gene[1])
result = getattr(talib, gene_name)(
dataframe,
timeperiod=gene_timeperiod,
).iloc[:, gene_index]
return normalize(result)
# For trend operators(MA-5-SMA-4)
elif gene_len == 4:
# print('gene_len == 4\t', indicator)
gene_timeperiod = int(gene[1])
sharp_indicator = f'{gene_name}-{gene_timeperiod}'
dataframe[sharp_indicator] = getattr(talib, gene_name)(
dataframe,
timeperiod=gene_timeperiod,
)
return normalize(talib.SMA(dataframe[sharp_indicator].fillna(0), TREND_CHECK_CANDLES))
# For trend operators(STOCH-0-4-SMA-4)
elif gene_len == 5:
# print('gene_len == 5\t', indicator)
gene_timeperiod = int(gene[2])
gene_index = int(gene[1])
sharp_indicator = f'{gene_name}-{gene_index}-{gene_timeperiod}'
dataframe[sharp_indicator] = getattr(talib, gene_name)(
dataframe,
timeperiod=gene_timeperiod,
).iloc[:, gene_index]
return normalize(talib.SMA(dataframe[sharp_indicator].fillna(0), TREND_CHECK_CANDLES))
def condition_generator(dataframe, operator, indicator, crossed_indicator, real_num):
condition = (dataframe['volume'] > 10)
# TODO : it ill callculated in populate indicators.
pd.set_option('display.max_rows', None)
pd.set_option('display.max_columns', None)
pd.set_option("display.width", 200)
# print(f"{indicator} {crossed_indicator} {real_num}")
dataframe[indicator] = gene_calculator(dataframe, indicator)
dataframe[crossed_indicator] = gene_calculator(dataframe, crossed_indicator)
indicator_trend_sma = f"{indicator}-SMA-{TREND_CHECK_CANDLES}"
if operator in ["UT", "DT", "OT", "CUT", "CDT", "COT"]:
dataframe[indicator_trend_sma] = gene_calculator(dataframe, indicator_trend_sma)
if operator == ">":
condition = (dataframe[indicator] > dataframe[crossed_indicator])
elif operator == "=":
condition = (np.isclose(dataframe[indicator], dataframe[crossed_indicator]))
elif operator == "<":
condition = (dataframe[indicator] < dataframe[crossed_indicator])
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (qtpylib.crossed_above(dataframe[indicator], dataframe[crossed_indicator]))
elif operator == "CB":
condition = (qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator]))
elif operator == ">R":
condition = (dataframe[indicator] > real_num)
elif operator == "=R":
condition = (np.isclose(dataframe[indicator], real_num))
elif operator == "<R":
condition = (dataframe[indicator] < real_num)
elif operator == "/>R":
condition = (dataframe[indicator].div(dataframe[crossed_indicator]) > real_num)
elif operator == "/=R":
condition = (np.isclose(dataframe[indicator].div(dataframe[crossed_indicator]), real_num))
elif operator == "/<R":
condition = (dataframe[indicator].div(dataframe[crossed_indicator]) < real_num)
elif operator == "UT":
condition = (dataframe[indicator] > dataframe[indicator_trend_sma])
elif operator == "DT":
condition = (dataframe[indicator] < dataframe[indicator_trend_sma])
elif operator == "OT":
condition = (np.isclose(dataframe[indicator], dataframe[indicator_trend_sma]))
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(dataframe[indicator],dataframe[indicator_trend_sma])
) & (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(dataframe[indicator], dataframe[indicator_trend_sma])
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(dataframe[indicator], dataframe[indicator_trend_sma])
) |
(
qtpylib.crossed_above(dataframe[indicator], dataframe[indicator_trend_sma])
)
) &
(
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
)
return condition, dataframe
# #########################################################################################################################
# This class is a sample. Feel free to customize it. # This class is a sample. Feel free to customize it.
class Empty(IStrategy): class Empty(IStrategy):
@@ -364,6 +187,14 @@ class Empty(IStrategy):
} }
} }
start_bull_indicator = CategoricalParameter(sma_indicators_d, default='sma100', space='buy', optimize=True, load=True)
start_bull_deriv1 = DecimalParameter(-0.005, 0.005, decimals=3, default=0, space='buy', optimize=True, load=True)
start_bull_deriv2 = DecimalParameter(-0.005, 0.005, decimals=3, default=0, space='buy', optimize=True, load=True)
start_bear_indicator = CategoricalParameter(sma_indicators_d, default='sma100', space='buy', optimize=True, load=True)
start_bear_deriv1 = DecimalParameter(-0.005, 0.005, decimals=3, default=0, space='buy', optimize=True, load=True)
start_bear_deriv2 = DecimalParameter(-0.005, 0.005, decimals=3, default=0, space='buy', optimize=True, load=True)
buy_deriv1_sma60 = DecimalParameter(-0.005, 0.005, decimals=3, default=0, space='buy', optimize=False, load=True) buy_deriv1_sma60 = DecimalParameter(-0.005, 0.005, decimals=3, default=0, space='buy', optimize=False, load=True)
buy_deriv1_sma5d = DecimalParameter(-0.07, 0.07, decimals=2, default=0, space='buy', optimize=False, load=True) buy_deriv1_sma5d = DecimalParameter(-0.07, 0.07, decimals=2, default=0, space='buy', optimize=False, load=True)
buy_deriv1_sma12d = DecimalParameter(-0.07, 0.07, decimals=2, default=0, space='buy', optimize=False, load=True) buy_deriv1_sma12d = DecimalParameter(-0.07, 0.07, decimals=2, default=0, space='buy', optimize=False, load=True)
@@ -372,48 +203,28 @@ class Empty(IStrategy):
buy_deriv2_sma5d = DecimalParameter(-0.07, 0.07, decimals=2, default=0, space='buy', optimize=False, load=True) buy_deriv2_sma5d = DecimalParameter(-0.07, 0.07, decimals=2, default=0, space='buy', optimize=False, load=True)
buy_deriv2_sma12d = DecimalParameter(-0.07, 0.07, decimals=2, default=0, space='buy', optimize=False, load=True) buy_deriv2_sma12d = DecimalParameter(-0.07, 0.07, decimals=2, default=0, space='buy', optimize=False, load=True)
buy_longue = CategoricalParameter(long_timeperiods, default=120, space='buy') buy_longue = CategoricalParameter(long_timeperiods, default=120, space='buy', optimize=False, load=True)
buy_longue_derive = CategoricalParameter(sma_deriv1_indicators, default="sma60_deriv1_1d", space='buy', optimize=False, load=True)
# Buy Hyperoptable Parameters/Spaces.
# buy_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="ADD-20", space='buy')
# buy_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="ASIN-6", space='buy')
# buy_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLEVENINGSTAR-50", space='buy')
#
# buy_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="SMA-100", space='buy')
# buy_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="WILLR-50", space='buy')
# buy_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHANGINGMAN-20", space='buy')
#
# buy_operator0 = CategoricalParameter(operators, default="/<R", space='buy')
# buy_operator1 = CategoricalParameter(operators, default="<R", space='buy')
# buy_operator2 = CategoricalParameter(operators, default="CB", space='buy')
#
# buy_real_num0 = DecimalParameter(-1, 1, decimals=DECIMALS, default=0, space='buy')
# buy_real_num1 = DecimalParameter(-1, 1, decimals=DECIMALS, default=0, space='buy')
# buy_real_num2 = DecimalParameter(-1, 1, decimals=DECIMALS, default=0, space='buy')
# Sell Hyperoptable Parameters/Spaces.
# sell_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell')
# sell_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="MAMA-1-100", space='sell')
# sell_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell')
#
# sell_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell')
# sell_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell')
# sell_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell')
#
# sell_operator0 = CategoricalParameter(operators, default="<R", space='sell')
# sell_operator1 = CategoricalParameter(operators, default="D", space='sell')
# sell_operator2 = CategoricalParameter(operators, default="/>R", space='sell')
#
# sell_real_num0 = DecimalParameter(-1, 1, decimals=DECIMALS, default=0, space='sell')
# sell_real_num1 = DecimalParameter(-1, 1, decimals=DECIMALS, default=0, space='sell')
# sell_real_num2 = DecimalParameter(-1, 1, decimals=DECIMALS, default=0, space='sell')
sell_score_indicator = CategoricalParameter(score_indicators, default="sma24_score", space='sell') sell_score_indicator = CategoricalParameter(score_indicators, default="sma24_score", space='sell')
sell_sma_indicators = CategoricalParameter(sma_indicators, default="sma24_score", space='sell') # sell_sma_indicators = CategoricalParameter(sma_indicators, default="sma24_score", space='sell')
sell_crossed_sma_indicators = CategoricalParameter(sma_indicators, default="sma24_score", space='sell') # sell_crossed_sma_indicators = CategoricalParameter(sma_indicators, default="sma24_score", space='sell')
drop_from_last_entry = DecimalParameter(-0.1, 0, decimals=2, default=-0.025, space='protection', optimize=False, load=True)
# baisses = list()
# for i in range(0, 0.5, 0.05):
# baisses.append(i)
mises = IntParameter(1, 10, default=1, space='protection')
sell_force_sell = DecimalParameter(-0.2, 0, decimals=3, default=-0.02, space='sell')
sell_indicator = CategoricalParameter(sma_indicators, default="sma36", space='sell', optimize=True, load=True)
baisse = DecimalParameter(0.1, 0.5, decimals=2, default=0.3, space='sell', optimize=True, load=True)
b30_indicateur = CategoricalParameter(sma_indicators_h, default="sma36", space='sell', optimize=True, load=True)
# lost_indicator = CategoricalParameter(sma_deriv1_indicators, default="sma5_deriv1", space='protection')
drop_from_last_entry = DecimalParameter(-0.1, 0, decimals=2, default=-0.025, space='protection')
# range_pos_stoploss = DecimalParameter(0, 0.1, decimals=2, default=0.05, space='protection') # range_pos_stoploss = DecimalParameter(0, 0.1, decimals=2, default=0.05, space='protection')
# stoploss_force = DecimalParameter(-0.2, 0, decimals=2, default=-0.05, space='protection') # stoploss_force = DecimalParameter(-0.2, 0, decimals=2, default=-0.05, space='protection')
@@ -438,12 +249,23 @@ class Empty(IStrategy):
# #
# range_pos = (last_candle['close'] - range_min) / (range_max - range_min) # range_pos = (last_candle['close'] - range_min) / (range_max - range_min)
range_pos = last_candle[f"range_pos"] # range_pos = last_candle[f"range_pos"]
sl_min = self.wallets.get_available_stake_amount() / 6 # sl_min = self.wallets.get_available_stake_amount() / 6
sl_max = self.wallets.get_available_stake_amount() / 2 # sl_max = self.wallets.get_available_stake_amount() / 2
#
# amount = sl_min + (1 - range_pos) * (sl_max - sl_min)
if last_candle['enter_tag'] in ['fall', 'bear', 'Force', 'Range-']:
amount = self.wallets.get_available_stake_amount() / 5
else:
amount = self.wallets.get_available_stake_amount() / self.mises.value # / (2 * self.pairs[pair]['count_of_lost'] + 1)
amount = sl_min + (1 - range_pos) * (sl_max - sl_min) # factor = 1
amount = self.wallets.get_available_stake_amount() #
# if self.pairs[pair]['last_trade'] is not None \
# and self.pairs[pair]['last_trade'].close_profit is not None \
# and self.pairs[pair]['last_trade'].close_profit > 0.01:
# factor = self.pairs[pair]['last_trade'].close_profit / 0.01
# amount = amount / factor
return min(amount, self.wallets.get_available_stake_amount()) return min(amount, self.wallets.get_available_stake_amount())
@@ -546,10 +368,16 @@ class Empty(IStrategy):
last_candle_2 = dataframe.iloc[-2].squeeze() last_candle_2 = dataframe.iloc[-2].squeeze()
last_candle_3 = dataframe.iloc[-3].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 \ condition = False if self.pairs[pair]['count_of_lost'] >= 1 \
and (last_candle['sma12_deriv1_1d'] < 0.001 \ and (last_candle['sma12_deriv1_1d'] < 0.001 or last_candle['sma12_deriv2_1d'] < 0.001) \
or last_candle['sma12_deriv2_1d'] < 0.001) else True and entry_tag != 'dist' else True
reason = '' reason = ''
if not condition: if not condition:
reason = 'lost' reason = 'lost'
@@ -619,19 +447,19 @@ class Empty(IStrategy):
buys=1, buys=1,
stake=round(stake_amount, 2) stake=round(stake_amount, 2)
) )
else: # else:
self.log_trade( # self.log_trade(
last_candle=last_candle, # last_candle=last_candle,
date=current_time, # date=current_time,
action=("🟩Buy" if allow_to_buy else "Canceled") + " " + reason, # action=("🟩Buy" if allow_to_buy else "Canceled") + " " + reason,
pair=pair, # pair=pair,
rate=rate, # rate=rate,
dispo=dispo, # dispo=dispo,
profit=0, # profit=0,
trade_type=entry_tag, # trade_type=entry_tag,
buys=1, # buys=1,
stake=0 # stake=0
) # )
return allow_to_buy return allow_to_buy
def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float, def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float,
@@ -701,6 +529,8 @@ class Empty(IStrategy):
self.pairs[pair]['max_profit'] = max(self.pairs[pair]['max_profit'], profit) self.pairs[pair]['max_profit'] = max(self.pairs[pair]['max_profit'], profit)
max_profit = self.pairs[pair]['max_profit'] max_profit = self.pairs[pair]['max_profit']
# baisse_min = last_candle['close'] - last_candle['min12']
baisse = 0 baisse = 0
if profit > 0: if profit > 0:
baisse = 1 - (profit / max_profit) baisse = 1 - (profit / max_profit)
@@ -722,22 +552,26 @@ class Empty(IStrategy):
# buys=count_of_buys, # buys=count_of_buys,
# stake=0 # stake=0
# ) # )
if self.pairs[pair]['current_trade'].enter_tag in ['bear', 'Force', 'Range-']:
if current_profit < - 0.02 and last_candle[f"close"] <= last_candle['sma60']: if current_profit < - 0.02 and last_candle[f"close"] <= last_candle['sma60'] and self.wallets.get_available_stake_amount() < 50:
self.pairs[pair]['force_sell'] = True self.pairs[pair]['force_sell'] = True
return 'sma60' return 'smaBF'
else:
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'
cross = qtpylib.crossed_below(dataframe[self.sell_sma_indicators.value], dataframe[self.sell_crossed_sma_indicators.value]) if profit > max(5, expected_profit) and \
(baisse > self.baisse.value and last_candle[f"close"] <= last_candle[self.b30_indicateur.value]) \
# if profit > 0 and cross.iloc[-1]: and last_candle['hapercent'] <0 :
# self.pairs[pair]['force_sell'] = True
# return 'Cross'
if profit > max(5, expected_profit) and baisse > 0.30 and last_candle[f"close"] <= last_candle['sma36']:
# and last_candle['percent3'] < 0 and last_candle['percent5'] < 0:
self.pairs[pair]['force_sell'] = True self.pairs[pair]['force_sell'] = True
return 'B30' return 'B30'
# if profit > max(5, expected_profit) and last_candle['sma5_deriv1_1d'] < 0 and baisse > 0.15:
# self.pairs[pair]['force_sell'] = True
# return 'Drv5d'
# if last_candle['range_pos'] > 0.05 and current_profit < - last_candle['range_pos'] /4 : #last_candle['cross_sma60']: # if last_candle['range_pos'] > 0.05 and current_profit < - last_candle['range_pos'] /4 : #last_candle['cross_sma60']:
# self.pairs[pair]['force_sell'] = True # self.pairs[pair]['force_sell'] = True
# return 'Range' # return 'Range'
@@ -827,7 +661,9 @@ class Empty(IStrategy):
dataframe['mid'] = dataframe['haopen'] + (dataframe['haclose'] - dataframe['haopen']) / 2 dataframe['mid'] = dataframe['haopen'] + (dataframe['haclose'] - dataframe['haopen']) / 2
dataframe['zero'] = 0 dataframe['zero'] = 0
dataframe[f"percent"] = dataframe['close'].pct_change()
for timeperiod in timeperiods: for timeperiod in timeperiods:
dataframe[f"mid_smooth{timeperiod}"] = dataframe['mid'].rolling(timeperiod).mean()
dataframe[f'max{timeperiod}'] = talib.MAX(dataframe['close'], timeperiod=timeperiod) dataframe[f'max{timeperiod}'] = talib.MAX(dataframe['close'], timeperiod=timeperiod)
dataframe[f'min{timeperiod}'] = talib.MIN(dataframe['close'], timeperiod=timeperiod) dataframe[f'min{timeperiod}'] = talib.MIN(dataframe['close'], timeperiod=timeperiod)
dataframe[f"percent{timeperiod}"] = dataframe['close'].pct_change(timeperiod) dataframe[f"percent{timeperiod}"] = dataframe['close'].pct_change(timeperiod)
@@ -853,11 +689,27 @@ class Empty(IStrategy):
for timeperiod in long_timeperiods: for timeperiod in long_timeperiods:
informative[f"sma{timeperiod}"] = informative['mid'].ewm(span=timeperiod, adjust=False).mean() 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) informative['rsi'] = talib.RSI(informative['close'], timeperiod=14)
self.calculeDerivees(informative, f"rsi", timeframe=self.timeframe, ema_period=14) self.calculeDerivees(informative, f"rsi", timeframe=self.timeframe, ema_period=14)
informative['max_rsi_12'] = talib.MAX(informative['rsi'], timeperiod=12) informative['max_rsi_12'] = talib.MAX(informative['rsi'], timeperiod=12)
informative['max_rsi_24'] = talib.MAX(informative['rsi'], timeperiod=24) informative['max_rsi_24'] = talib.MAX(informative['rsi'], timeperiod=24)
informative[f'stop_buying_deb'] = qtpylib.crossed_below(informative[f"sma12"], informative['sma36']) & (informative['close'] < informative['sma100'])
informative[f'stop_buying_end'] = qtpylib.crossed_above(informative[f"sma12"], informative['sma36']) & (informative['close'] > informative['sma100'])
latched = np.zeros(len(informative), dtype=bool)
for i in range(1, len(informative)):
if informative['stop_buying_deb'].iloc[i]:
latched[i] = True
elif informative['stop_buying_end'].iloc[i]:
latched[i] = False
else:
latched[i] = latched[i - 1]
informative['stop_buying'] = latched
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True)
# ###################################################################################################### # ######################################################################################################
@@ -868,7 +720,8 @@ class Empty(IStrategy):
# dataframe['cross_sma60'] = qtpylib.crossed_below(dataframe[self.sell_sma_indicators.value], dataframe[self.sell_crossed_sma_indicators.value]) # dataframe['cross_sma60'] = qtpylib.crossed_below(dataframe[self.sell_sma_indicators.value], dataframe[self.sell_crossed_sma_indicators.value])
dataframe[f'stop_buying'] = qtpylib.crossed_below(dataframe[f"sma12"], dataframe['sma48']) dataframe[f'has_cross_min'] = qtpylib.crossed_above(dataframe[f"close"], dataframe['min60_1d'])
dataframe[f'has_cross_min_6'] = (dataframe['has_cross_min'].rolling(6).max() == 1)
dataframe['atr'] = talib.ATR(dataframe) dataframe['atr'] = talib.ATR(dataframe)
dataframe['rsi'] = talib.RSI(dataframe['close'], timeperiod=14) dataframe['rsi'] = talib.RSI(dataframe['close'], timeperiod=14)
@@ -891,62 +744,13 @@ class Empty(IStrategy):
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe.loc[
# (
# (dataframe['sma24_score'].shift(2) <= dataframe['zero'])
# & (dataframe['sma5'].shift(1) <= dataframe['sma5'])
# & (dataframe['sma5_inv'] == -1)
# & (dataframe['min24'].shift(3) == dataframe['min24'])
# ),
# 'buy'] = 1
conditions = list() conditions = list()
# # print(dataframe.columns) # #####################################################################################
# # CA MONTE !!
# buy_indicator = self.buy_indicator0.value # #####################################################################################
# buy_crossed_indicator = self.buy_crossed_indicator0.value conditions.append(dataframe[f"{self.start_bull_indicator.value}_deriv1_1d" ] > self.start_bull_deriv1.value)
# buy_operator = self.buy_operator0.value conditions.append(dataframe[f"{self.start_bull_indicator.value}_deriv2_1d"] > self.start_bull_deriv2.value)
# buy_real_num = self.buy_real_num0.value
# condition, dataframe = condition_generator(
# dataframe,
# buy_operator,
# buy_indicator,
# buy_crossed_indicator,
# buy_real_num
# )
# conditions.append(condition)
# # backup
# buy_indicator = self.buy_indicator1.value
# buy_crossed_indicator = self.buy_crossed_indicator1.value
# buy_operator = self.buy_operator1.value
# buy_real_num = self.buy_real_num1.value
#
# condition, dataframe = condition_generator(
# dataframe,
# buy_operator,
# buy_indicator,
# buy_crossed_indicator,
# buy_real_num
# )
# conditions.append(condition)
#
# buy_indicator = self.buy_indicator2.value
# buy_crossed_indicator = self.buy_crossed_indicator2.value
# buy_operator = self.buy_operator2.value
# buy_real_num = self.buy_real_num2.value
# condition, dataframe = condition_generator(
# dataframe,
# buy_operator,
# buy_indicator,
# buy_crossed_indicator,
# buy_real_num
# )
# conditions.append(condition)
# conditions.append((dataframe[self.stop_buying_indicator.value] == False) | (dataframe['range_pos'] < 0))
#conditions.append((dataframe[self.stop_buying_indicator.value] == False) | (dataframe['range_pos'] < 0))
conditions.append(dataframe['sma12_deriv1'] > self.buy_deriv1_sma60.value) conditions.append(dataframe['sma12_deriv1'] > self.buy_deriv1_sma60.value)
conditions.append(dataframe['sma5_deriv1_1d'] > self.buy_deriv1_sma5d.value) conditions.append(dataframe['sma5_deriv1_1d'] > self.buy_deriv1_sma5d.value)
conditions.append(dataframe['sma12_deriv1_1d'] > self.buy_deriv1_sma12d.value) conditions.append(dataframe['sma12_deriv1_1d'] > self.buy_deriv1_sma12d.value)
@@ -962,11 +766,6 @@ class Empty(IStrategy):
dynamic_rsi_threshold = 70 + 15 * np.tanh(dataframe["dist_sma200_1d"] * 5) dynamic_rsi_threshold = 70 + 15 * np.tanh(dataframe["dist_sma200_1d"] * 5)
conditions.append((dataframe['max_rsi_12_1d'] < dynamic_rsi_threshold)) conditions.append((dataframe['max_rsi_12_1d'] < dynamic_rsi_threshold))
# | (
# (dataframe['sma5_deriv1'] > 0) & (dataframe['sma12_deriv1'] > 0) & (dataframe['sma24_deriv1'] > 0) & (
# dataframe['sma48_deriv1'] > 0) & (dataframe['sma60_deriv1'] > 0) & (dataframe['sma5_deriv1_1d'] > 0))
# )
conditions.append(dataframe[f"close"] > dataframe['sma60']) 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[f"range_pos"] < 0.05) ) | ((dataframe['sma12_deriv1'] > 0) & (dataframe['sma12_deriv2'] > 0)))
@@ -975,17 +774,131 @@ class Empty(IStrategy):
| (dataframe['sma60_inv_1d'] == -1) | (dataframe['sma60_inv_1d'] == -1)
) )
# print(f"BUY indicators tested \n"
# f"{self.buy_indicator0.value} {self.buy_crossed_indicator0.value} {self.buy_operator0.value} {self.buy_real_num0.value} \n"
# f"{self.buy_indicator1.value} {self.buy_crossed_indicator1.value} {self.buy_operator1.value} {self.buy_real_num1.value} \n"
# f"{self.buy_indicator2.value} {self.buy_crossed_indicator2.value} {self.buy_operator2.value} {self.buy_real_num2.value} \n"
# )
if conditions: if conditions:
dataframe.loc[ dataframe.loc[
reduce(lambda x, y: x & y, conditions), reduce(lambda x, y: x & y, conditions),
['enter_long', 'enter_tag'] ['enter_long', 'enter_tag']
] = (1, 'god') ] = (1, 'bull')
# #####################################################################################
# conditions = list()
# conditions.append(dataframe['dist_sma200_1d'] < -0.05)
# conditions.append(dataframe['sma12_inv'] == 1)
# # conditions.append(dataframe['sma100_deriv1_1d'] > 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_1d'])
conditions.append(dataframe['mid_smooth12'] > dataframe['mid_smooth12'].shift(1))
conditions.append(dataframe['sma100_deriv1_1d'] > 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_1d"
# },
# "protection": {
# "drop_from_last_entry": -0.03,
# "b30_indicateur": "sma3",
# "baisse": 0.31
# },
# #####################################################################################
conditions = list()
conditions.append(dataframe[f"{self.start_bear_indicator.value}_deriv1_1d" ] < self.start_bear_deriv1.value)
conditions.append(dataframe[f"{self.start_bear_indicator.value}_deriv2_1d"] < self.start_bear_deriv2.value)
conditions.append(dataframe['sma12_deriv1'] > 0.003)
conditions.append(dataframe['sma5_deriv1_1d'] > 0.0)
conditions.append(dataframe['sma12_deriv1_1d'] > 0.0)
conditions.append(dataframe['sma12_deriv2'] > -0.002)
conditions.append(dataframe['sma5_deriv2_1d'] > 0)
conditions.append(dataframe['sma12_deriv2_1d'] > -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_1d"] * 5)
conditions.append((dataframe['max_rsi_12_1d'] < 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_1d'] > dataframe[f'sma{self.buy_longue.value}_1d'])
| (dataframe['sma60_inv_1d'] == -1)
)
# if conditions:
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'bear')
# conditions = list()
# conditions.append(dataframe['close_1d'] < dataframe[f'sma{self.buy_longue.value}_1d'])
# 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_1d'] > 0.0)
conditions.append(dataframe['sma12_deriv1_1d'] > 0.0)
conditions.append(dataframe['sma24_deriv1_1d'] > 0.0)
conditions.append(dataframe['sma100_deriv1_1d'] > 0.0)
conditions.append(dataframe[f"range_pos"] < 0.025)
# conditions.append(dataframe['sma12_deriv1_1d'] > 0.0)
# # conditions.append(dataframe['close_1d'] < dataframe[f'sma{self.buy_longue.value}_1d'])
# # 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['range_pos'] < -0.03)
# conditions.append(dataframe['min36'] == dataframe['min36'].shift(3))
# dataframe.loc[
# reduce(lambda x, y: x & y, conditions),
# ['enter_long', 'enter_tag']
# ] = (1, 'Range-')
return dataframe return dataframe
@@ -1087,35 +1000,35 @@ class Empty(IStrategy):
# #################################################################### # ####################################################################
# Calcul de la pente lissée # Calcul de la pente lissée
d1 = series.diff() # d1 = series.diff()
d1_smooth = d1.rolling(5).mean() # d1_smooth = d1.rolling(5).mean()
# Normalisation # # Normalisation
z = (d1_smooth - d1_smooth.rolling(ema_period).mean()) / d1_smooth.rolling(ema_period).std() # z = (d1_smooth - d1_smooth.rolling(ema_period).mean()) / d1_smooth.rolling(ema_period).std()
dataframe[f"{name}{suffixe}_trend_up"] = ( # dataframe[f"{name}{suffixe}_trend_up"] = (
(d1_smooth.shift(1) < 0) & # (d1_smooth.shift(1) < 0) &
(d1_smooth > 0) & # (d1_smooth > 0) &
(z > 1.0) # (z > 1.0)
) # )
#
dataframe[f"{name}{suffixe}_trend_down"] = ( # dataframe[f"{name}{suffixe}_trend_down"] = (
(d1_smooth.shift(1) > 0) & # (d1_smooth.shift(1) > 0) &
(d1_smooth < 0) & # (d1_smooth < 0) &
(z < -1.0) # (z < -1.0)
) # )
#
momentum_short = d1.rolling(int(ema_period / 2)).mean() # momentum_short = d1.rolling(int(ema_period / 2)).mean()
momentum_long = d1.rolling(ema_period * 2).mean() # momentum_long = d1.rolling(ema_period * 2).mean()
#
dataframe[f"{name}{suffixe}_trend_change_up"] = ( # dataframe[f"{name}{suffixe}_trend_change_up"] = (
(momentum_short.shift(1) < momentum_long.shift(1)) & # (momentum_short.shift(1) < momentum_long.shift(1)) &
(momentum_short > momentum_long) # (momentum_short > momentum_long)
) # )
#
dataframe[f"{name}{suffixe}_trend_change_down"] = ( # dataframe[f"{name}{suffixe}_trend_change_down"] = (
(momentum_short.shift(1) > momentum_long.shift(1)) & # (momentum_short.shift(1) > momentum_long.shift(1)) &
(momentum_short < momentum_long) # (momentum_short < momentum_long)
) # )
return dataframe return dataframe
@@ -1291,3 +1204,11 @@ class Empty(IStrategy):
self.pairs[pair]['expected_profit'] = expected_profit self.pairs[pair]['expected_profit'] = expected_profit
return expected_profit return expected_profit
def getLastClosedTrade(self):
# récupérer le dernier trade fermé
trades = Trade.get_trades_proxy(pair=pair,is_open=False)
if trades:
last_trade = trades[-1]
self.pairs[pair]['last_profit'] = last_trade.close_profit # ex: 0.12 = +12%
self.pairs[pair]['last_trade'] = last_trade

1142
Empty.txt

File diff suppressed because it is too large Load Diff

32
Empty5m.json Normal file
View File

@@ -0,0 +1,32 @@
{
"strategy_name": "Empty5m",
"params": {
"roi": {
"0": 5
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": null,
"trailing_stop_positive_offset": 0.0,
"trailing_only_offset_is_reached": false
},
"max_open_trades": {
"max_open_trades": 20
},
"sell": {
"b30_indicateur": "sma36",
"baisse": 0.3,
"sell_force_sell": -0.03,
"sell_indicator": "sma36"
},
"protection": {
"drop_from_last_entry": -0.01,
"mises_bull": 4
}
},
"ft_stratparam_v": 1,
"export_time": "2026-03-07 20:20:17.895644+00:00"
}

1452
Empty5m.py Normal file

File diff suppressed because it is too large Load Diff

1218
EmptyAI.py Normal file

File diff suppressed because it is too large Load Diff

32
EmptyShort.json Normal file
View File

@@ -0,0 +1,32 @@
{
"strategy_name": "EmptyShort",
"params": {
"roi": {
"0": 5
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": null,
"trailing_stop_positive_offset": 0.0,
"trailing_only_offset_is_reached": false
},
"max_open_trades": {
"max_open_trades": 20
},
"sell": {
"b30_indicateur": "sma24",
"baisse": 0.2,
"sell_force_sell": -0.02,
"sell_indicator": "sma36"
},
"protection": {
"drop_from_last_entry": 0.0,
"mises_bull": 4
},
"stoploss": {
"stoploss": -0.02
}
},
"ft_stratparam_v": 1,
"export_time": "2026-03-29 18:29:54.986316+00:00"
}

1419
EmptyShort.py Normal file

File diff suppressed because it is too large Load Diff

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 "0": 10
}, },
"stoploss": { "stoploss": {
"stoploss": -1.0 "stoploss": -0.02
}, },
"trailing": { "trailing": {
"trailing_stop": false, "trailing_stop": false,

File diff suppressed because it is too large Load Diff