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'],