Spaces:
Sleeping
Sleeping
File size: 14,618 Bytes
58d7d2b 3bc03f3 009e186 f331c8d d123da7 6bc8791 009e186 d1d1a25 f331c8d 009e186 7798099 009e186 3bc03f3 5a46f77 f331c8d 5a46f77 58d7d2b 5a46f77 5af05d7 7798099 d123da7 f331c8d 5a46f77 7798099 f331c8d 5a46f77 6b5a7c6 009e186 f9f853e 009e186 7798099 3bacdac 009e186 5a46f77 009e186 3bc03f3 009e186 3bc03f3 009e186 3bc03f3 009e186 5a46f77 3bc03f3 6bc8791 009e186 d1d1a25 6bc8791 009e186 f9f853e 009e186 58d7d2b 009e186 f331c8d 009e186 5a46f77 6bc8791 009e186 6bc8791 f9f853e 6bc8791 009e186 f9f853e ccf88bd 009e186 6bc8791 5a46f77 009e186 d1d1a25 6bc8791 7798099 6bc8791 d123da7 d1d1a25 009e186 6bc8791 f9f853e d1d1a25 d123da7 3bc03f3 7798099 6bc8791 1182eda 6bc8791 f331c8d d123da7 6bc8791 f331c8d d123da7 58d7d2b f9f853e d123da7 5a46f77 6bc8791 58d7d2b 6bc8791 f331c8d 6bc8791 7ca1715 6bc8791 f9f853e 6bc8791 009e186 58d7d2b 7798099 58d7d2b 7798099 6bc8791 7798099 6bc8791 7798099 f331c8d 6bc8791 f331c8d d123da7 6bc8791 d123da7 6bc8791 d123da7 5a46f77 d123da7 6bc8791 d1d1a25 6bc8791 d123da7 009e186 58d7d2b 6bc8791 009e186 f331c8d 6bc8791 f9f853e 6bc8791 009e186 6bc8791 f9f853e 009e186 f9f853e f331c8d f9f853e 009e186 f9f853e f331c8d f9f853e f331c8d 5a46f77 f331c8d 5a46f77 f331c8d 5a46f77 f331c8d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# ==============================================================================
# π§ ml_engine/processor.py (V70.7 - GEM-Architect: Gate Override Fix)
# ==============================================================================
# - Fix: Forces the Pattern Gate to respect the lower (more permissive) threshold.
# This ensures coins with ~40% pattern score pass to Oracle if SystemLimit is 0.25.
# ==============================================================================
import asyncio
import traceback
import os
import numpy as np
from typing import Dict, Any, List, Optional
# --- Imports ---
try: from .pattern_engine import PatternEngine
except ImportError: PatternEngine = None
try: from .monte_carlo import MonteCarloEngine
except ImportError: MonteCarloEngine = None
try: from .oracle_engine import OracleEngine
except ImportError: OracleEngine = None
try: from .sniper_engine import SniperEngine
except ImportError: SniperEngine = None
try: from .hybrid_guardian import HybridDeepSteward
except ImportError: HybridDeepSteward = None
try: from .guardian_hydra import GuardianHydra
except ImportError: GuardianHydra = None
# Base Paths
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MODELS_UNIFIED_DIR = os.path.join(BASE_DIR, "ml_models", "Unified_Models_V1")
MODELS_SNIPER_DIR = os.path.join(BASE_DIR, "ml_models", "guard_v2")
MODELS_HYDRA_DIR = os.path.join(BASE_DIR, "ml_models", "guard_v1")
MODEL_V2_PATH = os.path.join(BASE_DIR, "ml_models", "DeepSteward_V2_Production.json")
MODEL_V3_PATH = os.path.join(BASE_DIR, "ml_models", "DeepSteward_V3_Production.json")
MODEL_V3_FEAT = os.path.join(BASE_DIR, "ml_models", "DeepSteward_V3_Features.json")
# ============================================================
# ποΈ SYSTEM LIMITS
# ============================================================
class SystemLimits:
"""
GEM-Architect: Logic Gates Configuration (Data-Driven).
"""
# --- Layer 2: Pattern Net Gate ---
L2_GATE_PATTERN_NET = 0.25 # β
Permissive Gate to let Oracle decide
# --- Layer 2: Composite Score Weights ---
L2_WEIGHT_ORACLE = 0.30 # The King
L2_WEIGHT_PATTERN = 0.50 # The Scout
L2_WEIGHT_MC = 0.20 # The Anchor
L2_MIN_COMPOSITE_SCORE = 50.0
# --- Layer 3 & 4 Limits ---
L3_WHALE_IMPACT_MAX = 15.0
L3_NEWS_IMPACT_MAX = 10.0
L3_MC_ADVANCED_MAX = 10.0
L4_ENTRY_THRESHOLD = 0.40
L4_WEIGHT_ML = 0.60
L4_WEIGHT_OB = 0.40
L4_OB_WALL_RATIO = 0.35
# --- Guardians ---
HYDRA_CRASH_THRESH = 0.80
HYDRA_GIVEBACK_THRESH = 0.70
HYDRA_STAGNATION_THRESH = 0.60
LEGACY_V2_PANIC_THRESH = 0.98
LEGACY_V3_HARD_THRESH = 0.95
LEGACY_V3_SOFT_THRESH = 0.88
LEGACY_V3_ULTRA_THRESH = 0.99
@classmethod
def to_dict(cls) -> Dict[str, Any]:
return {k: v for k, v in cls.__dict__.items() if not k.startswith('__') and not callable(v)}
# ============================================================
# π§ MLProcessor Class
# ============================================================
class MLProcessor:
def __init__(self, data_manager=None):
self.data_manager = data_manager
self.initialized = False
self.initialization_attempted = False
self.pattern_net = PatternEngine(model_dir=MODELS_UNIFIED_DIR) if PatternEngine else None
self.oracle = OracleEngine(model_dir=MODELS_UNIFIED_DIR) if OracleEngine else None
self.mc_analyzer = MonteCarloEngine() if MonteCarloEngine else None
self.sniper = SniperEngine(models_dir=MODELS_SNIPER_DIR) if SniperEngine else None
self.guardian_hydra = GuardianHydra(model_dir=MODELS_HYDRA_DIR) if GuardianHydra else None
self.guardian_legacy = None
if HybridDeepSteward:
self.guardian_legacy = HybridDeepSteward(
v2_model_path=MODEL_V2_PATH,
v3_model_path=MODEL_V3_PATH,
v3_features_map_path=MODEL_V3_FEAT
)
print(f"π§ [Processor V70.7] Gate Override Logic Active.")
async def initialize(self):
"""Async Initialization"""
if self.initialized: return True
if self.initialization_attempted: return self.initialized
self.initialization_attempted = True
print("βοΈ [Processor] Starting Neural Grid...")
try:
tasks = []
if self.pattern_net: tasks.append(self.pattern_net.initialize())
if self.oracle: tasks.append(self.oracle.initialize())
if self.sniper:
self.sniper.configure_settings(
threshold=SystemLimits.L4_ENTRY_THRESHOLD,
wall_ratio=SystemLimits.L4_OB_WALL_RATIO,
w_ml=SystemLimits.L4_WEIGHT_ML,
w_ob=SystemLimits.L4_WEIGHT_OB
)
tasks.append(self.sniper.initialize())
if self.mc_analyzer and hasattr(self.mc_analyzer, 'initialize'):
if asyncio.iscoroutinefunction(self.mc_analyzer.initialize):
tasks.append(self.mc_analyzer.initialize())
if tasks: await asyncio.gather(*tasks)
if self.guardian_hydra: self.guardian_hydra.initialize()
if self.guardian_legacy:
if asyncio.iscoroutinefunction(self.guardian_legacy.initialize):
await self.guardian_legacy.initialize()
else:
self.guardian_legacy.initialize()
self.initialized = True
return True
except Exception as e:
print(f"β [Processor] Init Error: {e}")
traceback.print_exc()
return False
# ============================================================
# π’ LAYER 2: Pattern + Oracle + MC (Centered Logic)
# ============================================================
async def execute_layer2_analysis(self, raw_data: Dict[str, Any]) -> Dict[str, Any]:
if not self.initialized: await self.initialize()
symbol = raw_data.get('symbol')
ohlcv = raw_data.get('ohlcv')
limits = raw_data.get('dynamic_limits', {})
result = raw_data.copy()
result.update({
'is_valid': False,
'reason': 'Unknown',
'l2_score': 0.0,
'pattern_score': 0.0,
'oracle_score': 0.0,
'mc_score': 0.0,
'pattern_probs': [0, 0, 0]
})
try:
# 1. Pattern Net Analysis
pattern_res = {'score': 0.0, 'probs': [0,0,0]}
if self.pattern_net:
pattern_res = await asyncio.to_thread(self.pattern_net.predict, ohlcv)
nn_score = pattern_res.get('score', 0.0)
pattern_probs = pattern_res.get('probs', [0,0,0])
result['pattern_score'] = nn_score
result['pattern_probs'] = pattern_probs
# 2. Monte Carlo
mc_val = 0.5
if self.mc_analyzer and '1h' in ohlcv:
try:
closes = [c[4] for c in ohlcv['1h']]
raw_mc = self.mc_analyzer.run_light_check(closes)
mc_val = 0.5 + (raw_mc * 5.0)
mc_val = max(0.0, min(1.0, mc_val))
except: pass
result['mc_score'] = mc_val
# π Soft Gate Check (The Fix)
# We use min() to ensure we pick the MOST PERMISSIVE threshold.
# If dynamic is 0.50 and system is 0.25, we use 0.25.
dynamic_gate = limits.get('l2_gate_pattern', 1.0)
gate_pattern = min(dynamic_gate, SystemLimits.L2_GATE_PATTERN_NET)
if nn_score < gate_pattern:
result['reason'] = f"Pattern Score {nn_score:.2f} < {gate_pattern}"
return result
# 3. Oracle Analysis (Now reachable!)
oracle_input = raw_data.copy()
oracle_input['titan_probs'] = pattern_probs
oracle_input['pattern_probs'] = pattern_probs
oracle_res = {'oracle_score': 0.0}
if self.oracle:
thresh = limits.get('l3_oracle_thresh', 0.005)
if hasattr(self.oracle, 'set_threshold'): self.oracle.set_threshold(thresh)
oracle_res = await self.oracle.predict(oracle_input)
raw_oracle_pred = oracle_res.get('oracle_score', 0.0)
result['oracle_score'] = raw_oracle_pred
# βοΈ SCORING Logic
oracle_val = 50.0 + (raw_oracle_pred / 0.005) * 50.0
oracle_val = max(0.0, min(100.0, oracle_val))
oracle_val_norm = oracle_val / 100.0
# 4. Composite Scoring
composite_score = (
(oracle_val_norm * SystemLimits.L2_WEIGHT_ORACLE) +
(nn_score * SystemLimits.L2_WEIGHT_PATTERN) +
(mc_val * SystemLimits.L2_WEIGHT_MC)
) * 100
result['l2_score'] = composite_score
if composite_score < SystemLimits.L2_MIN_COMPOSITE_SCORE:
result['reason'] = f"Composite {composite_score:.1f} < {SystemLimits.L2_MIN_COMPOSITE_SCORE}"
return result
# β
PASSED
result['is_valid'] = True
result['reason'] = 'PASSED'
result['titan_score'] = nn_score * 100
result['titan_probs'] = pattern_probs
return result
except Exception as e:
print(f"β [Layer 2] Error {symbol}: {e}")
result['reason'] = f"Error: {str(e)}"
return result
# ... (Rest of the class methods identical to V70.6) ...
async def execute_layer4_sniper(self, symbol: str, ohlcv_1m: List, order_book: Dict) -> Dict[str, Any]:
if not self.initialized: await self.initialize()
if not self.sniper: return {'signal': 'WAIT', 'confidence_prob': 0.0, 'reason': 'No Sniper'}
try:
self.sniper.configure_settings(
threshold=SystemLimits.L4_ENTRY_THRESHOLD,
wall_ratio=SystemLimits.L4_OB_WALL_RATIO,
w_ml=SystemLimits.L4_WEIGHT_ML,
w_ob=SystemLimits.L4_WEIGHT_OB
)
result = await self.sniper.check_entry_signal_async(ohlcv_1m, order_book, symbol=symbol)
return result
except Exception as e:
return {'signal': 'WAIT', 'confidence_prob': 0.0, 'reason': f"Sniper Error: {e}"}
def consult_guardians(self, symbol, ohlcv_1m, ohlcv_5m, ohlcv_15m, trade_context, ob_snapshot=None):
if not self.initialized:
return {'action': 'HOLD', 'reason': 'System not initialized', 'probs': {}, 'scores': {}}
limits = trade_context.get('dynamic_limits', {})
h_crash_thresh = limits.get('hydra_crash', SystemLimits.HYDRA_CRASH_THRESH)
h_giveback_thresh = limits.get('hydra_giveback', SystemLimits.HYDRA_GIVEBACK_THRESH)
h_stag_thresh = limits.get('hydra_stagnation', SystemLimits.HYDRA_STAGNATION_THRESH)
entry_price = float(trade_context.get('entry_price', 0.0))
highest_price = trade_context.get('highest_price', entry_price)
max_pnl_pct = ((highest_price - entry_price) / entry_price) * 100 if entry_price > 0 else 0.0
time_in_trade_mins = trade_context.get('time_in_trade_mins', 0.0)
hydra_result = {'action': 'HOLD', 'reason': 'Disabled', 'probs': {}}
if self.guardian_hydra:
try:
hydra_result = self.guardian_hydra.analyze_position(symbol, ohlcv_1m, ohlcv_5m, ohlcv_15m, trade_context)
h_probs = hydra_result.get('probs', {})
p_crash = h_probs.get('crash', 0.0)
p_giveback = h_probs.get('giveback', 0.0)
p_stagnation = h_probs.get('stagnation', 0.0)
if p_crash >= h_crash_thresh:
hydra_result['action'] = 'EXIT_HARD'
hydra_result['reason'] = f"Hydra Crash Risk {p_crash:.2f}"
elif p_giveback >= h_giveback_thresh and max_pnl_pct >= 0.6:
hydra_result['action'] = 'EXIT_SOFT'
hydra_result['reason'] = f"Hydra Giveback {p_giveback:.2f}"
elif p_stagnation >= h_stag_thresh and time_in_trade_mins > 90:
hydra_result['action'] = 'EXIT_SOFT'
hydra_result['reason'] = f"Hydra Stagnation {p_stagnation:.2f}"
except Exception: pass
legacy_result = {'action': 'HOLD', 'reason': 'Disabled', 'scores': {}}
if self.guardian_legacy:
try:
vol_30m = trade_context.get('volume_30m_usd', 0.0)
legacy_result = self.guardian_legacy.analyze_position(
ohlcv_1m, ohlcv_5m, ohlcv_15m, entry_price,
order_book=ob_snapshot,
volume_30m_usd=vol_30m
)
except Exception: pass
final_action = 'HOLD'
final_reason = f"Safe."
hydra_act = hydra_result.get('action', 'HOLD')
legacy_act = legacy_result.get('action', 'HOLD')
if hydra_act in ['EXIT_HARD', 'EXIT_SOFT', 'TIGHTEN_SL', 'TRAIL_SL']:
final_action = hydra_act
final_reason = f"π² {hydra_result.get('reason')}"
elif legacy_act in ['EXIT_HARD', 'EXIT_SOFT']:
final_action = legacy_act
final_reason = f"πΈοΈ {legacy_result.get('reason')}"
return {
'action': final_action,
'reason': final_reason,
'probs': hydra_result.get('probs', {}),
'scores': legacy_result.get('scores', {})
}
async def run_advanced_monte_carlo(self, symbol, timeframe='1h'):
if self.mc_analyzer and self.data_manager:
try:
ohlcv = await self.data_manager.get_latest_ohlcv(symbol, timeframe, limit=300)
if ohlcv: return self.mc_analyzer.run_advanced_simulation([c[4] for c in ohlcv])
except: pass
return 0.0
async def consult_oracle(self, symbol_data: Dict[str, Any]) -> Dict[str, Any]:
if self.oracle: return await self.oracle.predict(symbol_data)
return {'action': 'WAIT'}
async def check_sniper_entry(self, ohlcv_1m_data, order_book_data, context_data=None):
return await self.execute_layer4_sniper("UNKNOWN", ohlcv_1m_data, order_book_data) |