┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓

┃ 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% │
This commit is contained in:
Jérôme Delacotte
2026-02-28 18:58:41 +01:00
parent f5bf4a4ac1
commit 123804b5f3
3 changed files with 513 additions and 365 deletions

561
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]
sma_indicators = list()
sma_indicators_h = list()
sma_indicators_d = list()
score_indicators = list()
stop_buying_indicators = list()
god_genes_with_timeperiod = list()
sma_deriv1_indicators = list()
for timeperiod in timeperiods:
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")
# god_genes_with_timeperiod.append(f'max{timeperiod}')
# god_genes_with_timeperiod.append(f'min{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}_deriv1")
god_genes_with_timeperiod.append(f"sma{timeperiod}_deriv2")
god_genes_with_timeperiod.append(f"sma{timeperiod}_score")
# sma_deriv1_indicators.append(f"sma{timeperiod}_deriv1")
sma_deriv1_indicators.append(f"sma{timeperiod}_deriv1")
# sma_deriv1_indicators.append(f"sma{timeperiod}_deriv2")
# sma_deriv1_indicators.append(f"sma{timeperiod}_score")
# stoploss_indicators.append(f"stop_buying{timeperiod}")
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_change_up")
# 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.
TREND_CHECK_CANDLES = 4
DECIMALS = 1
@@ -94,169 +80,6 @@ def normalize(df):
df = (df-df.min())/(df.max()-df.min())
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.
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_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)
@@ -372,48 +203,24 @@ class Empty(IStrategy):
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_longue = CategoricalParameter(long_timeperiods, default=120, space='buy')
# 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')
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)
sell_score_indicator = CategoricalParameter(score_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_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)
baisse = DecimalParameter(0, 0.5, decimals=2, default=0.3, space='protection', optimize=True, load=True)
b30_indicateur = CategoricalParameter(sma_indicators_h, default="sma36", space='protection', 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')
# stoploss_force = DecimalParameter(-0.2, 0, decimals=2, default=-0.05, space='protection')
@@ -438,12 +245,23 @@ class Empty(IStrategy):
#
# range_pos = (last_candle['close'] - range_min) / (range_max - range_min)
range_pos = last_candle[f"range_pos"]
sl_min = self.wallets.get_available_stake_amount() / 6
sl_max = self.wallets.get_available_stake_amount() / 2
# range_pos = last_candle[f"range_pos"]
# sl_min = self.wallets.get_available_stake_amount() / 6
# sl_max = self.wallets.get_available_stake_amount() / 2
#
# amount = sl_min + (1 - range_pos) * (sl_max - sl_min)
if last_candle['enter_tag'] == 'fall':
amount = self.wallets.get_available_stake_amount() / 5
else:
amount = self.wallets.get_available_stake_amount() # / (2 * self.pairs[pair]['count_of_lost'] + 1)
amount = sl_min + (1 - range_pos) * (sl_max - sl_min)
amount = self.wallets.get_available_stake_amount()
# factor = 1
#
# 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())
@@ -546,6 +364,9 @@ class Empty(IStrategy):
last_candle_2 = dataframe.iloc[-2].squeeze()
last_candle_3 = dataframe.iloc[-3].squeeze()
# if (last_candle['has_cross_min_6'] and last_candle['sma60_deriv1'] > 0) or (last_candle['sma12_inv_1d']):
# self.pairs[pair]['count_of_lost'] = 0
condition = False if self.pairs[pair]['count_of_lost'] >= 1 \
and (last_candle['sma12_deriv1_1d'] < 0.001 \
or last_candle['sma12_deriv2_1d'] < 0.001) else True
@@ -619,19 +440,19 @@ class Empty(IStrategy):
buys=1,
stake=round(stake_amount, 2)
)
else:
self.log_trade(
last_candle=last_candle,
date=current_time,
action=("🟩Buy" if allow_to_buy else "Canceled") + " " + reason,
pair=pair,
rate=rate,
dispo=dispo,
profit=0,
trade_type=entry_tag,
buys=1,
stake=0
)
# else:
# self.log_trade(
# last_candle=last_candle,
# date=current_time,
# action=("🟩Buy" if allow_to_buy else "Canceled") + " " + reason,
# pair=pair,
# rate=rate,
# dispo=dispo,
# profit=0,
# trade_type=entry_tag,
# buys=1,
# stake=0
# )
return allow_to_buy
def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float,
@@ -701,6 +522,8 @@ class Empty(IStrategy):
self.pairs[pair]['max_profit'] = max(self.pairs[pair]['max_profit'], profit)
max_profit = self.pairs[pair]['max_profit']
# baisse_min = last_candle['close'] - last_candle['min12']
baisse = 0
if profit > 0:
baisse = 1 - (profit / max_profit)
@@ -722,19 +545,19 @@ class Empty(IStrategy):
# buys=count_of_buys,
# stake=0
# )
# if self.pairs[pair]['current_trade'].enter_tag == 'fall':
# 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
# return 'sma60'
# else:
if current_profit < - 0.02 and last_candle[f"close"] <= last_candle['sma60']:
self.pairs[pair]['force_sell'] = True
return 'sma60'
cross = qtpylib.crossed_below(dataframe[self.sell_sma_indicators.value], dataframe[self.sell_crossed_sma_indicators.value])
# if profit > 0 and cross.iloc[-1]:
# 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:
if profit > max(5, expected_profit) and \
(baisse > self.baisse.value and last_candle[f"close"] <= last_candle[self.b30_indicateur.value]) \
and last_candle['hapercent'] <0 :
self.pairs[pair]['force_sell'] = True
return 'B30'
@@ -827,7 +650,9 @@ class Empty(IStrategy):
dataframe['mid'] = dataframe['haopen'] + (dataframe['haclose'] - dataframe['haopen']) / 2
dataframe['zero'] = 0
dataframe[f"percent"] = dataframe['close'].pct_change()
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'min{timeperiod}'] = talib.MIN(dataframe['close'], timeperiod=timeperiod)
dataframe[f"percent{timeperiod}"] = dataframe['close'].pct_change(timeperiod)
@@ -853,11 +678,27 @@ class Empty(IStrategy):
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)
informative['max_rsi_12'] = talib.MAX(informative['rsi'], timeperiod=12)
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)
# ######################################################################################################
@@ -868,7 +709,8 @@ class Empty(IStrategy):
# 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['rsi'] = talib.RSI(dataframe['close'], timeperiod=14)
@@ -891,62 +733,13 @@ class Empty(IStrategy):
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()
# # print(dataframe.columns)
#
# buy_indicator = self.buy_indicator0.value
# buy_crossed_indicator = self.buy_crossed_indicator0.value
# buy_operator = self.buy_operator0.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))
# #####################################################################################
# CA MONTE !!
# #####################################################################################
# conditions.append(dataframe[f"{self.start_bull_indicator.value}_deriv1_1d" ] > self.start_bull_deriv1.value)
# conditions.append(dataframe[f"{self.start_bull_indicator.value}_deriv2_1d"] > self.start_bull_deriv2.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['sma12_deriv1_1d'] > self.buy_deriv1_sma12d.value)
@@ -962,11 +755,6 @@ class Empty(IStrategy):
dynamic_rsi_threshold = 70 + 15 * np.tanh(dataframe["dist_sma200_1d"] * 5)
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"range_pos"] < 0.05) ) | ((dataframe['sma12_deriv1'] > 0) & (dataframe['sma12_deriv2'] > 0)))
@@ -975,17 +763,84 @@ class Empty(IStrategy):
| (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:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
['enter_long', 'enter_tag']
] = (1, 'god')
] = (1, 'bull')
# #####################################################################################
# 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['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, 'fall')
return dataframe
@@ -1087,35 +942,35 @@ class Empty(IStrategy):
# ####################################################################
# Calcul de la pente lissée
d1 = series.diff()
d1_smooth = d1.rolling(5).mean()
# Normalisation
z = (d1_smooth - d1_smooth.rolling(ema_period).mean()) / d1_smooth.rolling(ema_period).std()
# d1 = series.diff()
# d1_smooth = d1.rolling(5).mean()
# # Normalisation
# z = (d1_smooth - d1_smooth.rolling(ema_period).mean()) / d1_smooth.rolling(ema_period).std()
dataframe[f"{name}{suffixe}_trend_up"] = (
(d1_smooth.shift(1) < 0) &
(d1_smooth > 0) &
(z > 1.0)
)
dataframe[f"{name}{suffixe}_trend_down"] = (
(d1_smooth.shift(1) > 0) &
(d1_smooth < 0) &
(z < -1.0)
)
momentum_short = d1.rolling(int(ema_period / 2)).mean()
momentum_long = d1.rolling(ema_period * 2).mean()
dataframe[f"{name}{suffixe}_trend_change_up"] = (
(momentum_short.shift(1) < momentum_long.shift(1)) &
(momentum_short > momentum_long)
)
dataframe[f"{name}{suffixe}_trend_change_down"] = (
(momentum_short.shift(1) > momentum_long.shift(1)) &
(momentum_short < momentum_long)
)
# dataframe[f"{name}{suffixe}_trend_up"] = (
# (d1_smooth.shift(1) < 0) &
# (d1_smooth > 0) &
# (z > 1.0)
# )
#
# dataframe[f"{name}{suffixe}_trend_down"] = (
# (d1_smooth.shift(1) > 0) &
# (d1_smooth < 0) &
# (z < -1.0)
# )
#
# momentum_short = d1.rolling(int(ema_period / 2)).mean()
# momentum_long = d1.rolling(ema_period * 2).mean()
#
# dataframe[f"{name}{suffixe}_trend_change_up"] = (
# (momentum_short.shift(1) < momentum_long.shift(1)) &
# (momentum_short > momentum_long)
# )
#
# dataframe[f"{name}{suffixe}_trend_change_down"] = (
# (momentum_short.shift(1) > momentum_long.shift(1)) &
# (momentum_short < momentum_long)
# )
return dataframe
@@ -1290,4 +1145,12 @@ class Empty(IStrategy):
expected_profit = lim * self.pairs[pair]['total_amount'] # min(3 * lim, max(lim, pct_to_max)) # 0.004 + 0.002 * self.pairs[pair]['count_of_buys'] #min(0.01, first_max)
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