Calcul probabilités

This commit is contained in:
Jérôme Delacotte
2025-05-05 20:34:38 +02:00
parent 8d3f2b0bff
commit 014996f0ab

View File

@@ -86,23 +86,33 @@ class Zeus_8_3_2_B_4_2(IStrategy):
"color": "#da59a6"}, "color": "#da59a6"},
"bb_upperband": { "bb_upperband": {
"color": "#da59a6", "color": "#da59a6",
},
"sma10": {
"color": "blue"
},
"sma5_1h": {
"color": "red"
} }
}, },
"subplots": { "subplots": {
"Pct": { "Pct": {
"sma20_pct": { "sma20_pct": {
'color': "green" 'color': "green"
},
"down_pct": {
"color": "blue"
},
"down_pct_1h": {
"color": "red"
} }
}, },
"Rsi": { "Rsi": {
"rsi60": { "rsi": {
"color": "red" "color": "pink"
}, },
'rsi60_diff': { "rsi_1h": {
"color": "blue" "color": "blue"
},
'rsi60_diff2': {
'color': "green"
} }
}, },
"Rsi_diff": { "Rsi_diff": {
@@ -111,8 +121,21 @@ class Zeus_8_3_2_B_4_2(IStrategy):
}, },
"rsi_diff_2_1h": { "rsi_diff_2_1h": {
"color": "blue" "color": "blue"
},
},
"Down": {
"down_count_1h": {
"color": "green"
},
"up_count_1h": {
"color": "blue"
} }
}, },
# "Diff": {
# "sma10_diff": {
# "color": "#74effc"
# }
# },
"smooth": { "smooth": {
'sma5_diff_sum_1h': { 'sma5_diff_sum_1h': {
"color": "green" "color": "green"
@@ -120,15 +143,15 @@ class Zeus_8_3_2_B_4_2(IStrategy):
'sma5_diff2_sum_1h': { 'sma5_diff2_sum_1h': {
"color": "blue" "color": "blue"
}, },
# 'mid_smooth_deriv1': { 'mid_smooth_deriv1_1d': {
# "color": "blue" "color": "blue"
# }, },
'mid_smooth_deriv1_1h': { 'mid_smooth_deriv1_1h': {
"color": "red" "color": "red"
}, },
# 'mid_smooth_deriv2': { 'mid_smooth_deriv2_1d': {
# "color": "pink" "color": "pink"
# }, },
'mid_smooth_deriv2_1h': { 'mid_smooth_deriv2_1h': {
"color": "#da59a6" "color": "#da59a6"
} }
@@ -207,11 +230,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
self.pairs[pair]['count_of_buys'] = 1 self.pairs[pair]['count_of_buys'] = 1
self.pairs[pair]['current_profit'] = 0 self.pairs[pair]['current_profit'] = 0
self.printLog( self.printLineLog()
f"|{'-' * 18}+{'-' * 12}+{'-' * 5}+{'-' * 20}+{'-' * 9}+{'-' * 8}+{'-' * 10}+{'-' * 8}+{'-' * 13}"
f"+{'-' * 14}+{'-' * 9}+{'-' * 4}+{'-' * 7}|"
)
stake_amount = self.adjust_stake_amount(pair, last_candle) stake_amount = self.adjust_stake_amount(pair, last_candle)
@@ -366,11 +385,11 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# f"|{'-' * 18}+{'-' * 12}+{'-' * 12}+{'-' * 20}+{'-' * 14}+{'-' * 8}+{'-' * 10}+{'-' * 7}+{'-' * 13}+{'-' * 14}+{'-' * 14}+{'-' * 7}+{'-' * 12}|" # f"|{'-' * 18}+{'-' * 12}+{'-' * 12}+{'-' * 20}+{'-' * 14}+{'-' * 8}+{'-' * 10}+{'-' * 7}+{'-' * 13}+{'-' * 14}+{'-' * 14}+{'-' * 7}+{'-' * 12}|"
# ) # )
self.printLog( self.printLog(
f"| {'Date':<16} | {'Action':<10} |{'Pair':<5}| {'Trade Type':<18} | {'Rate':>8} | {'Dispo':>6} | {'Profit':>8} | {'Pct':>6} | {'max_touch':>11} | {'last_lost':>12} | {'last_max':>7} |{'Buys':>4}| {'Stake':>5} |" f"| {'Date':<16} | {'Action':<10} |{'Pair':<5}| {'Trade Type':<18} |{'Rate':>8} | {'Dispo':>6} | {'Profit':>8} | {'Pct':>6} | {'max_touch':>11} | {'last_lost':>12} | {'last_max':>7} |{'Buys':>4}| {'Stake':>5} |"
) f"Tdc|Tdh|Tdd|Tdc|Tdh|Tdd|"
self.printLog(
f"|{'-' * 18}+{'-' * 12}+{'-' * 5}+{'-' * 20}+{'-' * 9}+{'-' * 8}+{'-' * 10}+{'-' * 8}+{'-' * 13}+{'-' * 14}+{'-' * 9}+{'-' * 4}+{'-' * 7}|"
) )
self.printLineLog()
self.columns_logged += 1 self.columns_logged += 1
date = str(date)[:16] if date else "-" date = str(date)[:16] if date else "-"
limit = None limit = None
@@ -415,7 +434,13 @@ class Zeus_8_3_2_B_4_2(IStrategy):
f"| {round(self.pairs[pair]['last_max'], 0) or '-':>7} |{buys or '-':>4}|{stake or '-':>7}" f"| {round(self.pairs[pair]['last_max'], 0) or '-':>7} |{buys or '-':>4}|{stake or '-':>7}"
f"|{round(last_candle['sma5_diff_sum_1h'], 2) or '-':>6}|{round(last_candle['sma5_diff_sum_1d'], 2) or '-':>6}" f"|{round(last_candle['sma5_diff_sum_1h'], 2) or '-':>6}|{round(last_candle['sma5_diff_sum_1d'], 2) or '-':>6}"
f"|{last_candle['tendency'] or '-':>3}|{last_candle['tendency_1h'] or '-':>3}|{last_candle['tendency_1d'] or '-':>3}" f"|{last_candle['tendency'] or '-':>3}|{last_candle['tendency_1h'] or '-':>3}|{last_candle['tendency_1d'] or '-':>3}"
f"|{round(last_candle['mid_smooth_deriv1']):>3}|{round(last_candle['mid_smooth_deriv1_1h']):>5}|{round(last_candle['mid_smooth_deriv1_1d']):>5}|" f"|{round(last_candle['mid_smooth_deriv1']) or '-':>3}|{round(last_candle['mid_smooth_deriv1_1h']) or '-':>5}|{round(last_candle['mid_smooth_deriv1_1d']) or '-' :>5}"
# f"|{round(last_candle['mid_smooth_deriv2']) or '-' :>3 }|{round(last_candle['mid_smooth_deriv2_1h']) or '-':>5}|{round(last_candle['mid_smooth_deriv2_1d']) or '-':>5}"
)
def printLineLog(self):
self.printLog(
f"+{'-' * 18}+{'-' * 12}+{'-' * 5}+{'-' * 20}+{'-' * 9}+{'-' * 8}+{'-' * 10}+{'-' * 8}+{'-' * 13}+{'-' * 14}+{'-' * 9}+{'-' * 4}+{'-' * 7}+"
) )
def printLog(self, str): def printLog(self, str):
@@ -452,8 +477,6 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe['haclose'] = heikinashi['close'] dataframe['haclose'] = heikinashi['close']
dataframe['hapercent'] = (dataframe['haclose'] - dataframe['haopen']) / dataframe['haclose'] dataframe['hapercent'] = (dataframe['haclose'] - dataframe['haopen']) / dataframe['haclose']
dataframe['close_02'] = dataframe['haclose'] * 1.02
dataframe['pct_change'] = dataframe['close'].pct_change(5) dataframe['pct_change'] = dataframe['close'].pct_change(5)
dataframe = self.calculateTendency(dataframe) dataframe = self.calculateTendency(dataframe)
@@ -474,6 +497,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe['sma5'] = talib.SMA(dataframe, timeperiod=5) dataframe['sma5'] = talib.SMA(dataframe, timeperiod=5)
dataframe['sma10'] = talib.SMA(dataframe, timeperiod=10) dataframe['sma10'] = talib.SMA(dataframe, timeperiod=10)
dataframe['sma10_diff'] = 100 * dataframe['sma10'].diff() / dataframe['sma10']
dataframe['sma20'] = talib.SMA(dataframe, timeperiod=20) dataframe['sma20'] = talib.SMA(dataframe, timeperiod=20)
dataframe['sma20_pct'] = 100 * dataframe['sma20'].diff() / dataframe['sma20'] dataframe['sma20_pct'] = 100 * dataframe['sma20'].diff() / dataframe['sma20']
dataframe['sma20_smooth'] = dataframe['sma20'].ewm(span=5).mean() dataframe['sma20_smooth'] = dataframe['sma20'].ewm(span=5).mean()
@@ -533,28 +557,24 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe['highest_4_average'] = highest_4.mean() dataframe['highest_4_average'] = highest_4.mean()
# Compter les baisses consécutives # Compter les baisses consécutives
dataframe['down'] = dataframe['hapercent'] <= 0.0001 self.calculateDownAndUp(dataframe, limit=0.0001)
dataframe['up'] = dataframe['hapercent'] >= 0.0001
dataframe['down_count'] = - dataframe['down'].astype(int) * (
dataframe['down'].groupby((dataframe['down'] != dataframe['down'].shift()).cumsum()).cumcount() + 1)
dataframe['up_count'] = dataframe['up'].astype(int) * (
dataframe['up'].groupby((dataframe['up'] != dataframe['up'].shift()).cumsum()).cumcount() + 1)
dataframe['down_tag'] = (dataframe['down_count'] < -7)
dataframe['up_tag'] = (dataframe['up_count'] > 7)
# Créer une colonne vide
dataframe['down_pct'] = self.calculateUpDownPct(dataframe, 'down_count')
dataframe['up_pct'] = self.calculateUpDownPct(dataframe, 'up_count')
dataframe = self.apply_regression_derivatives(dataframe, column='mid', window=24, degree=3) dataframe = self.apply_regression_derivatives(dataframe, column='mid', window=24, degree=3)
# Normaliser les données de 'close' # Normaliser les données de 'close'
# normalized_close = self.min_max_scaling(dataframe['close']) # normalized_close = self.min_max_scaling(dataframe['close'])
################### INFORMATIVE 1h ################### INFORMATIVE 1h
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h") informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
heikinashi = qtpylib.heikinashi(informative)
informative['haopen'] = heikinashi['open']
informative['haclose'] = heikinashi['close']
informative['hapercent'] = (informative['haclose'] - informative['haopen']) / informative['haclose']
informative = self.calculateTendency(informative, 3) informative = self.calculateTendency(informative, 3)
informative = self.apply_regression_derivatives(informative, column='mid', window=5, degree=3) informative = self.apply_regression_derivatives(informative, column='mid', window=5, degree=3)
informative['volatility'] = talib.STDDEV(informative['close'], timeperiod=14) / informative['close'] informative['volatility'] = talib.STDDEV(informative['close'], timeperiod=14) / informative['close']
informative['atr'] = (talib.ATR(informative['high'], informative['low'], informative['close'], timeperiod=14)) / informative['close'] informative['atr'] = (talib.ATR(informative['high'], informative['low'], informative['close'], timeperiod=14)) / informative['close']
informative['rsi'] = talib.RSI(informative['close'], length=7) informative['rsi'] = talib.RSI(informative['close']) #, timeperiod=7)
informative['rsi_diff'] = informative['rsi'].diff() informative['rsi_diff'] = informative['rsi'].diff()
informative['rsi_sum'] = (informative['rsi'].rolling(7).sum() - 350) / 7 informative['rsi_sum'] = (informative['rsi'].rolling(7).sum() - 350) / 7
informative['rsi_sum_diff'] = informative['rsi_sum'].diff() informative['rsi_sum_diff'] = informative['rsi_sum'].diff()
@@ -565,6 +585,11 @@ class Zeus_8_3_2_B_4_2(IStrategy):
informative['sma5_diff_sum'] = (informative['sma5_pct'].rolling(5).sum()) / 5 informative['sma5_diff_sum'] = (informative['sma5_pct'].rolling(5).sum()) / 5
informative['sma5_diff2_sum'] = informative['sma5_diff_sum'].diff() informative['sma5_diff2_sum'] = informative['sma5_diff_sum'].diff()
self.calculateDownAndUp(informative, limit=0.0012)
if self.dp.runmode.value in ('backtest'):
self.test_signal_success(informative, percent=0.01, window_size=24)
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
################### INFORMATIVE 1d ################### INFORMATIVE 1d
@@ -572,7 +597,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
informative = self.calculateTendency(informative, 3) informative = self.calculateTendency(informative, 3)
informative = self.apply_regression_derivatives(informative, column='mid', window=5, degree=3) informative = self.apply_regression_derivatives(informative, column='mid', window=5, degree=3)
informative['rsi'] = talib.RSI(informative['close'], length=7) informative['rsi'] = talib.RSI(informative['close']) #, timeperiod=7)
informative['rsi_diff'] = informative['rsi'].diff() informative['rsi_diff'] = informative['rsi'].diff()
informative['rsi_sum'] = (informative['rsi'].rolling(7).sum() - 350) / 7 informative['rsi_sum'] = (informative['rsi'].rolling(7).sum() - 350) / 7
informative['rsi_diff_2'] = informative['rsi_diff'].diff() informative['rsi_diff_2'] = informative['rsi_diff'].diff()
@@ -713,16 +738,29 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# self.getBinanceOrderBook(pair, dataframe) # self.getBinanceOrderBook(pair, dataframe)
# if self.dp.runmode.value in ('backtest'):
# self.test_signal_success(dataframe, 0.005)
return dataframe return dataframe
def calculateDownAndUp(self, dataframe, limit=0.0001):
dataframe['down'] = dataframe['hapercent'] <= limit
dataframe['up'] = dataframe['hapercent'] >= limit
dataframe['down_count'] = - dataframe['down'].astype(int) * (
dataframe['down'].groupby((dataframe['down'] != dataframe['down'].shift()).cumsum()).cumcount() + 1)
dataframe['up_count'] = dataframe['up'].astype(int) * (
dataframe['up'].groupby((dataframe['up'] != dataframe['up'].shift()).cumsum()).cumcount() + 1)
dataframe['down_tag'] = (dataframe['down_count'] < -7)
dataframe['up_tag'] = (dataframe['up_count'] > 7)
# Créer une colonne vide
dataframe['down_pct'] = self.calculateUpDownPct(dataframe, 'down_count')
dataframe['up_pct'] = self.calculateUpDownPct(dataframe, 'up_count')
def calculateTendency(self, dataframe, window=12): def calculateTendency(self, dataframe, window=12):
dataframe['mid'] = dataframe['open'] + (dataframe['close'] - dataframe['open']) / 2 dataframe['mid'] = dataframe['open'] + (dataframe['close'] - dataframe['open']) / 2
# 2. Calcul du lissage sur 200 bougies par moyenne mobile médiane # 2. Calcul du lissage sur 200 bougies par moyenne mobile médiane
dataframe['mid_smooth'] = dataframe['mid'].rolling(window=window, center=True, min_periods=1).median().rolling( dataframe['mid_smooth'] = dataframe['mid'].rolling(window=window, center=True, min_periods=1).median().rolling(
3).mean() 3).mean()
dataframe['mid_smooth_tag_max'] = (dataframe['mid_smooth'].shift(1)) == 0 & (dataframe['mid_smooth'] < 0)
dataframe['mid_smooth_tag_min'] = (dataframe['mid_smooth'].shift(1)) == 0 & (dataframe['mid_smooth'] > 0)
# 2. Dérivée première = différence entre deux bougies successives # 2. Dérivée première = différence entre deux bougies successives
dataframe['mid_smooth_deriv1'] = round(100000 * dataframe['mid_smooth'].pct_change(), 2) dataframe['mid_smooth_deriv1'] = round(100000 * dataframe['mid_smooth'].pct_change(), 2)
# 3. Dérivée seconde = différence de la dérivée première # 3. Dérivée seconde = différence de la dérivée première
@@ -1553,5 +1591,34 @@ class Zeus_8_3_2_B_4_2(IStrategy):
return df return df
def test_signal_success(self, df, percent=0.03, window_size=36):
"""
df : DataFrame avec colonnes ['close', 'high', ...]
percent : hausse recherchée (ex: 0.03 pour +3%)
window_size : nombre de bougies (ex: 36 pour 3h en 5m)
"""
# Exemple condition : RSI < 30 et EMA20 > SMA50
condition = (df['down_count'] == 0) & (df['down_count'].shift(1) < 0) & (df['down_pct'].shift(1) < -3)
hits = 0
total = 0
for idx in df[condition].index:
price_now = df.loc[idx, 'close']
idx_pos = df.index.get_loc(idx)
# Fenêtre de h heures
future_idx = df.index[idx_pos + 1: idx_pos + 1 + window_size]
if len(future_idx) < window_size:
continue
future_highs = df.loc[future_idx, 'high']
if (future_highs >= price_now * (1 + percent)).any():
hits += 1
total += 1
prob = hits / total if total > 0 else 0
print(f"{hits}/{total} hausses >= {percent*100:.1f}% dans {window_size} bougies → probabilité : {prob:.2%}")
return prob