Calcul 20250101-20250714 737.222 159.166$

This commit is contained in:
Jérôme Delacotte
2025-09-12 23:38:01 +02:00
parent 5a9adb0b53
commit 82391fcde1
2 changed files with 1656 additions and 1160 deletions

View File

@@ -307,7 +307,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# if count < 3:
# allow_to_buy = False
if not self.should_enter_trade(pair, last_candle):
if not self.should_enter_trade(pair, last_candle, current_time):
allow_to_buy = False
if allow_to_buy:
@@ -382,6 +382,9 @@ class Zeus_8_3_2_B_4_2(IStrategy):
self.pairs[pair]['last_buy'] = 0
self.pairs[pair]['last_date'] = current_time
self.pairs[pair]['last_palier_index'] = -1
self.pairs[pair]['last_trade'] = trade
self.pairs[pair]['current_trade'] = None
return (allow_to_sell) | (exit_reason == 'force_exit')
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
@@ -413,6 +416,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
max_touch_before = self.pairs[pair]['max_touch']
self.pairs[pair]['last_max'] = max(last_candle['close'], self.pairs[pair]['last_max'])
self.pairs[pair]['last_min'] = min(last_candle['close'], self.pairs[pair]['last_min'])
self.pairs[pair]['current_trade'] = trade
count_of_buys = trade.nr_of_successful_entries
@@ -434,23 +438,26 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# if (last_candle['sma20_deriv1'] < 0 and before_last_candle['sma20_deriv1'] >= 0) and (current_profit > expected_profit):
# return 'Drv_' + str(count_of_buys)
pair_name = self.getShortName(pair)
if 1 <= count_of_buys <= 3:
if ((before_last_candle_2['mid_smooth_3_deriv1'] <= before_last_candle['mid_smooth_3_deriv1'])
& (before_last_candle['mid_smooth_3_deriv1'] >= last_candle['mid_smooth_3_deriv1'])) \
and (current_profit > expected_profit):
return 'Drv3_' + pair_name + '_' + str(count_of_buys)
# if (current_profit > expected_profit) and last_candle['can_sell']:
# return 'Can_' + pair_name + '_' + str(count_of_buys)
if 4 <= count_of_buys <= 6:
if ((before_last_candle_2['mid_smooth_12_deriv1'] <= before_last_candle['mid_smooth_12_deriv1'])
& (before_last_candle['mid_smooth_12_deriv1'] >= last_candle['mid_smooth_12_deriv1'])) \
and (current_profit > expected_profit):
return 'Drv13_' + pair_name + '_' + str(count_of_buys)
# if 1 <= count_of_buys <= 3:
if ((before_last_candle_2['mid_smooth_3_deriv1'] <= before_last_candle['mid_smooth_3_deriv1'])
& (before_last_candle['mid_smooth_3_deriv1'] >= last_candle['mid_smooth_3_deriv1'])) \
and (current_profit > expected_profit):
return 'Drv3_' + pair_name + '_' + str(count_of_buys)
if 7 <= count_of_buys:
if ((before_last_candle_24['sma24_deriv1_1h'] <= before_last_candle_12['sma24_deriv1_1h'])
& (before_last_candle_12['sma24_deriv1_1h'] >= last_candle['sma24_deriv1_1h'])) \
and (current_profit > expected_profit):
return 'Drv24_' + pair_name + '_' + str(count_of_buys)
# if 4 <= count_of_buys <= 6:
# if ((before_last_candle_2['mid_smooth_12_deriv1'] <= before_last_candle['mid_smooth_12_deriv1'])
# & (before_last_candle['mid_smooth_12_deriv1'] >= last_candle['mid_smooth_12_deriv1'])) \
# and (current_profit > expected_profit):
# return 'Drv13_' + pair_name + '_' + str(count_of_buys)
#
# if 7 <= count_of_buys:
# if ((before_last_candle_24['sma24_deriv1_1h'] <= before_last_candle_12['sma24_deriv1_1h'])
# & (before_last_candle_12['sma24_deriv1_1h'] >= last_candle['sma24_deriv1_1h'])) \
# and (current_profit > expected_profit):
# return 'Drv24_' + pair_name + '_' + str(count_of_buys)
# if (baisse > mx) & (current_profit > expected_profit):
# self.trades = list()
@@ -507,7 +514,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
if self.columns_logged % 10 == 0:
self.printLog(
f"| {'Date':<16} | {'Action':<10} |{'Pair':<5}| {'Trade Type':<18} |{'Rate':>8} | {'Dispo':>6} | {'Profit':>10} | {'Pct':>6} | {'max_touch':>11} | {'last_lost':>12} | {'last_max':>7}| {'last_max':>7}|{'Buys':>5}| {'Stake':>5} |"
f"Tdc|{'val':>6}|Distmax|s201d|s5_1d|s5_2d|s5_1h|s5_2h|smt1h|smt2h|"
f"Tdc|{'val':>6}|Distmax|s201d|s5_1d|s5_2d|s241h|s242h|smt1h|smt2h|"
)
self.printLineLog()
df = pd.DataFrame.from_dict(self.pairs, orient='index')
@@ -657,6 +664,8 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe["percent12"] = (dataframe["close"] - dataframe["open"].shift(12)) / dataframe["open"].shift(12)
dataframe = self.calculateDerivation(dataframe, window=3, suffixe="_3")
# dataframe = self.calculateDerivation(dataframe, window=3, suffixe="_6")
dataframe["mid_re_smooth_3"] = self.conditional_smoothing(dataframe['mid_smooth_3'].dropna(),
threshold=0.0005).dropna()
self.calculeDerivees(dataframe, "mid_re_smooth_3")
@@ -668,6 +677,10 @@ class Zeus_8_3_2_B_4_2(IStrategy):
self.calculeDerivees(dataframe, 'rsi')
dataframe['max48'] = talib.MAX(dataframe['close'], timeperiod=48)
dataframe['min36'] = talib.MIN(dataframe['close'], timeperiod=36)
dataframe['max36'] = talib.MAX(dataframe['close'], timeperiod=36)
dataframe['pct36'] = 100 * (dataframe['max36'] - dataframe['min36']) / dataframe['min36']
dataframe['maxpct36'] = talib.MAX(dataframe['pct36'], timeperiod=36)
# Bollinger Bands
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
@@ -681,6 +694,9 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe["bb_width"] = ((dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_upperband"])
# Normalization
dataframe['bb_upperband5'] = dataframe['bb_upperband'].rolling(window=5).mean()
dataframe['bb_lowerband5'] = dataframe['bb_lowerband'].rolling(window=5).mean()
# dataframe = self.calculateRegression(dataframe, column='mid_smooth', window=24, degree=4, future_offset=12)
# dataframe = self.calculateRegression(dataframe, column='mid_smooth_24', window=24, degree=4, future_offset=12)
@@ -724,10 +740,11 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# informative['atr'] = (talib.ATR(informative['high'], informative['low'], informative['close'], timeperiod=14)) / informative['close']
# informative = self.apply_regression_derivatives(informative, column='mid', window=5, degree=4)
period_1d = 60
informative['max12'] = talib.MAX(informative['close'], timeperiod=12)
informative['max60'] = talib.MAX(informative['close'], timeperiod=60)
informative['max60'] = talib.MAX(informative['close'], timeperiod=period_1d)
informative['min12'] = talib.MIN(informative['close'], timeperiod=12)
informative['min60'] = talib.MIN(informative['close'], timeperiod=60)
informative['min60'] = talib.MIN(informative['close'], timeperiod=period_1d)
informative['volatility'] = talib.STDDEV(informative['close'], timeperiod=14) / informative['close']
self.calculeDerivees(informative, 'volatility')
@@ -929,25 +946,71 @@ class Zeus_8_3_2_B_4_2(IStrategy):
pair = metadata['pair']
# self.getOpenTrades()
expected_profit = self.expectedProfit(pair, dataframe.iloc[-1])
# expected_profit = self.expectedProfit(pair, dataframe.iloc[-1])
# self.getBinanceOrderBook(pair, dataframe)
last_candle = dataframe.iloc[-1].squeeze()
# Calcul de la pente (différence entre deux bougies consécutives)
dataframe['bb_ub_slope'] = dataframe['bb_upperband'].diff()
# Détection d'une inversion (changement de signe de la pente)
# inversion = (
# (dataframe['bb_ub_slope'].shift(1).rolling(5).apply(
# lambda x: any(x[i] > 0 and x[i + 1] < 0 for i in range(len(x) - 1)))) == 1
# )
# On regarde si la bande supérieure a atteint un maximum il y a k bougies
# lookback = 5
# inversion = (dataframe['bb_upperband'] == dataframe['bb_upperband'].rolling(lookback).max())
# pente de la bb_upperband
dataframe['bb_ub_slope'] = dataframe['bb_upperband5'].diff()
# évènement "inversion vers le bas" (pente passe de >0 à <=0) sur chaque bougie
cross_down = (dataframe['bb_ub_slope'].shift(1) > 0) & (dataframe['bb_ub_slope'] <= 0)
dataframe['bb_cross_down'] = 10000 * cross_down * dataframe['bb_width'] \
* (dataframe['bb_lowerband'] - dataframe['bb_lowerband'].shift(1)) / dataframe['bb_lowerband']
# vrai si AU MOINS une inversion a eu lieu dans les 5 bougies *précédentes* (on exclut l'actuelle)
inversion_last5 = cross_down.shift(1).rolling(5, min_periods=1).max().astype(bool)
dataframe['inversion_last5'] = inversion_last5
N = 24 # nombre minimum de bougies avant inversion
rise_threshold = 1.0 # % de hausse à ne pas dépasser
# Calcul de la hausse minimale avant inversion
def compute_rise(idx):
if idx < N:
return 0
low_before = dataframe['close'].iloc[idx - N:idx].min() # min des N bougies avant inversion
return (dataframe['close'].iloc[idx] / low_before - 1) * 100
rise = [compute_rise(i) for i in range(len(dataframe))]
dataframe['rise_before_inversion'] = rise
# Filtre : inversion sans forte hausse avant
valid_inversion = inversion_last5 & (dataframe['rise_before_inversion'] <= rise_threshold)
# dataframe.loc[
# (
# (dataframe['percent'] > 0)
# & (dataframe['mid_smooth_deriv1'] >= dataframe['mid_smooth_deriv1'].shift(1))
# ), ['enter_long', 'enter_tag']] = (1, 'down')
factor = 1.01
if pair == "BTC/USDT" or pair == "BTC/USDC":
factor = factor / 2
dataframe.loc[
(
# (dataframe['deriv2_1h'].shift(2) >= dataframe['deriv2_1h'].shift(1))
# & (dataframe['deriv2_1h'].shift(1) <= dataframe['deriv2_1h'])
# (dataframe['deriv1_1h'] >= -0.01)
# & (dataframe['deriv2_1h'] >= -0.00)
(dataframe['mid_smooth_3_deriv1'].shift(2) >= dataframe['mid_smooth_3_deriv1'].shift(1))
& (dataframe['mid_smooth_3_deriv1'].shift(1) <= dataframe['mid_smooth_3_deriv1'])
& (dataframe['close'] < dataframe['max48'] * 0.995)
valid_inversion & inversion_last5
& (dataframe['hapercent'] > 0)
# valid_inversion
# ((dataframe['bb_cross_down'] < - 0.1)
# | (dataframe['bb_cross_down'].shift(1) < - 0.1)
# | (dataframe['bb_cross_down'].shift(2) < - 0.1)
# | (dataframe['bb_cross_down'].shift(3) < - 0.1)
# )
# & (dataframe['hapercent'] > 0)
# & (dataframe['close'] * factor < dataframe['bb_upperband5'])
#
#
# (dataframe['mid_smooth_1h_deriv1'] >= 0)
@@ -1126,7 +1189,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
print("skip dataframe")
return None
if not self.should_enter_trade(pair, last_candle):
if not self.should_enter_trade(pair, last_candle, current_time):
return None
# if self.dp.runmode.value in ('dry_run'):
@@ -1356,6 +1419,13 @@ class Zeus_8_3_2_B_4_2(IStrategy):
def getPct60D(self, pair, last_candle):
return round((last_candle['max60_1d'] - last_candle['min60_1d']) / last_candle['max60_1d'], 4)
def getPctClose60D(self, pair, last_candle):
if last_candle['close'] > last_candle['max60_1d']:
return 1
if last_candle['close'] < last_candle['min60_1d']:
return 0
return round((last_candle['close'] - last_candle['min60_1d']) / (last_candle['max60_1d'] - last_candle['min60_1d']), 4)
def getLimitBuy(self, pair, last_candle, first_pct):
count_of_buys = self.pairs[pair]['count_of_buys']
pct60 = self.getPct60D(pair, last_candle) # exemple 0.3 pour 30%
@@ -1398,10 +1468,17 @@ class Zeus_8_3_2_B_4_2(IStrategy):
def adjust_stake_amount(self, pair: str, last_candle: DataFrame):
# Calculer le minimum des 14 derniers jours
base_stake_amount = self.config.get('stake_amount') # Montant de base configuré
# pct60 = round(100 * self.getPctClose60D(pair, last_candle), 2)
if not pair in ('BTC/USDT', 'BTC/USDC'):
# factors = [1, 1.2, 1.3, 1.4]
adjusted_stake_amount = base_stake_amount
if self.pairs[pair]['count_of_buys'] == 0:
pctClose60 = self.getPctClose60D(pair, last_candle)
adjusted_stake_amount = max(base_stake_amount / 5, base_stake_amount * (1 - pctClose60))
else:
adjusted_stake_amount = self.pairs[pair]['first_amount']
else :
first_price = self.pairs[pair]['first_buy']
if (first_price == 0):
@@ -1413,12 +1490,15 @@ class Zeus_8_3_2_B_4_2(IStrategy):
pct = 100 * (last_max - first_price) / last_max
factor = self.multi_step_interpolate(pct, self.thresholds, self.factors)
adjusted_stake_amount = 0.7 * base_stake_amount * factor # max(base_stake_amount, min(100, base_stake_amount * percent_4))
adjusted_stake_amount = base_stake_amount * factor # max(base_stake_amount, min(100, base_stake_amount * percent_4))
# pct = 100 * abs(self.getPctFirstBuy(pair, last_candle))
#
# factor = self.multi_step_interpolate(pct, self.thresholds, self.factors)
if self.pairs[pair]['count_of_buys'] == 0:
self.pairs[pair]['first_amount'] = adjusted_stake_amount
return adjusted_stake_amount
def calculateAmountSliding(self, pair, last_candle):
@@ -1465,12 +1545,14 @@ class Zeus_8_3_2_B_4_2(IStrategy):
return out_max - position * (out_max - out_min)
def expectedProfit(self, pair: str, last_candle: DataFrame):
pct_to_max = 0.004
max_60 = last_candle['max60_1d']
if last_candle['close'] < max_60:
pct_to_max = 0.25 * (max_60 - last_candle['close']) / max_60
pct_to_max = 0.004 + 0.001 * self.pairs[pair]['count_of_buys']
# pctClose60 = self.getPctClose60D(pair, last_candle)
expected_profit = max(0.004, pct_to_max) # 0.004 + 0.002 * self.pairs[pair]['count_of_buys'] #min(0.01, first_max)
# max_60 = last_candle['max60_1d']
# if last_candle['close'] < max_60:
# pct_to_max = 0.25 * (max_60 - last_candle['close']) / max_60
# pct_to_max = pct_to_max * (2 - pctClose60)
expected_profit = max(0.004, pct_to_max) # 0.004 + 0.002 * self.pairs[pair]['count_of_buys'] #min(0.01, first_max)
# print(
# f"Expected profit price={current_price:.4f} min_max={min_max:.4f} min_14={min_14_days:.4f} max_14={max_14_days:.4f} percent={percent:.4f} expected_profit={expected_profit:.4f}")
@@ -1984,7 +2066,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
print("Moyenne des valeurs par double-tranche :")
print(pivot_mean.round(2))
def should_enter_trade(self, pair: str, last_candle) -> bool:
def should_enter_trade(self, pair: str, last_candle, current_time) -> bool:
limit = 3
@@ -2013,9 +2095,15 @@ class Zeus_8_3_2_B_4_2(IStrategy):
max_nb_trades = 0
total_non_btc = 0
max_pair = ''
limit_amount = 250
max_amount = 0
for p in non_btc_pairs:
max_nb_trades = max(max_nb_trades, self.pairs[p]['count_of_buys'])
max_amount = max(max_amount, self.pairs[p]['total_amount'])
for p in non_btc_pairs:
if (max_nb_trades == self.pairs[p]['count_of_buys'] and max_nb_trades > limit):
# if (max_amount == self.pairs[p]['total_amount'] and max_amount > limit_amount):
max_pair = p
total_non_btc += self.pairs[p]['count_of_buys']

File diff suppressed because it is too large Load Diff