Riy777 commited on
Commit
e765f32
Β·
verified Β·
1 Parent(s): d721423

Update ml_engine/guardian_hydra.py

Browse files
Files changed (1) hide show
  1. ml_engine/guardian_hydra.py +36 -45
ml_engine/guardian_hydra.py CHANGED
@@ -10,17 +10,15 @@ import sys
10
 
11
  class GuardianHydra:
12
  """
13
- GuardianHydra V1.3 (X-RAY DIAGNOSTIC MODE)
14
- - Puts everything under a microscope.
15
- - Prints INPUT Data (OHLCV sample).
16
- - Prints CALCULATED Features (RSI, ATR, etc).
17
- - Prints RAW MODEL Output (Array).
18
  """
19
  def __init__(self, model_dir):
20
  self.model_dir = model_dir
21
  self.initialized = False
22
  self.models = {}
23
  self.feature_cols = []
 
24
 
25
  self.smoothing_buffer = defaultdict(lambda: {
26
  'crash': deque(maxlen=3),
@@ -29,43 +27,48 @@ class GuardianHydra:
29
  })
30
 
31
  self.ATR_PERIOD = 14
32
- print("🐲 [Hydra X-RAY] Instance Created. Waiting for data...")
 
 
 
 
 
33
 
34
  def initialize(self):
35
- print(f"🐲 [Hydra X-RAY] Loading from: {self.model_dir}")
36
 
37
  if not os.path.exists(self.model_dir):
38
- print(f"❌ [FATAL] Directory missing: {self.model_dir}")
39
  return False
40
 
41
  try:
42
  # 1. Load Features
43
  feat_path = os.path.join(self.model_dir, "hydra_features_list.pkl")
44
  if not os.path.exists(feat_path):
45
- print(f"❌ Feature list missing: {feat_path}")
46
  return False
47
  self.feature_cols = joblib.load(feat_path)
48
- print(f"βœ… Features List Loaded ({len(self.feature_cols)} items)")
49
 
50
  # 2. Load Models (RAW)
51
  heads = ['crash', 'giveback', 'stagnation']
52
  for h in heads:
53
  model_path = os.path.join(self.model_dir, f"hydra_head_{h}_raw.json")
54
  if not os.path.exists(model_path):
55
- print(f"❌ Model missing: {model_path}")
56
  return False
57
 
58
  clf = xgb.XGBClassifier()
59
  clf.load_model(model_path)
60
  self.models[h] = clf
61
- print(f"βœ… Loaded Head: {h}")
62
 
63
  self.initialized = True
64
- print(f"βœ… [Hydra X-RAY] System Ready.")
65
  return True
66
 
67
  except Exception as e:
68
- print(f"❌ [Hydra Init Error] {e}")
69
  traceback.print_exc()
70
  return False
71
 
@@ -73,17 +76,18 @@ class GuardianHydra:
73
  try:
74
  # 1. Check Raw Data Inputs
75
  if not ohlcv_1m or len(ohlcv_1m) < 1:
76
- print("⚠️ [X-RAY] 1m Data is EMPTY!")
77
  return None
78
 
79
  df_1m = pd.DataFrame(ohlcv_1m, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
80
 
81
  # [DIAGNOSTIC 1] Print Input Sample
82
  last_close = df_1m['close'].iloc[-1]
83
- print(f"πŸ” [Input Check] Last Close: {last_close} | Candles: {len(df_1m)}")
 
84
 
85
  if len(df_1m) < 50:
86
- print(f"⚠️ [X-RAY] Not enough history: {len(df_1m)} < 50")
87
  return None
88
 
89
  # 2. Indicator Calculation
@@ -94,7 +98,7 @@ class GuardianHydra:
94
  last_rsi = df_1m['rsi'].iloc[-1]
95
  last_atr = df_1m['atr'].iloc[-1]
96
 
97
- if pd.isna(last_rsi) or pd.isna(last_atr):
98
  print(f"⚠️ [X-RAY] Indicators are NaN! RSI: {last_rsi}, ATR: {last_atr}")
99
 
100
  # ... rest of calculations ...
@@ -131,17 +135,12 @@ class GuardianHydra:
131
 
132
  duration_mins = trade_context.get('time_in_trade_mins', 10)
133
 
134
- # [GEM-FIX] Extract Highest Price & Calculate Max PnL
135
- # This enables the "Giveback" model to see profit retracements.
136
  highest_price = float(trade_context.get('highest_price', entry_price))
137
- if highest_price < entry_price: highest_price = entry_price # Safety
138
 
139
  max_pnl_amt = highest_price - entry_price
140
  max_pnl_r = max_pnl_amt / sl_dist_unit if sl_dist_unit > 0 else 0.0
141
 
142
- # [DIAGNOSTIC 3] Context Check
143
- # print(f"πŸ” [Context Check] Entry: {entry_price} | Current: {last_close} | PnL R: {norm_pnl_r:.2f}")
144
-
145
  # Assemble Vector
146
  feat_dict = {
147
  'rsi_1m': last_rsi,
@@ -152,7 +151,7 @@ class GuardianHydra:
152
  'dist_ema20_1h': dist_ema20_1h,
153
  'atr_pct': atr_val / last_close,
154
  'norm_pnl_r': norm_pnl_r,
155
- 'max_pnl_r': max_pnl_r, # [GEM-FIX] Now uses real calculated value
156
  'dist_tp_atr': 0.0,
157
  'dist_sl_atr': 0.0,
158
  'time_in_trade': float(duration_mins),
@@ -164,22 +163,22 @@ class GuardianHydra:
164
 
165
  vector = pd.DataFrame([feat_dict])
166
 
167
- # Fill missing columns
168
  for col in self.feature_cols:
169
  if col not in vector.columns:
170
  vector[col] = 0.0
171
 
172
- # [DIAGNOSTIC 4] Check Final Vector for NaNs
173
  if vector.isnull().values.any():
174
- print("⚠️ [X-RAY] Final Vector contains NaNs! Model will fail or output 0.")
175
- print(vector.iloc[0].to_dict())
176
- vector = vector.fillna(0) # Force fix
 
177
 
178
  return vector[self.feature_cols].astype(float)
179
 
180
  except Exception as e:
181
- print(f"❌ [X-RAY] Feature Error: {e}")
182
- traceback.print_exc()
 
183
  return None
184
 
185
  def analyze_position(self, symbol, ohlcv_1m, ohlcv_5m, ohlcv_15m, trade_data):
@@ -187,40 +186,32 @@ class GuardianHydra:
187
  return {'action': 'HOLD', 'reason': 'Not Init'}
188
 
189
  try:
190
- # Time calculation
191
  features = self._engineer_features(ohlcv_1m, ohlcv_5m, ohlcv_15m, trade_data)
192
 
193
  if features is None:
194
- print(f"🚫 [X-RAY] {symbol}: Feature Engineering Failed.")
195
  return {'action': 'HOLD', 'reason': 'Feat Fail'}
196
 
197
  probs = {}
198
- print(f"πŸ”¬ [X-RAY] Predicting for {symbol}...")
199
 
200
  for h in ['crash', 'giveback', 'stagnation']:
201
- # Predict
202
  try:
203
- # XGBoost predict_proba returns [[prob_0, prob_1]]
204
  full_pred = self.models[h].predict_proba(features)
205
-
206
- # [DIAGNOSTIC 5] Print Full Prediction Array
207
- # print(f" πŸ‘‰ {h.upper()} Raw Array: {full_pred}")
208
-
209
  raw_prob = full_pred[0][1]
210
  probs[h] = raw_prob
211
 
212
- if raw_prob > 0.0:
213
  print(f" πŸ”₯ {h.upper()} Non-Zero Prob: {raw_prob:.4f}")
214
 
215
  except Exception as e:
216
- print(f" ❌ Error predicting {h}: {e}")
217
  probs[h] = 0.0
218
 
219
- # Pass-through logic (Simplified for test)
220
  return self._pkg('HOLD', 0.0, "X-RAY DIAGNOSTIC", probs)
221
 
222
  except Exception as e:
223
- print(f"❌ [X-RAY] Analyze Error: {e}")
224
  return {'action': 'HOLD', 'reason': 'Error'}
225
 
226
  def _pkg(self, action, conf, reason, probs):
 
10
 
11
  class GuardianHydra:
12
  """
13
+ GuardianHydra V1.4 (Configurable Verbosity)
14
+ - Added set_silent_mode() to suppress logs during Backtesting.
 
 
 
15
  """
16
  def __init__(self, model_dir):
17
  self.model_dir = model_dir
18
  self.initialized = False
19
  self.models = {}
20
  self.feature_cols = []
21
+ self.verbose = True # βœ… Default to True for Live System
22
 
23
  self.smoothing_buffer = defaultdict(lambda: {
24
  'crash': deque(maxlen=3),
 
27
  })
28
 
29
  self.ATR_PERIOD = 14
30
+ # βœ… Silent check
31
+ if self.verbose: print("🐲 [Hydra X-RAY] Instance Created. Waiting for data...")
32
+
33
+ def set_silent_mode(self, silent=True):
34
+ """ βœ… Control Logging Output (True = No Logs, False = X-RAY Logs) """
35
+ self.verbose = not silent
36
 
37
  def initialize(self):
38
+ if self.verbose: print(f"🐲 [Hydra X-RAY] Loading from: {self.model_dir}")
39
 
40
  if not os.path.exists(self.model_dir):
41
+ if self.verbose: print(f"❌ [FATAL] Directory missing: {self.model_dir}")
42
  return False
43
 
44
  try:
45
  # 1. Load Features
46
  feat_path = os.path.join(self.model_dir, "hydra_features_list.pkl")
47
  if not os.path.exists(feat_path):
48
+ if self.verbose: print(f"❌ Feature list missing: {feat_path}")
49
  return False
50
  self.feature_cols = joblib.load(feat_path)
51
+ if self.verbose: print(f"βœ… Features List Loaded ({len(self.feature_cols)} items)")
52
 
53
  # 2. Load Models (RAW)
54
  heads = ['crash', 'giveback', 'stagnation']
55
  for h in heads:
56
  model_path = os.path.join(self.model_dir, f"hydra_head_{h}_raw.json")
57
  if not os.path.exists(model_path):
58
+ if self.verbose: print(f"❌ Model missing: {model_path}")
59
  return False
60
 
61
  clf = xgb.XGBClassifier()
62
  clf.load_model(model_path)
63
  self.models[h] = clf
64
+ if self.verbose: print(f"βœ… Loaded Head: {h}")
65
 
66
  self.initialized = True
67
+ if self.verbose: print(f"βœ… [Hydra X-RAY] System Ready.")
68
  return True
69
 
70
  except Exception as e:
71
+ if self.verbose: print(f"❌ [Hydra Init Error] {e}")
72
  traceback.print_exc()
73
  return False
74
 
 
76
  try:
77
  # 1. Check Raw Data Inputs
78
  if not ohlcv_1m or len(ohlcv_1m) < 1:
79
+ if self.verbose: print("⚠️ [X-RAY] 1m Data is EMPTY!")
80
  return None
81
 
82
  df_1m = pd.DataFrame(ohlcv_1m, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
83
 
84
  # [DIAGNOSTIC 1] Print Input Sample
85
  last_close = df_1m['close'].iloc[-1]
86
+ if self.verbose:
87
+ print(f"πŸ” [Input Check] Last Close: {last_close} | Candles: {len(df_1m)}")
88
 
89
  if len(df_1m) < 50:
90
+ if self.verbose: print(f"⚠️ [X-RAY] Not enough history: {len(df_1m)} < 50")
91
  return None
92
 
93
  # 2. Indicator Calculation
 
98
  last_rsi = df_1m['rsi'].iloc[-1]
99
  last_atr = df_1m['atr'].iloc[-1]
100
 
101
+ if (pd.isna(last_rsi) or pd.isna(last_atr)) and self.verbose:
102
  print(f"⚠️ [X-RAY] Indicators are NaN! RSI: {last_rsi}, ATR: {last_atr}")
103
 
104
  # ... rest of calculations ...
 
135
 
136
  duration_mins = trade_context.get('time_in_trade_mins', 10)
137
 
 
 
138
  highest_price = float(trade_context.get('highest_price', entry_price))
139
+ if highest_price < entry_price: highest_price = entry_price
140
 
141
  max_pnl_amt = highest_price - entry_price
142
  max_pnl_r = max_pnl_amt / sl_dist_unit if sl_dist_unit > 0 else 0.0
143
 
 
 
 
144
  # Assemble Vector
145
  feat_dict = {
146
  'rsi_1m': last_rsi,
 
151
  'dist_ema20_1h': dist_ema20_1h,
152
  'atr_pct': atr_val / last_close,
153
  'norm_pnl_r': norm_pnl_r,
154
+ 'max_pnl_r': max_pnl_r,
155
  'dist_tp_atr': 0.0,
156
  'dist_sl_atr': 0.0,
157
  'time_in_trade': float(duration_mins),
 
163
 
164
  vector = pd.DataFrame([feat_dict])
165
 
 
166
  for col in self.feature_cols:
167
  if col not in vector.columns:
168
  vector[col] = 0.0
169
 
 
170
  if vector.isnull().values.any():
171
+ if self.verbose:
172
+ print("⚠️ [X-RAY] Final Vector contains NaNs! Model will fail or output 0.")
173
+ print(vector.iloc[0].to_dict())
174
+ vector = vector.fillna(0)
175
 
176
  return vector[self.feature_cols].astype(float)
177
 
178
  except Exception as e:
179
+ if self.verbose:
180
+ print(f"❌ [X-RAY] Feature Error: {e}")
181
+ traceback.print_exc()
182
  return None
183
 
184
  def analyze_position(self, symbol, ohlcv_1m, ohlcv_5m, ohlcv_15m, trade_data):
 
186
  return {'action': 'HOLD', 'reason': 'Not Init'}
187
 
188
  try:
 
189
  features = self._engineer_features(ohlcv_1m, ohlcv_5m, ohlcv_15m, trade_data)
190
 
191
  if features is None:
192
+ if self.verbose: print(f"🚫 [X-RAY] {symbol}: Feature Engineering Failed.")
193
  return {'action': 'HOLD', 'reason': 'Feat Fail'}
194
 
195
  probs = {}
196
+ if self.verbose: print(f"πŸ”¬ [X-RAY] Predicting for {symbol}...")
197
 
198
  for h in ['crash', 'giveback', 'stagnation']:
 
199
  try:
 
200
  full_pred = self.models[h].predict_proba(features)
 
 
 
 
201
  raw_prob = full_pred[0][1]
202
  probs[h] = raw_prob
203
 
204
+ if raw_prob > 0.0 and self.verbose:
205
  print(f" πŸ”₯ {h.upper()} Non-Zero Prob: {raw_prob:.4f}")
206
 
207
  except Exception as e:
208
+ if self.verbose: print(f" ❌ Error predicting {h}: {e}")
209
  probs[h] = 0.0
210
 
 
211
  return self._pkg('HOLD', 0.0, "X-RAY DIAGNOSTIC", probs)
212
 
213
  except Exception as e:
214
+ if self.verbose: print(f"❌ [X-RAY] Analyze Error: {e}")
215
  return {'action': 'HOLD', 'reason': 'Error'}
216
 
217
  def _pkg(self, action, conf, reason, probs):