From 70e1a57e47a090c129e8220f4ce67c388cb0dfbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Delacotte?= Date: Wed, 25 Feb 2026 11:24:48 +0100 Subject: [PATCH] Zeus god genes --- Zeus_8_3_2_B_4_2.json | 16 +- Zeus_8_3_2_B_4_2.py | 1263 ++++++++++++++++++++++++++++++++--------- 2 files changed, 1003 insertions(+), 276 deletions(-) diff --git a/Zeus_8_3_2_B_4_2.json b/Zeus_8_3_2_B_4_2.json index 843c2c6..f7a9121 100644 --- a/Zeus_8_3_2_B_4_2.json +++ b/Zeus_8_3_2_B_4_2.json @@ -20,17 +20,13 @@ "mise_factor_buy": 0.01, "pct": 0.029, "pct_inc": 0.0027, - "bm1": 800, - "bm2": 200, - "bm3": 0, - "bm4": 800, - "bp0": 0, - "bp1": 0, - "bp2": 800, - "bp3": 0, - "bp4": 0 + "buy_filter_indicator": "rsi5_deriv1_1d", + "buy_indicator0": "rsi60_inv_hau", + "buy_indicator1": "mid_smooth_48_inv_bas", + "buy_indicator2": "sma24_inv_bas_1h", + "buy_indicator3": "bb_lowerband3_inv_hau_1h" } }, "ft_stratparam_v": 1, - "export_time": "2026-02-15 14:23:04.601092+00:00" + "export_time": "2026-02-18 16:50:53.773582+00:00" } \ No newline at end of file diff --git a/Zeus_8_3_2_B_4_2.py b/Zeus_8_3_2_B_4_2.py index 75ab2bc..bd661f1 100644 --- a/Zeus_8_3_2_B_4_2.py +++ b/Zeus_8_3_2_B_4_2.py @@ -105,10 +105,507 @@ def pprint_df(dframe): print(tabulate(dframe, headers='keys', tablefmt='psql', showindex=False)) +# ######################################################################################################################### +# Add your lib to import here +# TODO: talib is fast but have not more indicators +# import talib.abstract as ta +from functools import reduce +from random import shuffle +# TODO: this gene is removed 'MAVP' cuz or error on periods +all_god_genes = { + 'Overlap Studies': { + 'BBANDS-0', # Bollinger Bands + 'BBANDS-1', # Bollinger Bands + 'BBANDS-2', # Bollinger Bands + 'DEMA', # Double Exponential Moving Average + 'EMA', # Exponential Moving Average + 'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline + 'KAMA', # Kaufman Adaptive Moving Average + 'MA', # Moving average + 'MAMA-0', # MESA Adaptive Moving Average + 'MAMA-1', # MESA Adaptive Moving Average + # TODO: Fix this + # 'MAVP', # Moving average with variable period + 'MIDPOINT', # MidPoint over period + 'MIDPRICE', # Midpoint Price over period + 'SAR', # Parabolic SAR + 'SAREXT', # Parabolic SAR - Extended + 'SMA', # Simple Moving Average + 'T3', # Triple Exponential Moving Average (T3) + 'TEMA', # Triple Exponential Moving Average + 'TRIMA', # Triangular Moving Average + 'WMA', # Weighted Moving Average + }, + 'Momentum Indicators': { + 'ADX', # Average Directional Movement Index + 'ADXR', # Average Directional Movement Index Rating + 'APO', # Absolute Price Oscillator + 'AROON-0', # Aroon + 'AROON-1', # Aroon + 'AROONOSC', # Aroon Oscillator + 'BOP', # Balance Of Power + 'CCI', # Commodity Channel Index + 'CMO', # Chande Momentum Oscillator + 'DX', # Directional Movement Index + 'MACD-0', # Moving Average Convergence/Divergence + 'MACD-1', # Moving Average Convergence/Divergence + 'MACD-2', # Moving Average Convergence/Divergence + 'MACDEXT-0', # MACD with controllable MA type + 'MACDEXT-1', # MACD with controllable MA type + 'MACDEXT-2', # MACD with controllable MA type + 'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26 + 'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26 + 'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26 + 'MFI', # Money Flow Index + 'MINUS_DI', # Minus Directional Indicator + 'MINUS_DM', # Minus Directional Movement + 'MOM', # Momentum + 'PLUS_DI', # Plus Directional Indicator + 'PLUS_DM', # Plus Directional Movement + 'PPO', # Percentage Price Oscillator + 'ROC', # Rate of change : ((price/prevPrice)-1)*100 + # Rate of change Percentage: (price-prevPrice)/prevPrice + 'ROCP', + 'ROCR', # Rate of change ratio: (price/prevPrice) + # Rate of change ratio 100 scale: (price/prevPrice)*100 + 'ROCR100', + 'RSI', # Relative Strength Index + 'STOCH-0', # Stochastic + 'STOCH-1', # Stochastic + 'STOCHF-0', # Stochastic Fast + 'STOCHF-1', # Stochastic Fast + 'STOCHRSI-0', # Stochastic Relative Strength Index + 'STOCHRSI-1', # Stochastic Relative Strength Index + # 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA + 'TRIX', + 'ULTOSC', # Ultimate Oscillator + 'WILLR', # Williams' %R + }, + 'Volume Indicators': { + 'AD', # Chaikin A/D Line + 'ADOSC', # Chaikin A/D Oscillator + 'OBV', # On Balance Volume + }, + 'Volatility Indicators': { + 'ATR', # Average True Range + 'NATR', # Normalized Average True Range + 'TRANGE', # True Range + }, + 'Price Transform': { + 'AVGPRICE', # Average Price + 'MEDPRICE', # Median Price + 'TYPPRICE', # Typical Price + 'WCLPRICE', # Weighted Close Price + }, + 'Cycle Indicators': { + 'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period + 'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase + 'HT_PHASOR-0', # Hilbert Transform - Phasor Components + 'HT_PHASOR-1', # Hilbert Transform - Phasor Components + 'HT_SINE-0', # Hilbert Transform - SineWave + 'HT_SINE-1', # Hilbert Transform - SineWave + 'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode + }, + 'Pattern Recognition': { + 'CDL2CROWS', # Two Crows + 'CDL3BLACKCROWS', # Three Black Crows + 'CDL3INSIDE', # Three Inside Up/Down + 'CDL3LINESTRIKE', # Three-Line Strike + 'CDL3OUTSIDE', # Three Outside Up/Down + 'CDL3STARSINSOUTH', # Three Stars In The South + 'CDL3WHITESOLDIERS', # Three Advancing White Soldiers + 'CDLABANDONEDBABY', # Abandoned Baby + 'CDLADVANCEBLOCK', # Advance Block + 'CDLBELTHOLD', # Belt-hold + 'CDLBREAKAWAY', # Breakaway + 'CDLCLOSINGMARUBOZU', # Closing Marubozu + 'CDLCONCEALBABYSWALL', # Concealing Baby Swallow + 'CDLCOUNTERATTACK', # Counterattack + 'CDLDARKCLOUDCOVER', # Dark Cloud Cover + 'CDLDOJI', # Doji + 'CDLDOJISTAR', # Doji Star + 'CDLDRAGONFLYDOJI', # Dragonfly Doji + 'CDLENGULFING', # Engulfing Pattern + 'CDLEVENINGDOJISTAR', # Evening Doji Star + 'CDLEVENINGSTAR', # Evening Star + 'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines + 'CDLGRAVESTONEDOJI', # Gravestone Doji + 'CDLHAMMER', # Hammer + 'CDLHANGINGMAN', # Hanging Man + 'CDLHARAMI', # Harami Pattern + 'CDLHARAMICROSS', # Harami Cross Pattern + 'CDLHIGHWAVE', # High-Wave Candle + 'CDLHIKKAKE', # Hikkake Pattern + 'CDLHIKKAKEMOD', # Modified Hikkake Pattern + 'CDLHOMINGPIGEON', # Homing Pigeon + 'CDLIDENTICAL3CROWS', # Identical Three Crows + 'CDLINNECK', # In-Neck Pattern + 'CDLINVERTEDHAMMER', # Inverted Hammer + 'CDLKICKING', # Kicking + 'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu + 'CDLLADDERBOTTOM', # Ladder Bottom + 'CDLLONGLEGGEDDOJI', # Long Legged Doji + 'CDLLONGLINE', # Long Line Candle + 'CDLMARUBOZU', # Marubozu + 'CDLMATCHINGLOW', # Matching Low + 'CDLMATHOLD', # Mat Hold + 'CDLMORNINGDOJISTAR', # Morning Doji Star + 'CDLMORNINGSTAR', # Morning Star + 'CDLONNECK', # On-Neck Pattern + 'CDLPIERCING', # Piercing Pattern + 'CDLRICKSHAWMAN', # Rickshaw Man + 'CDLRISEFALL3METHODS', # Rising/Falling Three Methods + 'CDLSEPARATINGLINES', # Separating Lines + 'CDLSHOOTINGSTAR', # Shooting Star + 'CDLSHORTLINE', # Short Line Candle + 'CDLSPINNINGTOP', # Spinning Top + 'CDLSTALLEDPATTERN', # Stalled Pattern + 'CDLSTICKSANDWICH', # Stick Sandwich + # Takuri (Dragonfly Doji with very long lower shadow) + 'CDLTAKURI', + 'CDLTASUKIGAP', # Tasuki Gap + 'CDLTHRUSTING', # Thrusting Pattern + 'CDLTRISTAR', # Tristar Pattern + 'CDLUNIQUE3RIVER', # Unique 3 River + 'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows + 'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods + + }, + 'Statistic Functions': { + 'BETA', # Beta + 'CORREL', # Pearson's Correlation Coefficient (r) + 'LINEARREG', # Linear Regression + 'LINEARREG_ANGLE', # Linear Regression Angle + 'LINEARREG_INTERCEPT', # Linear Regression Intercept + 'LINEARREG_SLOPE', # Linear Regression Slope + 'STDDEV', # Standard Deviation + 'TSF', # Time Series Forecast + 'VAR', # Variance + }, + 'MINE': { + 'sma3_inv', 'sma3_inv', 'mid_smooth_3_inv', 'mid_smooth_3_inv', 'sma5_inv', 'sma5_inv', 'mid_smooth_5_inv', + 'mid_smooth_5_inv', 'sma12_inv', 'sma12_inv', 'mid_smooth_12_inv', 'mid_smooth_12_inv', 'sma24_inv', 'sma24_inv', + 'mid_smooth_24_inv', 'mid_smooth_24_inv', 'sma48_inv', 'sma48_inv', 'mid_smooth_48_inv', 'mid_smooth_48_inv', + 'sma60_inv', 'sma60_inv', 'mid_smooth_60_inv', 'mid_smooth_60_inv', 'rsi_inv', 'rsi_inv', 'rsi3_inv', + 'rsi3_inv', 'bb_lowerband3_inv', 'bb_lowerband3_inv', 'bb_upperband3_inv', 'bb_upperband3_inv', 'rsi5_inv', + 'rsi5_inv', 'bb_lowerband5_inv', 'bb_lowerband5_inv', 'bb_upperband5_inv', 'bb_upperband5_inv', 'rsi12_inv', + 'rsi12_inv', 'bb_lowerband12_inv', 'bb_lowerband12_inv', 'bb_upperband12_inv', 'bb_upperband12_inv', 'rsi24_inv', + 'rsi24_inv', 'bb_lowerband24_inv', 'bb_lowerband24_inv', 'bb_upperband24_inv', 'bb_upperband24_inv', 'rsi48_inv', + 'rsi48_inv', 'bb_lowerband48_inv', 'bb_lowerband48_inv', 'bb_upperband48_inv', 'bb_upperband48_inv', 'rsi60_inv', + 'rsi60_inv', 'bb_lowerband60_inv', 'bb_lowerband60_inv', 'bb_upperband60_inv', 'bb_upperband60_inv', + + # 'sma3_inv_1h', + # 'sma3_inv_1h', 'mid_smooth_3_inv_1h', 'mid_smooth_3_inv_1h', 'sma5_inv_1h', 'sma5_inv_1h', 'mid_smooth_5_inv_1h', + # 'mid_smooth_5_inv_1h', 'sma12_inv_1h', 'sma12_inv_1h', 'mid_smooth_12_inv_1h', 'mid_smooth_12_inv_1h', 'sma24_inv_1h', + # 'sma24_inv_1h', 'mid_smooth_24_inv_1h', 'mid_smooth_24_inv_1h', 'sma48_inv_1h', 'sma48_inv_1h', + # 'mid_smooth_48_inv_1h', 'mid_smooth_48_inv_1h', 'sma60_inv_1h', 'sma60_inv_1h', 'mid_smooth_60_inv_1h', + # 'mid_smooth_60_inv_1h', 'rsi_inv_1h', 'rsi_inv_1h', 'rsi3_inv_1h', 'rsi3_inv_1h', 'bb_lowerband3_inv_1h', + # 'bb_lowerband3_inv_1h', 'bb_upperband3_inv_1h', 'bb_upperband3_inv_1h', 'rsi5_inv_1h', 'rsi5_inv_1h', + # 'bb_lowerband5_inv_1h', 'bb_lowerband5_inv_1h', 'bb_upperband5_inv_1h', 'bb_upperband5_inv_1h', 'rsi12_inv_1h', + # 'rsi12_inv_1h', 'bb_lowerband12_inv_1h', 'bb_lowerband12_inv_1h', 'bb_upperband12_inv_1h', 'bb_upperband12_inv_1h', + # 'rsi24_inv_1h', 'rsi24_inv_1h', 'bb_lowerband24_inv_1h', 'bb_lowerband24_inv_1h', 'bb_upperband24_inv_1h', + # 'bb_upperband24_inv_1h', 'rsi48_inv_1h', 'rsi48_inv_1h', 'bb_lowerband48_inv_1h', 'bb_lowerband48_inv_1h', + # 'bb_upperband48_inv_1h', 'bb_upperband48_inv_1h', 'rsi60_inv_1h', 'rsi60_inv_1h', 'bb_lowerband60_inv_1h', + # 'bb_lowerband60_inv_1h', 'bb_upperband60_inv_1h', 'bb_upperband60_inv_1h', + # 'sma3_inv_1d', 'sma3_inv_1d', + # 'mid_smooth_3_inv_1d', 'mid_smooth_3_inv_1d', 'sma5_inv_1d', 'sma5_inv_1d', 'mid_smooth_5_inv_1d', + # 'mid_smooth_5_inv_1d', 'sma12_inv_1d', 'sma12_inv_1d', 'mid_smooth_12_inv_1d', 'mid_smooth_12_inv_1d', 'sma24_inv_1d', + # 'sma24_inv_1d', 'mid_smooth_24_inv_1d', 'mid_smooth_24_inv_1d', 'sma48_inv_1d', 'sma48_inv_1d', + # 'mid_smooth_48_inv_1d', 'mid_smooth_48_inv_1d', 'sma60_inv_1d', 'sma60_inv_1d', 'mid_smooth_60_inv_1d', + # 'mid_smooth_60_inv_1d', 'rsi_inv_1d', 'rsi_inv_1d', 'rsi3_inv_1d', 'rsi3_inv_1d', 'bb_lowerband3_inv_1d', + # 'bb_lowerband3_inv_1d', 'bb_upperband3_inv_1d', 'bb_upperband3_inv_1d', 'rsi5_inv_1d', 'rsi5_inv_1d', + # 'bb_lowerband5_inv_1d', 'bb_lowerband5_inv_1d', 'bb_upperband5_inv_1d', 'bb_upperband5_inv_1d', 'rsi12_inv_1d', + # 'rsi12_inv_1d', 'bb_lowerband12_inv_1d', 'bb_lowerband12_inv_1d', 'bb_upperband12_inv_1d', 'bb_upperband12_inv_1d', + # 'rsi24_inv_1d', 'rsi24_inv_1d', 'bb_lowerband24_inv_1d', 'bb_lowerband24_inv_1d', 'bb_upperband24_inv_1d', + # 'bb_upperband24_inv_1d', 'rsi48_inv_1d', 'rsi48_inv_1d', 'bb_lowerband48_inv_1d', 'bb_lowerband48_inv_1d', + # 'bb_upperband48_inv_1d', 'bb_upperband48_inv_1d', 'rsi60_inv_1d', 'rsi60_inv_1d', 'bb_lowerband60_inv_1d', + # 'bb_lowerband60_inv_1d', 'bb_upperband60_inv_1d', 'bb_upperband60_inv_1d' + + # # 'sma3_deriv1', 'sma3_deriv2', 'mid_smooth_3_deriv1', 'mid_smooth_3_deriv2', 'sma5_deriv1', 'sma5_deriv2', 'mid_smooth_5_deriv1', + # # 'mid_smooth_5_deriv2', 'sma12_deriv1', 'sma12_deriv2', 'mid_smooth_12_deriv1', 'mid_smooth_12_deriv2', + # 'sma24_deriv1', 'sma24_deriv2', 'mid_smooth_24_deriv1', 'mid_smooth_24_deriv2', 'sma48_deriv1', 'sma48_deriv2', 'mid_smooth_48_deriv1', 'mid_smooth_48_deriv2', + # 'sma60_deriv1', 'sma60_deriv2', 'mid_smooth_60_deriv1', 'mid_smooth_60_deriv2', + # #'rsi_deriv1', 'rsi_deriv2', 'rsi3_deriv1', 'rsi3_deriv2', + # # 'bb_lowerband3_deriv1', 'bb_lowerband3_deriv2', 'bb_upperband3_deriv1', 'bb_upperband3_deriv2', 'rsi5_deriv1', 'rsi5_deriv2', + # # 'bb_lowerband5_deriv1', 'bb_lowerband5_deriv2', 'bb_upperband5_deriv1', 'bb_upperband5_deriv2', 'rsi12_deriv1', 'rsi12_deriv2', + # # 'bb_lowerband12_deriv1', 'bb_lowerband12_deriv2', 'bb_upperband12_deriv1', 'bb_upperband12_deriv2', 'rsi24_deriv1', 'rsi24_deriv2', + # # 'bb_lowerband24_deriv1', 'bb_lowerband24_deriv2', 'bb_upperband24_deriv1', 'bb_upperband24_deriv2', 'rsi48_deriv1', 'rsi48_deriv2', + # # 'bb_lowerband48_deriv1', 'bb_lowerband48_deriv2', 'bb_upperband48_deriv1', 'bb_upperband48_deriv2', 'rsi60_deriv1', 'rsi60_deriv2', + # # 'bb_lowerband60_deriv1', 'bb_lowerband60_deriv2', 'bb_upperband60_deriv1', 'bb_upperband60_deriv2', + # + # 'sma3_deriv1_1h', 'sma3_deriv2_1h', + # 'mid_smooth_3_deriv1_1h', 'mid_smooth_3_deriv2_1h', 'sma5_deriv1_1h', 'sma5_deriv2_1h', 'mid_smooth_5_deriv1_1h', 'mid_smooth_5_deriv2_1h', + # 'sma12_deriv1_1h', 'sma12_deriv2_1h', 'mid_smooth_12_deriv1_1h', 'mid_smooth_12_deriv2_1h', 'sma24_deriv1_1h', 'sma24_deriv2_1h', + # 'mid_smooth_24_deriv1_1h', 'mid_smooth_24_deriv2_1h', 'sma48_deriv1_1h', 'sma48_deriv2_1h', 'mid_smooth_48_deriv1_1h', + # 'mid_smooth_48_deriv2_1h', 'sma60_deriv1_1h', 'sma60_deriv2_1h', 'mid_smooth_60_deriv1_1h', 'mid_smooth_60_deriv2_1h', + # # 'rsi_deriv1_1h', + # # 'rsi_deriv2_1h', 'rsi3_deriv1_1h', 'rsi3_deriv2_1h', 'bb_lowerband3_deriv1_1h', 'bb_lowerband3_deriv2_1h', 'bb_upperband3_deriv1_1h', + # # 'bb_upperband3_deriv2_1h', 'rsi5_deriv1_1h', 'rsi5_deriv2_1h', 'bb_lowerband5_deriv1_1h', 'bb_lowerband5_deriv2_1h', + # # 'bb_upperband5_deriv1_1h', 'bb_upperband5_deriv2_1h', 'rsi12_deriv1_1h', 'rsi12_deriv2_1h', 'bb_lowerband12_deriv1_1h', + # # 'bb_lowerband12_deriv2_1h', 'bb_upperband12_deriv1_1h', 'bb_upperband12_deriv2_1h', 'rsi24_deriv1_1h', 'rsi24_deriv2_1h', + # # 'bb_lowerband24_deriv1_1h', 'bb_lowerband24_deriv2_1h', 'bb_upperband24_deriv1_1h', 'bb_upperband24_deriv2_1h', 'rsi48_deriv1_1h', + # # 'rsi48_deriv2_1h', 'bb_lowerband48_deriv1_1h', 'bb_lowerband48_deriv2_1h', 'bb_upperband48_deriv1_1h', 'bb_upperband48_deriv2_1h', + # # 'rsi60_deriv1_1h', 'rsi60_deriv2_1h', 'bb_lowerband60_deriv1_1h', 'bb_lowerband60_deriv2_1h', 'bb_upperband60_deriv1_1h', + # + # # 'bb_upperband60_deriv2_1h', 'sma3_deriv1_1d', 'sma3_deriv2_1d', 'mid_smooth_3_deriv1_1d', 'mid_smooth_3_deriv2_1d', 'sma5_deriv1_1d', + # # 'sma5_deriv2_1d', 'mid_smooth_5_deriv1_1d', 'mid_smooth_5_deriv2_1d', 'sma12_deriv1_1d', 'sma12_deriv2_1d', 'mid_smooth_12_deriv1_1d', + # # 'mid_smooth_12_deriv2_1d', 'sma24_deriv1_1d', 'sma24_deriv2_1d', 'mid_smooth_24_deriv1_1d', 'mid_smooth_24_deriv2_1d', 'sma48_deriv1_1d', + # # 'sma48_deriv2_1d', 'mid_smooth_48_deriv1_1d', 'mid_smooth_48_deriv2_1d', 'sma60_deriv1_1d', 'sma60_deriv2_1d', 'mid_smooth_60_deriv1_1d', + # # 'mid_smooth_60_deriv2_1d', 'rsi_deriv1_1d', 'rsi_deriv2_1d', 'rsi3_deriv1_1d', 'rsi3_deriv2_1d', 'bb_lowerband3_deriv1_1d', + # # 'bb_lowerband3_deriv2_1d', 'bb_upperband3_deriv1_1d', 'bb_upperband3_deriv2_1d', 'rsi5_deriv1_1d', 'rsi5_deriv2_1d', + # # 'bb_lowerband5_deriv1_1d', 'bb_lowerband5_deriv2_1d', 'bb_upperband5_deriv1_1d', 'bb_upperband5_deriv2_1d', 'rsi12_deriv1_1d', + # # 'rsi12_deriv2_1d', 'bb_lowerband12_deriv1_1d', 'bb_lowerband12_deriv2_1d', 'bb_upperband12_deriv1_1d', 'bb_upperband12_deriv2_1d', + # # 'rsi24_deriv1_1d', 'rsi24_deriv2_1d', 'bb_lowerband24_deriv1_1d', 'bb_lowerband24_deriv2_1d', 'bb_upperband24_deriv1_1d', + # # 'bb_upperband24_deriv2_1d', 'rsi48_deriv1_1d', 'rsi48_deriv2_1d', 'bb_lowerband48_deriv1_1d', 'bb_lowerband48_deriv2_1d', + # # 'bb_upperband48_deriv1_1d', 'bb_upperband48_deriv2_1d', 'rsi60_deriv1_1d', 'rsi60_deriv2_1d', 'bb_lowerband60_deriv1_1d', + # # 'bb_lowerband60_deriv2_1d', 'bb_upperband60_deriv1_1d', 'bb_upperband60_deriv2_1d', + # + # 'mid_smooth_1h_deriv1', 'mid_smooth_1h_deriv2', 'mid_smooth_5h_deriv1', 'mid_smooth_5h_deriv2' + } + +} +god_genes = set() +########################### SETTINGS ############################## + +# god_genes = {'SMA'} +# god_genes |= all_god_genes['Overlap Studies'] +# god_genes |= all_god_genes['Momentum Indicators'] +# god_genes |= all_god_genes['Volume Indicators'] +# god_genes |= all_god_genes['Volatility Indicators'] +# god_genes |= all_god_genes['Price Transform'] +# god_genes |= all_god_genes['Cycle Indicators'] +# god_genes |= all_god_genes['Pattern Recognition'] +# god_genes |= all_god_genes['Statistic Functions'] +# god_genes |= all_god_genes['MINE'] + +timeperiods2 = [24, 48, 60, 120, 240] +timeperiods = [3, 5, 12, 24, 48, 60] +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 devided to cross indicator, bigger than real number + # "/=R", # Normalized indicator devided to cross indicator, equal with real number + # "/ 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].div(dataframe[crossed_indicator]) > real_num) + elif operator == "/=R": + condition = (np.isclose(dataframe[indicator].div(dataframe[crossed_indicator]), real_num)) + elif operator == "/ 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 +# ######################################################################################################################### + + def generate_state_params(states, mises): params = {} for s in states: @@ -308,11 +805,9 @@ class Zeus_8_3_2_B_4_2(IStrategy): pct = DecimalParameter(0.005, 0.05, default=0.012, decimals=3, space='buy', optimize=False, load=True) pct_inc = DecimalParameter(0.0001, 0.003, default=0.0022, decimals=4, space='buy', optimize=False, load=True) - - - mises = [0,200,400,600,800,1000] - states = [-4, -3, -2, -1, 0, 1, 2, 3, 4] - locals().update(generate_state_params(states, mises)) + # mises = [0,200,400,600,800,1000] + # states = [-4, -3, -2, -1, 0, 1, 2, 3, 4] + # locals().update(generate_state_params(states, mises)) labels = ['B3', 'B2', 'B1', 'N0', 'H1', 'H2', 'H3'] index_labels = ['B3', 'B2', 'B1', 'N0', 'H1', 'H2', 'H3'] @@ -341,6 +836,80 @@ class Zeus_8_3_2_B_4_2(IStrategy): should_enter_trade_count = 0 + + # #################### END OF RESULT PLACE #################### + + # ######################################################################################################################### + + buy_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="SMA-100", space='buy') + buy_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="SMA-100", space='buy') + buy_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="SMA-100", space='buy') + buy_indicator3 = CategoricalParameter(god_genes_with_timeperiod, default="SMA-100", space='buy') + + buy_filter_indicator = CategoricalParameter(filter_indicators, default="SMA-100", 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="/ float: + dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) + last_candle = dataframe.iloc[-1].squeeze() + return self.adjust_stake_amount(pair, last_candle) + def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str, current_time: datetime, entry_tag: Optional[str], **kwargs) -> bool: @@ -432,7 +1001,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): profit =trade.calc_profit(rate) force = self.pairs[pair]['force_sell'] - allow_to_sell = (last_candle['hapercent'] < 0 and profit > 0) or force or (exit_reason == 'sma48') or (exit_reason == 'force_exit') or (exit_reason == 'stop_loss') + allow_to_sell = True #(last_candle['hapercent'] < 0 and profit > 0) or force or (exit_reason == 'sma48') or (exit_reason == 'force_exit') or (exit_reason == 'stop_loss') minutes = int(round((current_time - trade.date_last_filled_utc).total_seconds() / 60, 0)) @@ -465,22 +1034,24 @@ 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]['current_trade'] = None + # else: # print(f"STOP triggered for {pair} ({exit_reason}) but condition blocked", "warning") return (allow_to_sell) | (exit_reason == 'force_exit') | (exit_reason == 'stop_loss') | force - - def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, - proposed_stake: float, min_stake: float, max_stake: float, - **kwargs) -> float: - - dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) - current_candle = dataframe.iloc[-1].squeeze() - adjusted_stake_amount = self.adjust_stake_amount(pair, current_candle) - - # print(f"{pair} adjusted_stake_amount{adjusted_stake_amount}") - - # Use default stake amount. - return adjusted_stake_amount + # + # def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, + # proposed_stake: float, min_stake: float, max_stake: float, + # **kwargs) -> float: + # + # dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) + # current_candle = dataframe.iloc[-1].squeeze() + # adjusted_stake_amount = self.adjust_stake_amount(pair, current_candle) + # + # # print(f"{pair} adjusted_stake_amount{adjusted_stake_amount}") + # + # # Use default stake amount. + # return adjusted_stake_amount + # def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs): @@ -540,12 +1111,20 @@ class Zeus_8_3_2_B_4_2(IStrategy): # return 'Drv_' + str(count_of_buys) pair_name = self.getShortName(pair) - if current_profit < - 0.02 and last_candle['sma48'] < before_last_candle['sma48'] - 10 and last_candle['sma60_deriv2'] < - 10 and (last_candle['hapercent3'] < -0.0005) and (last_candle['percent'] < 0): + if current_profit < - 0.05 and last_candle['baisse5_1d'] == 1 : self.pairs[pair]['stop'] = True self.pairs[pair]['force_sell'] = True self.pairs[pair]['force_buy'] = False #(self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) return str(count_of_buys) + '_' + 'stop48_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) + if current_profit < - 0.015 and last_candle['close'] > last_candle['sma5_1d'] * 1.015\ + and last_candle['sma24_1h'] > before_last_candle_12['sma24_1h']: + self.pairs[pair]['stop'] = True + self.pairs[pair]['force_sell'] = True + self.pairs[pair]['force_buy'] = False #(self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) + return str(count_of_buys) + '_' + 'top_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) + + # if current_profit < - 0.005 and last_candle['sma5_1h'] < before_last_candle_12['sma5_1h'] and hours > 12: # self.pairs[pair]['force_sell'] = True # self.pairs[pair]['force_buy'] = False #(self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) @@ -572,26 +1151,26 @@ class Zeus_8_3_2_B_4_2(IStrategy): self.pairs[pair]['force_buy'] = (self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) return str(count_of_buys) + '_' + 'Frc_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) - # if profit > max(5, expected_profit) and baisse > 0.30: - # self.pairs[pair]['force_sell'] = True - # self.pairs[pair]['force_buy'] = (self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) - # return str(count_of_buys) + '_' + 'B30_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) - # - # if (max_profit > 0.5 * count_of_buys or hours > 12) and baisse > 0.15 and last_candle['sma12_state'] <= 0 and last_candle['sma60_state'] <= - 1: - # self.pairs[pair]['force_sell'] = True - # self.pairs[pair]['force_buy'] = (self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) - # return str(count_of_buys) + '_' + 'B15_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) + if profit > max(5, expected_profit) and baisse > 0.30: + self.pairs[pair]['force_sell'] = True + self.pairs[pair]['force_buy'] = (self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) + return str(count_of_buys) + '_' + 'B30_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) - if profit > max(5, expected_profit) and last_candle['sma5_inv_bas_1h'] == - 1 and (last_candle['hapercent3'] < -0.0005) and (last_candle['percent'] < 0): + if (max_profit > 0.5 * count_of_buys) and baisse > 0.15 and last_candle['sma12_state'] <= 0 and last_candle['sma60_state'] <= - 1: + self.pairs[pair]['force_sell'] = True + self.pairs[pair]['force_buy'] = (self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) + return str(count_of_buys) + '_' + 'B15_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) + + if profit > max(5, expected_profit) and last_candle['sma5_inv_1h'] == - 1 and (last_candle['hapercent3'] < -0.0005) and (last_candle['percent'] < 0): self.pairs[pair]['force_sell'] = True self.pairs[pair]['force_buy'] = (self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) return str(count_of_buys) + '_' + 'SMA5_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) - if profit < 0 and last_candle['sma5_inv_hau_1h']: - self.pairs[pair]['stop'] = True - self.pairs[pair]['force_sell'] = True - self.pairs[pair]['force_buy'] = (self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) - return str(count_of_buys) + '_' + 'SMA24_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) + # if profit < 0 and last_candle['sma5_inv_1h']: + # # self.pairs[pair]['stop'] = True + # self.pairs[pair]['force_sell'] = True + # self.pairs[pair]['force_buy'] = (self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3) + # return str(count_of_buys) + '_' + 'SMA24_' + pair_name + '_' + str(self.pairs[pair]['has_gain']) # if (last_candle['sma48_deriv1'] < -0.1 and last_candle['sma48_deriv2'] < -10): # self.pairs[pair]['force_sell'] = True @@ -701,8 +1280,6 @@ class Zeus_8_3_2_B_4_2(IStrategy): # + " " + str(int(last_candle['rsi_1h'])) \ # + " " + str(int(last_candle['rsi_deriv1_1h'])) - # val144 = self.getProbaHausse144(last_candle) - # val1h = self.getProbaHausse1h(last_candle) val = self.getProbaHausseSma5d(last_candle) pct60 = round(100 * self.getPct60D(pair, last_candle), 2) @@ -748,6 +1325,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): #|tdc1d|tdc1h f"|{last_candle['mid_smooth_5_state_1d'] or '-':>3}|{last_candle['mid_smooth_24_state_1h'] or '-':>3}|{last_candle['mid_smooth_5_state_1h'] or '-':>3}|{last_candle['mid_smooth_5_state'] or '-':>3}" f"|{last_candle['trend_class_1d']:>5} {last_candle['trend_class_1h']:>5}" + f"|{val:>5}" ) def getLastLost(self, last_candle, pair): @@ -908,9 +1486,9 @@ class Zeus_8_3_2_B_4_2(IStrategy): # Lissage des valeurs Journalières horizon_d = 12 * 5 * 24 - dataframe['stop_buying_deb'] = (dataframe['sma48_deriv1'] < - 0.2) & (dataframe['sma5_1h'] < dataframe['sma5_1h'].shift(13)) - dataframe['stop_buying_end'] = (dataframe['sma48_deriv1'] > - 0.2) & (dataframe['sma5_1h'] > dataframe['sma5_1h'].shift(13)) - + # ###################################################################################################### + dataframe['stop_buying_deb'] = (dataframe['sma12_inv_1h'] == 1) + dataframe['stop_buying_end'] = (dataframe['sma12_inv_1h'] == -1) latched = np.zeros(len(dataframe), dtype=bool) for i in range(1, len(dataframe)): @@ -920,9 +1498,24 @@ class Zeus_8_3_2_B_4_2(IStrategy): latched[i] = False else: latched[i] = latched[i - 1] - dataframe['stop_buying'] = latched + # ###################################################################################################### + + dataframe['has_crossed_below'] = qtpylib.crossed_below(dataframe['sma48'], dataframe['sma3_1h']) + dataframe['has_crossed_above'] = qtpylib.crossed_above(dataframe['sma48'], dataframe['sma3_1h']) + latched = np.zeros(len(dataframe), dtype=int) + + for i in range(1, len(dataframe)): + if dataframe['has_crossed_below'].iloc[i]: + latched[i] = 1 + elif dataframe['has_crossed_above'].iloc[i]: + latched[i] = -1 + else: + latched[i] = latched[i - 1] + + dataframe['has_crossed'] = latched + self.model_indicators = self.listUsableColumns(dataframe) # if False and self.dp.runmode.value in ('backtest'): # self.trainModel(dataframe, metadata) @@ -989,13 +1582,11 @@ class Zeus_8_3_2_B_4_2(IStrategy): def listUsableColumns(self, dataframe): # Étape 1 : sélectionner numériques - numeric_cols = dataframe.select_dtypes(include=['int64', 'float64']).columns + numeric_cols = dataframe.columns #dataframe.select_dtypes(include=['int64', 'float64']).columns + # Étape 2 : enlever constantes usable_cols = [c for c in numeric_cols if dataframe[c].nunique() > 1 - and ( - ("deriv" in c or "dist" in c) - and ("_1h" in c or "_1d" in c) - ) + and ("_bas" in c or "_hau" in c) # and not "smooth" in c and not c.endswith("_state") # and not c.endswith("_1d") @@ -1718,31 +2309,15 @@ class Zeus_8_3_2_B_4_2(IStrategy): dataframe['hapercent'] = (dataframe['haclose'] - dataframe['haopen']) / dataframe['haclose'] dataframe['mid'] = dataframe['haopen'] + (dataframe['haclose'] - dataframe['haopen']) / 2 - dataframe["percent"] = dataframe['close'].pct_change() - dataframe["percent5"] = dataframe['close'].pct_change(5) - dataframe["percent12"] = dataframe['close'].pct_change(12) - dataframe["percent24"] = dataframe['close'].pct_change(24) + dataframe[f"percent"] = dataframe['close'].pct_change() + for timeperiod in timeperiods: + dataframe[f"percent{timeperiod}"] = dataframe['close'].pct_change(timeperiod) + dataframe[f"sma{timeperiod}"] = dataframe['mid'].ewm(span=timeperiod, adjust=False).mean() + self.calculeDerivees(dataframe, f"sma{timeperiod}", timeframe=timeframe, ema_period=timeperiod) + dataframe = self.calculateDerivation(dataframe, window=timeperiod, suffixe=f"_{timeperiod}", timeframe=timeframe) + dataframe["hapercent3"] = (dataframe['haclose'] - dataframe['haopen'].shift(3)) / dataframe['haclose'].shift(3) - # if self.dp.runmode.value in ('backtest'): - # dataframe['futur_percent'] = 100 * (dataframe['close'].shift(-1) - dataframe['close']) / dataframe['close'] - - dataframe['sma5'] = dataframe['mid'].ewm(span=5, adjust=False).mean() #dataframe["mid"].rolling(window=5).mean() - self.calculeDerivees(dataframe, 'sma5', timeframe=timeframe, ema_period=5) - dataframe['sma12'] = dataframe['mid'].ewm(span=12, adjust=False).mean() #dataframe["mid"].rolling(window=12).mean() - self.calculeDerivees(dataframe, 'sma12', timeframe=timeframe, ema_period=12) - dataframe['sma24'] = dataframe['mid'].ewm(span=24, adjust=False).mean() #dataframe["mid"].rolling(window=24).mean() - self.calculeDerivees(dataframe, 'sma24', timeframe=timeframe, ema_period=24) - dataframe['sma48'] = dataframe['mid'].ewm(span=48, adjust=False).mean() #dataframe["mid"].rolling(window=48).mean() - self.calculeDerivees(dataframe, 'sma48', timeframe=timeframe, ema_period=48) - dataframe['sma60'] = dataframe['mid'].ewm(span=60, adjust=False).mean() #dataframe["mid"].rolling(window=60).mean() - self.calculeDerivees(dataframe, 'sma60', timeframe=timeframe, ema_period=60) - - dataframe = self.calculateDerivation(dataframe, window=3, suffixe="_3",timeframe=timeframe) - dataframe = self.calculateDerivation(dataframe, window=5, suffixe="_5",timeframe=timeframe) - dataframe = self.calculateDerivation(dataframe, window=12, suffixe="_12",timeframe=timeframe) - dataframe = self.calculateDerivation(dataframe, window=24, suffixe="_24", timeframe=timeframe) - # print(metadata['pair']) dataframe['rsi'] = talib.RSI(dataframe['close'], timeperiod=14) dataframe['max_rsi_12'] = talib.MAX(dataframe['rsi'], timeperiod=12) dataframe['max_rsi_24'] = talib.MAX(dataframe['rsi'], timeperiod=24) @@ -1757,141 +2332,38 @@ class Zeus_8_3_2_B_4_2(IStrategy): # 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) - dataframe['bb_lowerband'] = bollinger['lower'] - dataframe['bb_middleband'] = bollinger['mid'] - dataframe['bb_upperband'] = bollinger['upper'] - dataframe["bb_percent"] = ( - (dataframe["close"] - dataframe["bb_lowerband"]) / - (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) - ) - dataframe["bb_width"] = (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["sma24"] - # dataframe["bb_width"] = ( - # (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"] - # ) + for timeperiod in timeperiods: + dataframe[f"rsi{timeperiod}"] = talib.RSI(dataframe["close"], timeperiod=timeperiod) + dataframe[f"max_rsi_{timeperiod}"] = talib.MAX(dataframe[f"rsi{timeperiod}"], timeperiod=timeperiod) + self.calculeDerivees(dataframe, f"rsi{timeperiod}", timeframe=timeframe, ema_period=timeperiod) - # Calcul MACD - macd, macdsignal, macdhist = talib.MACD( - dataframe['close'], - fastperiod=12, - slowperiod=26, - signalperiod=9 - ) + bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=timeperiod, stds=2) + dataframe[f"bb_lowerband{timeperiod}"] = bollinger['lower'] + dataframe[f"bb_middleband{timeperiod}"] = bollinger['mid'] + dataframe[f"bb_upperband{timeperiod}"] = bollinger['upper'] + dataframe[f"bb_percent{timeperiod}"] = ( + (dataframe["close"] - dataframe[f"bb_lowerband{timeperiod}"]) / + (dataframe[f"bb_upperband{timeperiod}"] - dataframe[f"bb_lowerband{timeperiod}"]) + ) + self.calculeDerivees(dataframe, f"bb_lowerband{timeperiod}", timeframe=timeframe, ema_period=timeperiod) + self.calculeDerivees(dataframe, f"bb_upperband{timeperiod}", timeframe=timeframe, ema_period=timeperiod) + dataframe[f"bb_width{timeperiod}"] = (dataframe[f"bb_upperband{timeperiod}"] - dataframe[f"bb_lowerband{timeperiod}"]) / dataframe[f"sma{timeperiod}"] - # | Nom | Formule / définition | Signification | - # | ---------------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - # | **MACD** (`macd`) | `EMA_fast - EMA_slow` (ex : 12-26 périodes) | Montre l’écart entre la moyenne courte et la moyenne longue.
- Positive → tendance haussière
- Négative → tendance baissière | - # | **Signal** (`macdsignal`) | `EMA_9(MACD)` | Sert de ligne de **signal de déclenchement**.
- Croisement du MACD au-dessus → signal d’achat
- Croisement du MACD en dessous → signal de vente | - # | **Histogramme** (`macdhist`) | `MACD - Signal` | Montre la **force et l’accélération** de la tendance.
- Positif et croissant → tendance haussière qui s’accélère
- Positif mais décroissant → ralentissement de la hausse
- Négatif et décroissant → baisse qui s’accélère
- Négatif mais croissant → ralentissement de la baisse | + # ###################################################################################################### + dataframe['bai5'] = (dataframe['sma5'] <= dataframe['sma5'].shift(1)) + dataframe['hau5'] = (dataframe['sma5'] > dataframe['sma5'].shift(1)) + latched = np.zeros(len(dataframe), dtype=int) - # Ajouter dans le dataframe - dataframe['macd'] = macd - dataframe['macdsignal'] = macdsignal - dataframe['macdhist'] = macdhist + for i in range(1, len(dataframe)): + if dataframe['bai5'].iloc[i]: + latched[i] = 1 + elif dataframe['hau5'].iloc[i]: + latched[i] = -1 + else: + latched[i] = latched[i - 1] - # Regarde dans le futur - # # --- Rendre relatif sur chaque série (-1 → 1) --- - # for col in ['macd', 'macdsignal', 'macdhist']: - # series = dataframe[col] - # valid = series[~np.isnan(series)] # ignorer NaN - # min_val = valid.min() - # max_val = valid.max() - # span = max_val - min_val if max_val != min_val else 1 - # dataframe[f'{col}_rel'] = 2 * ((series - min_val) / span) - 1 - # - # dataframe['tdc_macd'] = self.macd_tendance_int( - # dataframe, - # macd_col='macd_rel', - # signal_col='macdsignal_rel', - # hist_col='macdhist_rel' - # ) - - # ------------------------------------------------------------------------------------ - # rolling SMA indicators (used for trend detection too) - s_short = self.DEFAULT_PARAMS['sma_short'] - s_long = self.DEFAULT_PARAMS['sma_long'] - - dataframe[f'sma_{s_short}'] = dataframe['close'].rolling(window=s_short).mean() - dataframe[f'sma_{s_long}'] = dataframe['close'].rolling(window=s_long).mean() - - # --- pente brute --- - dataframe['slope'] = dataframe['sma24'].diff() - - # --- lissage EMA --- - dataframe['slope_smooth'] = dataframe['slope'].ewm(span=10, adjust=False).mean() - - # # RSI - # window = 14 - # delta = dataframe['close'].diff() - # up = delta.clip(lower=0) - # down = -1 * delta.clip(upper=0) - # ma_up = up.rolling(window=window).mean() - # ma_down = down.rolling(window=window).mean() - # rs = ma_up / ma_down.replace(0, 1e-9) - # dataframe['rsi'] = 100 - (100 / (1 + rs)) - # - # # EMA example - # dataframe['ema'] = dataframe['close'].ewm(span=self.DEFAULT_PARAMS['ema_period'], adjust=False).mean() - # - # # ATR (simple implementation) - # high_low = dataframe['high'] - dataframe['low'] - # high_close = (dataframe['high'] - dataframe['close'].shift()).abs() - # low_close = (dataframe['low'] - dataframe['close'].shift()).abs() - # tr = DataFrame({'hl': high_low, 'hc': high_close, 'lc': low_close}).max(axis=1) - # dataframe['atr'] = tr.rolling(window=self.DEFAULT_PARAMS['atr_period']).mean() - - ########################### - # df = ton DataFrame OHLCV avec colonnes: open, high, low, close, volume - # Assure-toi qu'il est trié par date croissante - - # --- Volatilité normalisée --- - dataframe['atr'] = ta.volatility.AverageTrueRange( - high=dataframe['high'], low=dataframe['low'], close=dataframe['close'], window=14 - ).average_true_range() - dataframe['atr_norm'] = dataframe['atr'] / dataframe['close'] - - # # --- Force de tendance --- - # dataframe['adx'] = ta.trend.ADXIndicator( - # high=dataframe['high'], low=dataframe['low'], close=dataframe['close'], window=14 - # ).adx() - # - # # --- Volume directionnel (On Balance Volume) --- - # dataframe['obv'] = ta.volume.OnBalanceVolumeIndicator( - # close=dataframe['close'], volume=dataframe['volume'] - # ).on_balance_volume() - # self.calculeDerivees(dataframe, 'obv', timeframe=timeframe, ema_period=1) - # - # dataframe['obv5'] = ta.volume.OnBalanceVolumeIndicator( - # close=dataframe['sma5'], volume=dataframe['volume'].rolling(5).sum() - # ).on_balance_volume() - # self.calculeDerivees(dataframe, 'obv5', timeframe=timeframe, ema_period=5) - - # --- Volatilité récente (écart-type des rendements) --- - # dataframe['vol_24'] = dataframe['percent'].rolling(24).std() - - # Compter les baisses / hausses consécutives - # self.calculateDownAndUp(dataframe, limit=0.0001) - - # df : ton dataframe OHLCV + indicateurs existants - # Assurez-vous que les colonnes suivantes existent : - # 'max_rsi_12', 'roc_24', 'bb_percent_1h' - - # --- Filtrage des NaN initiaux --- - # dataframe = dataframe.dropna() - - # dataframe['rsi_slope'] = dataframe['rsi'].diff(3) / 3 # vitesse moyenne du RSI - # dataframe['adx_change'] = dataframe['adx'] - dataframe['adx'].shift(12) # évolution de la tendance - # dataframe['volatility_ratio'] = dataframe['atr_norm'] / dataframe['bb_width'] - - # dataframe["rsi_diff"] = dataframe["rsi"] - dataframe["rsi"].shift(3) - # dataframe["slope_ratio"] = dataframe["sma5_deriv1"] / (dataframe["sma60_deriv1"] + 1e-9) - # dataframe["divergence"] = (dataframe["rsi_deriv1"] * dataframe["sma5_deriv1"]) < 0 - - ########################### - # - # dataframe['volume_sma_deriv'] = dataframe['volume'] * dataframe['sma5_deriv1'] / (dataframe['volume'].rolling(5).mean()) - # self.calculeDerivees(dataframe, 'volume', timeframe=timeframe, ema_period=12) + dataframe['baisse5'] = latched self.setTrends(dataframe) @@ -2001,11 +2473,40 @@ class Zeus_8_3_2_B_4_2(IStrategy): series = dataframe[f"{name}{suffixe}"] - cond_bas = (series.shift(2) > series.shift(1)) & (series.shift(1) < series) - cond_haut = (series.shift(2) < series.shift(1)) & (series.shift(1) > series) + d1 = series.diff() + d2 = d1.diff() + slope_threshold = 0.1 + accel_threshold = 0.02 - dataframe[f"{name}{suffixe}_inv_bas"] = np.where(cond_bas, -1, 0) - dataframe[f"{name}{suffixe}_inv_hau"] = np.where(cond_haut, 1, 0) + # cond_bas = ( + # (d1.shift(1) < -slope_threshold) & + # (d1 > slope_threshold) & + # (d2 > accel_threshold) + # ) + + cond_bas = ( + (d1.rolling(3).mean() > d1.rolling(10).mean()) + ) + + cond_haut = ( + (d1.rolling(3).mean() < d1.rolling(10).mean()) + ) + + # cond_haut = ( + # (d1.shift(1) > slope_threshold) & + # (d1 < -slope_threshold) & + # (d2 < -accel_threshold) + # ) + + dataframe[f"{name}{suffixe}_inv"] = np.where(cond_bas, -1, np.where(cond_haut, 1, 0)) + # dataframe[f"{name}{suffixe}_inv"] = np.where(cond_haut, 1, 0) + + + # cond_bas = (series.shift(2) > series.shift(1)) & (series.shift(1) < series) + # cond_haut = (series.shift(2) < series.shift(1)) & (series.shift(1) > series) + # + # dataframe[f"{name}{suffixe}_inv"] = np.where(cond_bas, -1, 0) + # dataframe[f"{name}{suffixe}_inv"] = np.where(cond_haut, 1, 0) # --- Distance à la moyenne mobile --- dataframe[f"{name}{suffixe}_dist"] = (dataframe['close'] - dataframe[f"{name}{suffixe}"]) / dataframe[f"{name}{suffixe}"] @@ -2095,73 +2596,242 @@ class Zeus_8_3_2_B_4_2(IStrategy): return self.trades def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - pair = metadata['pair'] - # Backtested 2025-04-09 00:00:00 -> 2025-05-25 00:00:00 | Max open trades : 1 - # ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓ - # ┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDC ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃ - # ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩ - # │ Zeus_8_3_2_B_4_2 │ 76 │ 0.17 │ 126.862 │ 12.69 │ 12:51:00 │ 51 0 25 67.1 │ 55.742 USDC 4.71% │ - # └──────────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴────────────────────┘ + conditions = list() + + # print(dataframe.columns) + # TODO: Its not dry code! + # 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['stop_buying'] == True)) + # + # 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_stop') + + # # print(len(dataframe.keys())) + # conditions2 = list() + # + # buy_2_indicator = self.buy_2_indicator0.value + # buy_2_crossed_indicator = self.buy_2_crossed_indicator0.value + # buy_2_operator = self.buy_2_operator0.value + # buy_2_real_num = self.buy_2_real_num0.value + # condition, dataframe = condition_generator( + # dataframe, + # buy_2_operator, + # buy_2_indicator, + # buy_2_crossed_indicator, + # buy_2_real_num + # ) + # conditions2.append(condition) + # # backup + # buy_2_indicator = self.buy_2_indicator1.value + # buy_2_crossed_indicator = self.buy_2_crossed_indicator1.value + # buy_2_operator = self.buy_2_operator1.value + # buy_2_real_num = self.buy_2_real_num1.value + # + # condition, dataframe = condition_generator( + # dataframe, + # buy_2_operator, + # buy_2_indicator, + # buy_2_crossed_indicator, + # buy_2_real_num + # ) + # conditions2.append(condition) + # + # buy_2_indicator = self.buy_2_indicator2.value + # buy_2_crossed_indicator = self.buy_2_crossed_indicator2.value + # buy_2_operator = self.buy_2_operator2.value + # buy_2_real_num = self.buy_2_real_num2.value + # condition, dataframe = condition_generator( + # dataframe, + # buy_2_operator, + # buy_2_indicator, + # buy_2_crossed_indicator, + # buy_2_real_num + # ) + # conditions2.append(condition) + # conditions2.append((dataframe['stop_buying'] == False)) + # + # print(f"BUY indicators tested \n" + # f"{self.buy_2_indicator0.value} {self.buy_2_crossed_indicator0.value} {self.buy_2_operator0.value} {self.buy_2_real_num0.value} \n" + # f"{self.buy_2_indicator1.value} {self.buy_2_crossed_indicator1.value} {self.buy_2_operator1.value} {self.buy_2_real_num1.value} \n" + # f"{self.buy_2_indicator2.value} {self.buy_2_crossed_indicator2.value} {self.buy_2_operator2.value} {self.buy_2_real_num2.value} \n" + # ) + # + # if conditions2: + # dataframe.loc[ + # reduce(lambda x, y: x & y, conditions2), + # ['enter_long', 'enter_tag'] + # ] = (1, 'god_start') + + # pair = metadata['pair'] + # + # # Backtested 2025-04-09 00:00:00 -> 2025-05-25 00:00:00 | Max open trades : 1 + # # ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓ + # # ┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDC ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃ + # # ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩ + # # │ Zeus_8_3_2_B_4_2 │ 76 │ 0.17 │ 126.862 │ 12.69 │ 12:51:00 │ 51 0 25 67.1 │ 55.742 USDC 4.71% │ + # # └──────────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴────────────────────┘ + # # dataframe.loc[ + # # ( + # # # (dataframe["mid_smooth_5_deriv1_1d"] > 0) + # # (dataframe["percent12"] > 0) + # # & (dataframe['sma48'] > dataframe['sma48'].shift(1)) + # # # & (dataframe['sma48'] < dataframe['sma48'].shift(1) + 10) + # # & (dataframe['sma5_1h'] >= dataframe['sma5_1h'].shift(13)) + # # & (dataframe['stop_buying'] == False) + # # # & (dataframe['trend_class_1h'] <= -1) + # # # & (dataframe['mid_smooth_5_state_1d'] >= -2) #or '-':>3}|{last_candle['mid_smooth_24_state_1h'] ) + # # ), ['enter_long', 'enter_tag']] = (1, 'sma48') + # + # + # # Backtested 2025-04-09 00:00:00 -> 2025-05-25 00:00:00 | Max open trades : 1 + # # ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓ + # # ┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDC ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃ + # # ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩ + # # │ Zeus_8_3_2_B_4_2 │ 60 │ 0.17 │ 103.408 │ 10.34 │ 12:52:00 │ 44 0 16 73.3 │ 38.701 USDC 3.53% │ + # # └──────────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴────────────────────┘ + # # dataframe.loc[ + # # ( + # # (dataframe["sma48_deriv1"] <= 0) + # # & (dataframe['min12_1h'].shift(36) == dataframe['min12_1h']) + # # & (dataframe["sma12_deriv1"] > dataframe["sma12_deriv1"].shift(1)) + # # ), ['enter_long', 'enter_tag']] = (1, 'min12_1h') + # + # # Backtested 2025-04-09 00:00:00 -> 2025-05-25 00:00:00 | Max open trades : 1 + # # ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓ + # # ┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDC ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃ + # # ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩ + # # │ Zeus_8_3_2_B_4_2 │ 28 │ 0.49 │ 136.071 │ 13.61 │ 1 day, 2:11:00 │ 27 0 1 96.4 │ 37.149 USDC 3.17% │ + # # └──────────────────┴────────┴──────────────┴─────────────────┴──────────────┴────────────────┴────────────────────────┴────────────────────┘ + # # dataframe.loc[ + # # ( + # # (dataframe['sma5_inv_1h'] == -1) + # # ), ['enter_long', 'enter_tag']] = (1, 'sma5_inv') + # + # # Backtested 2025-04-09 00:00:00 -> 2025-05-25 00:00:00 | Max open trades : 1 + # # ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓ + # # ┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDC ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃ + # # ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩ + # # │ Zeus_8_3_2_B_4_2 │ 32 │ 0.60 │ 191.920 │ 19.19 │ 20:56:00 │ 26 0 6 81.2 │ 48.62 USDC 4.02% │ + # # └──────────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴───────────────────┘ + # + # dataframe.loc[ + # ( + # (dataframe['sma5_inv_1h'] == -1) + # & (dataframe['sma24_1h'].shift(1) <= dataframe['sma24_1h']) + # ), ['enter_long', 'enter_tag']] = (1, 'sma5_inv') + # # dataframe.loc[ # ( - # # (dataframe["mid_smooth_5_deriv1_1d"] > 0) - # (dataframe["percent12"] > 0) - # & (dataframe['sma48'] > dataframe['sma48'].shift(1)) - # # & (dataframe['sma48'] < dataframe['sma48'].shift(1) + 10) - # & (dataframe['sma5_1h'] >= dataframe['sma5_1h'].shift(13)) - # & (dataframe['stop_buying'] == False) - # # & (dataframe['trend_class_1h'] <= -1) - # # & (dataframe['mid_smooth_5_state_1d'] >= -2) #or '-':>3}|{last_candle['mid_smooth_24_state_1h'] ) - # ), ['enter_long', 'enter_tag']] = (1, 'sma48') - - - # Backtested 2025-04-09 00:00:00 -> 2025-05-25 00:00:00 | Max open trades : 1 - # ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓ - # ┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDC ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃ - # ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩ - # │ Zeus_8_3_2_B_4_2 │ 60 │ 0.17 │ 103.408 │ 10.34 │ 12:52:00 │ 44 0 16 73.3 │ 38.701 USDC 3.53% │ - # └──────────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴────────────────────┘ - # dataframe.loc[ - # ( - # (dataframe["sma48_deriv1"] <= 0) - # & (dataframe['min12_1h'].shift(36) == dataframe['min12_1h']) - # & (dataframe["sma12_deriv1"] > dataframe["sma12_deriv1"].shift(1)) - # ), ['enter_long', 'enter_tag']] = (1, 'min12_1h') - - # Backtested 2025-04-09 00:00:00 -> 2025-05-25 00:00:00 | Max open trades : 1 - # ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓ - # ┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDC ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃ - # ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩ - # │ Zeus_8_3_2_B_4_2 │ 28 │ 0.49 │ 136.071 │ 13.61 │ 1 day, 2:11:00 │ 27 0 1 96.4 │ 37.149 USDC 3.17% │ - # └──────────────────┴────────┴──────────────┴─────────────────┴──────────────┴────────────────┴────────────────────────┴────────────────────┘ - # dataframe.loc[ - # ( - # (dataframe['sma5_inv_bas_1h'] == -1) - # ), ['enter_long', 'enter_tag']] = (1, 'sma5_inv') - - # Backtested 2025-04-09 00:00:00 -> 2025-05-25 00:00:00 | Max open trades : 1 - # ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓ - # ┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDC ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃ - # ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩ - # │ Zeus_8_3_2_B_4_2 │ 32 │ 0.60 │ 191.920 │ 19.19 │ 20:56:00 │ 26 0 6 81.2 │ 48.62 USDC 4.02% │ - # └──────────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴───────────────────┘ + # # qtpylib.crossed_below(dataframe['sma48'], dataframe['sma3_1h']) + # (dataframe['has_crossed'] == 1) + # & (dataframe['close'] <= dataframe['min12_1h'] * 1.004) #| (dataframe['min12_1h'] == dataframe['min12_1h'].shift(24))) + # & (dataframe['hapercent'] >= 0) + # # & (dataframe['sma24_inv_1h'] != 1) + # ), ['enter_long', 'enter_tag']] = (1, 'sma3_inv_1h') dataframe.loc[ ( - (dataframe['sma5_inv_bas_1h'] == -1) - & (dataframe['sma24_1h'].shift(1) <= dataframe['sma24_1h']) - ), ['enter_long', 'enter_tag']] = (1, 'sma5_inv') + (dataframe['baisse5_1h'].shift(12) == 1) + & (dataframe['baisse5_1h'] == -1) + ), ['enter_long', 'enter_tag']] = (1, 'baisse5_1h') - dataframe.loc[ - ( - (dataframe['sma48_inv_bas'] == -1) - & (dataframe['sma24_1h'].shift(1) <= dataframe['sma24_1h']) - ), ['enter_long', 'enter_tag']] = (1, 'sma48_inv') + d1 = self.buy_filter_indicator.value + d2 = str(d1).replace('deriv1', 'deriv2') + # ✅ Seconde dérivée(accélération ou concavité) + # Positive: la pente augmente → accélération de la hausse ou ralentissement de la baisse. + # Négative: la pente diminue → accélération de la baisse ou ralentissement de la hausse. + # Changement de signe: indique souvent un changement de courbure, utile pour prévoir des retournements. + # + # Exemples: - # dataframe['test'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.01, np.nan) + # # ========================================================================================= + # # 🟢 Dérivée 1 > 0 et dérivée 2 > 0: tendance haussière qui s’accélère. + # condition = ( + # (dataframe[self.buy_indicator0.value] == -1) + # & (dataframe[d1] > 0) + # & (dataframe[d2] > 0) + # ) + # dataframe.loc[condition, ['enter_long', 'enter_tag']] = (1, "HAU++") + # + # # ========================================================================================= + # # 🟡 Dérivée 1 > 0 et dérivée 2 < 0: tendance haussière qui ralentit → essoufflement potentiel. + # condition = ( + # (dataframe[self.buy_indicator1.value] == -1) + # & (dataframe[d1] > 0) + # & (dataframe[d2] < 0) + # ) + # dataframe.loc[condition, ['enter_long', 'enter_tag']] = (1, "HAU--") + # + # # ========================================================================================= + # # 🔴 Dérivée 1 < 0 et dérivée 2 < 0: tendance baissière qui s’accélère. + # condition = ( + # (dataframe[self.buy_indicator2.value] == -1) + # & (dataframe[d1] < 0) + # & (dataframe[d2] < 0) + # ) + # dataframe.loc[condition, ['enter_long', 'enter_tag']] = (1, "BAI++") + # + # # ========================================================================================= + # # 🟠 Dérivée 1 < 0 et dérivée 2 > 0: tendance baissière qui ralentit → possible bottom. + # condition = ( + # (dataframe[self.buy_indicator3.value] == -1) + # & (dataframe[d1] < 0) + # & (dataframe[d2] > 0) + # ) + # dataframe.loc[condition, ['enter_long', 'enter_tag']] = (1, f"BAI--") + # + # # dataframe['test'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.01, np.nan) + # if self.dp.runmode.value in ('backtest'): dataframe.to_feather(f"user_data/backtest_results/{metadata['pair'].replace('/', '_')}_df.feather") @@ -2311,10 +2981,70 @@ class Zeus_8_3_2_B_4_2(IStrategy): print(line) def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + # conditions = list() + # # TODO: Its not dry code! + # sell_indicator = self.sell_indicator0.value + # sell_crossed_indicator = self.sell_crossed_indicator0.value + # sell_operator = self.sell_operator0.value + # sell_real_num = self.sell_real_num0.value + # condition, dataframe = condition_generator( + # dataframe, + # sell_operator, + # sell_indicator, + # sell_crossed_indicator, + # sell_real_num + # ) + # conditions.append(condition) + # + # sell_indicator = self.sell_indicator1.value + # sell_crossed_indicator = self.sell_crossed_indicator1.value + # sell_operator = self.sell_operator1.value + # sell_real_num = self.sell_real_num1.value + # condition, dataframe = condition_generator( + # dataframe, + # sell_operator, + # sell_indicator, + # sell_crossed_indicator, + # sell_real_num + # ) + # conditions.append(condition) + # + # sell_indicator = self.sell_indicator2.value + # sell_crossed_indicator = self.sell_crossed_indicator2.value + # sell_operator = self.sell_operator2.value + # sell_real_num = self.sell_real_num2.value + # condition, dataframe = condition_generator( + # dataframe, + # sell_operator, + # sell_indicator, + # sell_crossed_indicator, + # sell_real_num + # ) + # conditions.append(condition) + # + # + # print(f"SELL indicators tested \n" + # f"{self.sell_indicator0.value} {self.sell_crossed_indicator0.value} {self.sell_operator0.value} {self.sell_real_num0.value} \n" + # f"{self.sell_indicator1.value} {self.sell_crossed_indicator1.value} {self.sell_operator1.value} {self.sell_real_num1.value} \n" + # f"{self.sell_indicator2.value} {self.sell_crossed_indicator2.value} {self.sell_operator2.value} {self.sell_real_num2.value} \n" + # ) + # + # + # if conditions: + # dataframe.loc[ + # reduce(lambda x, y: x & y, conditions), + # 'sell']=1 + # dataframe.loc[ # ( - # (dataframe['sma48'] < dataframe['sma48'].shift(1) - 10) - # ), ['exit_long', 'exit_tag']] = (1, 'sma48') + # # qtpylib.crossed_below(dataframe['sma48'], dataframe['sma3_1h']) + # # (dataframe['has_crossed'] == -1) + # # & (dataframe['close'] >= dataframe['max12_1h'] * 0.996) #| (dataframe['min12_1h'] == dataframe['min12_1h'].shift(24))) + # # (dataframe['hapercent'] < 0) + # (qtpylib.crossed_below(dataframe['sma3'], dataframe['sma24'])) + # # & (dataframe['sma24_inv_1h'] != 1) + # ), ['exit_long', 'exit_tag']] = (1, 'sma3_inv_1h') return dataframe @@ -2548,7 +3278,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): return val def adjust_stake_amount(self, pair: str, last_candle: DataFrame): - amount = self.config.get('stake_amount') + amount = self.config.get('stake_amount') / 4 # state = int(last_candle.get('trend_class_1h')) # @@ -2983,7 +3713,8 @@ class Zeus_8_3_2_B_4_2(IStrategy): # return last_candle['slope_norm_1d'] < last_candle['slope_norm_1h'] - if self.pairs[pair]['stop'] and last_candle['sma24_inv_bas_1h'] == -1: + if self.pairs[pair]['stop'] and last_candle['baisse5_1d'] == -1\ + and last_candle['sma24_deriv1_1h'] > 0: dispo = round(self.wallets.get_available_stake_amount()) self.pairs[pair]['stop'] = False self.log_trade( @@ -3033,7 +3764,7 @@ class Zeus_8_3_2_B_4_2(IStrategy): # self.log_trade( # last_candle=last_candle, # date=current_time, - # action="🔴STOP " + str(last_candle['sma24_inv_bas_1h']), + # action="🔴STOP " + str(last_candle['sma24_inv_1h']), # dispo=dispo, # pair=pair, # rate=last_candle['close'],