| | |
| | |
| | |
| | |
| |
|
| | import asyncio |
| | import traceback |
| | import logging |
| | import os |
| | import sys |
| | import numpy as np |
| | from typing import Dict, Any, List, Optional |
| |
|
| | |
| | try: from .titan_engine import TitanEngine |
| | except ImportError: TitanEngine = None |
| | try: from .patterns import ChartPatternAnalyzer |
| | except ImportError: ChartPatternAnalyzer = 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_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| | MODELS_L2_DIR = os.path.join(BASE_DIR, "ml_models", "layer2") |
| | MODELS_PATTERN_DIR = os.path.join(BASE_DIR, "ml_models", "xgboost_pattern2") |
| | 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") |
| |
|
| | |
| | |
| | |
| | class SystemLimits: |
| | """ |
| | GEM-Architect: Adjusted Defaults based on real-world calibration. |
| | Oracle Ceiling detected at ~0.75, so Threshold set to 0.60. |
| | """ |
| | |
| | |
| | L1_MIN_AFFINITY_SCORE = 15.0 |
| | |
| | |
| | L2_GATE_TITAN = 0.60 |
| | L2_GATE_PATTERN = 0.50 |
| | L2_GATE_MC = 0.50 |
| | |
| | |
| | L2_MIN_SCORE = 0.65 |
| | L2_WEIGHT_TITAN = 0.40 |
| | L2_WEIGHT_PATTERNS = 0.40 |
| | L2_WEIGHT_MC = 0.20 |
| |
|
| | |
| | PATTERN_TF_WEIGHTS = {'1h': 0.35, '15m': 0.25, '1d': 0.20, '5m': 0.10, '4h': 0.10} |
| | PATTERN_THRESH_BULLISH = 0.50 |
| | PATTERN_THRESH_BEARISH = 0.40 |
| |
|
| | |
| | L3_CONFIDENCE_THRESHOLD = 0.60 |
| | L3_WHALE_IMPACT_MAX = 0.10 |
| | L3_NEWS_IMPACT_MAX = 0.05 |
| | L3_MC_ADVANCED_MAX = 0.10 |
| |
|
| | |
| | L4_ENTRY_THRESHOLD = 0.40 |
| | L4_WEIGHT_ML = 0.60 |
| | L4_WEIGHT_OB = 0.40 |
| | L4_OB_WALL_RATIO = 0.35 |
| |
|
| | |
| | HYDRA_CRASH_THRESH = 0.60 |
| | HYDRA_GIVEBACK_THRESH = 0.80 |
| | 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)} |
| |
|
| | |
| | |
| | |
| | class MLProcessor: |
| | def __init__(self, data_manager=None): |
| | self.data_manager = data_manager |
| | self.initialized = False |
| | |
| | self.titan = TitanEngine(model_dir=MODELS_L2_DIR) if TitanEngine else None |
| | self.pattern_engine = ChartPatternAnalyzer(models_dir=MODELS_PATTERN_DIR) if ChartPatternAnalyzer else None |
| | self.mc_analyzer = MonteCarloEngine() if MonteCarloEngine else None |
| | self.oracle = OracleEngine(model_dir=MODELS_UNIFIED_DIR) if OracleEngine else None |
| | self.sniper = SniperEngine(models_dir=MODELS_SNIPER_DIR) if SniperEngine else None |
| | |
| | self.guardian_hydra = None |
| | if GuardianHydra: |
| | self.guardian_hydra = GuardianHydra(model_dir=MODELS_HYDRA_DIR) |
| |
|
| | 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"๐ง [MLProcessor V68.1] Realistic Mode Loaded (Oracle 0.60).") |
| |
|
| | async def initialize(self): |
| | if self.initialized: return |
| | print("โ๏ธ [Processor] Initializing Neural Grid...") |
| | try: |
| | tasks = [] |
| | if self.titan: tasks.append(self.titan.initialize()) |
| | |
| | if self.pattern_engine: |
| | self.pattern_engine.configure_thresholds( |
| | weights=SystemLimits.PATTERN_TF_WEIGHTS, |
| | bull_thresh=SystemLimits.PATTERN_THRESH_BULLISH, |
| | bear_thresh=SystemLimits.PATTERN_THRESH_BEARISH |
| | ) |
| | tasks.append(self.pattern_engine.initialize()) |
| | |
| | if self.oracle: |
| | if hasattr(self.oracle, 'set_threshold'): |
| | self.oracle.set_threshold(SystemLimits.L3_CONFIDENCE_THRESHOLD) |
| | tasks.append(self.oracle.initialize()) |
| | |
| | if self.sniper: |
| | if hasattr(self.sniper, 'configure_settings'): |
| | 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 tasks: await asyncio.gather(*tasks) |
| |
|
| | if self.guardian_hydra: |
| | self.guardian_hydra.initialize() |
| | print(" ๐ก๏ธ [Guard 1] Hydra X-Ray: Active") |
| | |
| | if self.guardian_legacy: |
| | if asyncio.iscoroutinefunction(self.guardian_legacy.initialize): |
| | await self.guardian_legacy.initialize() |
| | else: |
| | self.guardian_legacy.initialize() |
| | |
| | |
| | self.guardian_legacy.configure_thresholds( |
| | v2_panic=SystemLimits.LEGACY_V2_PANIC_THRESH, |
| | v3_hard=SystemLimits.LEGACY_V3_HARD_THRESH, |
| | v3_soft=SystemLimits.LEGACY_V3_SOFT_THRESH, |
| | v3_ultra=SystemLimits.LEGACY_V3_ULTRA_THRESH |
| | ) |
| | print(f" ๐ก๏ธ [Guard 2] Legacy Steward: Active") |
| |
|
| | self.initialized = True |
| | print("โ
[Processor] All Systems Operational.") |
| | |
| | except Exception as e: |
| | print(f"โ [Processor FATAL] Init failed: {e}") |
| | traceback.print_exc() |
| |
|
| | async def process_compound_signal(self, raw_data: Dict[str, Any]) -> Optional[Dict[str, Any]]: |
| | """ |
| | L2 Processing with Hybrid Gated Scoring (Full Visibility). |
| | """ |
| | if not self.initialized: await self.initialize() |
| | |
| | symbol = raw_data.get('symbol') |
| | ohlcv_data = raw_data.get('ohlcv') |
| | current_price = raw_data.get('current_price', 0.0) |
| | |
| | |
| | limits = raw_data.get('dynamic_limits', {}) |
| | |
| | if not symbol or not ohlcv_data: return None |
| | |
| | try: |
| | |
| | score_titan = 0.5 |
| | titan_res = {} |
| | if self.titan: |
| | titan_res = await asyncio.to_thread(self.titan.predict, ohlcv_data) |
| | score_titan = titan_res.get('score', 0.5) |
| |
|
| | |
| | score_patterns = 0.5 |
| | pattern_res = {} |
| | pattern_name = "Neutral" |
| | if self.pattern_engine: |
| | pattern_res = await self.pattern_engine.detect_chart_patterns(ohlcv_data) |
| | score_patterns = pattern_res.get('pattern_confidence', 0.5) |
| | pattern_name = pattern_res.get('pattern_detected', 'Neutral') |
| |
|
| | |
| | mc_score = 0.5 |
| | if self.mc_analyzer and '1h' in ohlcv_data: |
| | closes = [c[4] for c in ohlcv_data['1h']] |
| | raw_mc = self.mc_analyzer.run_light_check(closes) |
| | mc_score = 0.5 + (raw_mc * 5.0) |
| | mc_score = max(0.0, min(1.0, mc_score)) |
| |
|
| | |
| | |
| | |
| | gate_titan = limits.get('l2_gate_titan', SystemLimits.L2_GATE_TITAN) |
| | gate_patt = limits.get('l2_gate_pattern', SystemLimits.L2_GATE_PATTERN) |
| | gate_mc = limits.get('l2_gate_mc', SystemLimits.L2_GATE_MC) |
| | |
| | rejection_reason = None |
| | is_valid = True |
| |
|
| | |
| | if score_titan < gate_titan: |
| | is_valid = False |
| | rejection_reason = f"Titan {score_titan:.2f} < {gate_titan}" |
| | elif score_patterns < gate_patt: |
| | is_valid = False |
| | rejection_reason = f"Pattern {score_patterns:.2f} < {gate_patt}" |
| | elif mc_score < gate_mc: |
| | is_valid = False |
| | rejection_reason = f"MC {mc_score:.2f} < {gate_mc}" |
| |
|
| | |
| | w_titan = limits.get('w_titan', SystemLimits.L2_WEIGHT_TITAN) |
| | w_patt = limits.get('w_patt', SystemLimits.L2_WEIGHT_PATTERNS) |
| | w_mc = limits.get('w_mc', SystemLimits.L2_WEIGHT_MC) |
| | |
| | total_w = w_titan + w_patt + w_mc |
| | if total_w <= 0: total_w = 1.0 |
| | |
| | hybrid_score = ((score_titan * w_titan) + (score_patterns * w_patt) + (mc_score * w_mc)) / total_w |
| | |
| | |
| | min_l2_score = limits.get('l2_min_score', SystemLimits.L2_MIN_SCORE) |
| | if is_valid and hybrid_score < min_l2_score: |
| | is_valid = False |
| | rejection_reason = f"Hybrid {hybrid_score:.2f} < {min_l2_score}" |
| | |
| | return { |
| | 'symbol': symbol, |
| | 'current_price': current_price, |
| | 'enhanced_final_score': hybrid_score, |
| | 'is_valid': is_valid, |
| | 'rejection_reason': rejection_reason, |
| | 'dynamic_limits': limits, |
| | 'asset_regime': raw_data.get('asset_regime', 'UNKNOWN'), |
| | 'strategy_type': raw_data.get('strategy_type', 'NORMAL'), |
| | 'titan_score': score_titan, |
| | 'patterns_score': score_patterns, |
| | 'mc_score': mc_score, |
| | 'components': { |
| | 'titan_score': score_titan, |
| | 'patterns_score': score_patterns, |
| | 'mc_score': mc_score |
| | }, |
| | 'pattern_name': pattern_name, |
| | 'ohlcv': ohlcv_data, |
| | 'titan_details': titan_res, |
| | 'pattern_details': pattern_res.get('details', {}) |
| | } |
| | except Exception as e: |
| | print(f"โ [Processor] Error processing {symbol}: {e}") |
| | return None |
| |
|
| | async def consult_oracle(self, symbol_data: Dict[str, Any]) -> Dict[str, Any]: |
| | if not self.initialized: await self.initialize() |
| | |
| | |
| | limits = symbol_data.get('dynamic_limits', {}) |
| | threshold = limits.get('l3_oracle_thresh', SystemLimits.L3_CONFIDENCE_THRESHOLD) |
| | |
| | if self.oracle: |
| | if hasattr(self.oracle, 'set_threshold'): |
| | self.oracle.set_threshold(threshold) |
| | |
| | decision = await self.oracle.predict(symbol_data) |
| | conf = decision.get('confidence', 0.0) |
| | |
| | if decision.get('action') in ['WATCH', 'BUY'] and conf < threshold: |
| | decision['action'] = 'WAIT' |
| | decision['reason'] = f"Context Veto: Conf {conf:.2f} < Limit {threshold:.2f}" |
| | |
| | return decision |
| | return {'action': 'WAIT', 'reason': 'Oracle Engine Missing'} |
| |
|
| | async def check_sniper_entry(self, ohlcv_1m_data: List, order_book_data: Dict[str, Any], context_data: Dict = None) -> Dict[str, Any]: |
| | if not self.initialized: await self.initialize() |
| | |
| | limits = context_data.get('dynamic_limits', {}) if context_data else {} |
| | thresh = limits.get('l4_sniper_thresh', SystemLimits.L4_ENTRY_THRESHOLD) |
| | wall_r = limits.get('l4_ob_wall_ratio', SystemLimits.L4_OB_WALL_RATIO) |
| |
|
| | if self.sniper: |
| | if hasattr(self.sniper, 'configure_settings'): |
| | self.sniper.configure_settings( |
| | threshold=thresh, |
| | wall_ratio=wall_r, |
| | w_ml=SystemLimits.L4_WEIGHT_ML, |
| | w_ob=SystemLimits.L4_WEIGHT_OB |
| | ) |
| | return await self.sniper.check_entry_signal_async(ohlcv_1m_data, order_book_data) |
| | |
| | return {'signal': 'WAIT', 'reason': 'Sniper Engine Missing'} |
| |
|
| | def consult_dual_guardians(self, symbol, ohlcv_1m, ohlcv_5m, ohlcv_15m, trade_context, order_book_snapshot=None): |
| | """ |
| | ๐ GEM-Architect: Conditional Hydra & Fixed Legacy Logic |
| | """ |
| | response = {'action': 'HOLD', 'detailed_log': '', 'probs': {}} |
| | |
| | |
| | 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 and self.guardian_hydra.initialized: |
| | 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} >= {h_crash_thresh}" |
| | |
| | |
| | elif p_giveback >= h_giveback_thresh: |
| | if max_pnl_pct >= 0.6: |
| | hydra_result['action'] = 'EXIT_SOFT' |
| | hydra_result['reason'] = f"Hydra Giveback {p_giveback:.2f} (Max PnL {max_pnl_pct:.2f}%)" |
| | else: |
| | hydra_result['action'] = 'HOLD' |
| |
|
| | |
| | elif p_stagnation >= h_stag_thresh: |
| | if time_in_trade_mins > 90: |
| | hydra_result['action'] = 'EXIT_SOFT' |
| | hydra_result['reason'] = f"Hydra Stagnation {p_stagnation:.2f} (>90m)" |
| | else: |
| | hydra_result['action'] = 'HOLD' |
| | |
| | |
| | |
| | |
| | legacy_result = {'action': 'HOLD', 'reason': 'Disabled', 'scores': {}} |
| | if self.guardian_legacy and self.guardian_legacy.initialized: |
| | self.guardian_legacy.configure_thresholds( |
| | v2_panic=0.98, |
| | v3_hard=0.95, |
| | v3_soft=0.88, |
| | v3_ultra=0.99 |
| | ) |
| | 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=order_book_snapshot, |
| | volume_30m_usd=vol_30m |
| | ) |
| |
|
| | |
| | |
| | |
| | h_probs = hydra_result.get('probs', {}) |
| | l_scores = legacy_result.get('scores', {}) |
| | |
| | h_c = h_probs.get('crash', 0.0) |
| | h_g = h_probs.get('giveback', 0.0) |
| | l_v2 = l_scores.get('v2', 0.0) |
| | |
| | stamp_str = f"๐ฒ[C:{h_c:.2f}|G:{h_g:.2f}] ๐ธ๏ธ[V2:{l_v2:.2f}]" |
| |
|
| | final_action = 'HOLD' |
| | final_reason = f"Safe. {stamp_str}" |
| | |
| | if hydra_result['action'] in ['EXIT_HARD', 'EXIT_SOFT', 'TIGHTEN_SL', 'TRAIL_SL']: |
| | final_action = hydra_result['action'] |
| | final_reason = f"๐ฒ HYDRA: {hydra_result['reason']}" |
| | elif legacy_result['action'] in ['EXIT_HARD', 'EXIT_SOFT']: |
| | final_action = legacy_result['action'] |
| | final_reason = f"๐ธ๏ธ LEGACY: {legacy_result['reason']}" |
| |
|
| | return { |
| | 'action': final_action, |
| | 'reason': final_reason, |
| | 'detailed_log': f"{final_action} | {stamp_str}", |
| | 'probs': h_probs, |
| | 'scores': l_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 Exception: pass |
| | return 0.0 |