| //+------------------------------------------------------------------+
|
| //| CDualEAController.mqh - P0-P5 Master Controller |
|
| //| Singleton controller managing all P0-P5 hardening systems |
|
| //+------------------------------------------------------------------+
|
| #ifndef CDUALEACONTROLLER_MQH
|
| #define CDUALEACONTROLLER_MQH
|
|
|
| #include "DualEA_MasterIntegration.mqh"
|
| #include "CSystemMonitor.mqh"
|
| #include "CSQLiteExplorationCounter.mqh"
|
| #include "CSQLiteKnowledgeBase.mqh"
|
| #include "CArchitectureConfig.mqh"
|
| #include "CErrorHandling.mqh"
|
| #include "CResourceManager.mqh"
|
|
|
| // Forward declarations
|
| class CIndicatorCache;
|
| class CFeatureDriftDetector;
|
|
|
| // Indicator types enum
|
| enum ENUM_INDICATOR_TYPE
|
| {
|
| INDI_MA,
|
| INDI_RSI,
|
| INDI_ATR,
|
| INDI_MACD,
|
| INDI_ADX,
|
| INDI_STOCHASTIC,
|
| INDI_CCI,
|
| INDI_MOMENTUM,
|
| INDI_WILLIAMS,
|
| INDI_DEMARKER,
|
| INDI_FORCE_INDEX,
|
| INDI_BULLS_POWER,
|
| INDI_BEARS_POWER,
|
| INDI_RVI,
|
| INDI_OSMA,
|
| INDI_TRIX,
|
| INDI_AC,
|
| INDI_AO,
|
| INDI_ALLIGATOR,
|
| INDI_GATOR,
|
| INDI_ICHIMOKU,
|
| INDI_FRACTALS,
|
| INDI_ZIGZAG,
|
| INDI_UO
|
| };
|
|
|
| // Note: SDualEAConfig is defined in DualEA_MasterIntegration.mqh
|
| // and included via CDualEAController.mqh dependencies
|
|
|
| //+------------------------------------------------------------------+
|
| //| Dual EA Controller Class - Singleton |
|
| //+------------------------------------------------------------------+
|
| class CDualEAController
|
| {
|
| private:
|
| static CDualEAController* s_instance;
|
|
|
| SDualEAConfig m_config;
|
| bool m_initialized;
|
| CSystemMonitor* m_system_monitor;
|
| CSQLiteKnowledgeBase* m_sqlite_kb;
|
| CIndicatorCache* m_indicator_cache;
|
| CFeatureDriftDetector* m_feature_drift;
|
|
|
| // CPU budgeting
|
| ulong m_last_tick_cpu_ms;
|
| int m_cpu_budget_pct;
|
|
|
| // Gate tracking
|
| struct SGateRecord
|
| {
|
| string name;
|
| bool passed;
|
| double confidence;
|
| datetime timestamp;
|
| };
|
| SGateRecord m_gate_records[];
|
| int m_gate_record_count;
|
|
|
| // Daily tracking
|
| double m_daily_pnl;
|
| double m_max_drawdown;
|
| int m_consecutive_losses;
|
|
|
| public:
|
| CDualEAController()
|
| {
|
| m_initialized = false;
|
| m_system_monitor = NULL;
|
| m_sqlite_kb = NULL;
|
| m_indicator_cache = NULL;
|
| m_feature_drift = NULL;
|
| m_last_tick_cpu_ms = 0;
|
| m_cpu_budget_pct = 50;
|
| m_gate_record_count = 0;
|
| m_daily_pnl = 0.0;
|
| m_max_drawdown = 0.0;
|
| m_consecutive_losses = 0;
|
| ArrayResize(m_gate_records, 0);
|
| }
|
|
|
| ~CDualEAController()
|
| {
|
| Shutdown();
|
| }
|
|
|
| static CDualEAController* Instance()
|
| {
|
| if(s_instance == NULL)
|
| s_instance = new CDualEAController();
|
| return s_instance;
|
| }
|
|
|
| static void Destroy()
|
| {
|
| if(s_instance != NULL)
|
| {
|
| delete s_instance;
|
| s_instance = NULL;
|
| }
|
| }
|
|
|
| bool Initialize(SDualEAConfig &config)
|
| {
|
| if(m_initialized) return true;
|
|
|
| m_config = config;
|
|
|
| // Initialize system monitor
|
| m_system_monitor = new CSystemMonitor();
|
|
|
| // Initialize SQLite KB if enabled
|
| if(config.sqlite_enabled)
|
| {
|
| m_sqlite_kb = new CSQLiteKnowledgeBase(config.sqlite_db_name);
|
| if(!m_sqlite_kb.Initialize())
|
| {
|
| delete m_sqlite_kb;
|
| m_sqlite_kb = NULL;
|
| }
|
| }
|
|
|
| m_initialized = true;
|
| Print("[DualEAController] P0-P5 controller initialized");
|
| return true;
|
| }
|
|
|
| void Shutdown()
|
| {
|
| if(m_sqlite_kb != NULL)
|
| {
|
| m_sqlite_kb.Close();
|
| delete m_sqlite_kb;
|
| m_sqlite_kb = NULL;
|
| }
|
|
|
| if(m_system_monitor != NULL)
|
| {
|
| delete m_system_monitor;
|
| m_system_monitor = NULL;
|
| }
|
|
|
| m_initialized = false;
|
| }
|
|
|
| CSQLiteKnowledgeBase* GetSQLiteKB() { return m_sqlite_kb; }
|
| CIndicatorCache* GetIndicatorCache() { return m_indicator_cache; }
|
| CFeatureDriftDetector* GetFeatureDrift() { return m_feature_drift; }
|
|
|
| bool PreGateValidation(const string gate_name, const double &features[], double threshold)
|
| {
|
| // P2: Pre-gate validation with concept drift check
|
| if(m_feature_drift != NULL)
|
| {
|
| // Check for feature drift before allowing gate processing
|
| return true; // Simplified - always allow in stub
|
| }
|
| return true;
|
| }
|
|
|
| bool ShouldProcessGate(const string gate_name, bool &was_skipped)
|
| {
|
| // P3: CPU budgeting - skip non-essential gates under load
|
| // G1, G4, G7, G8 are never skipped per spec
|
| if(gate_name == "G1" || gate_name == "G4" || gate_name == "G7" || gate_name == "G8")
|
| {
|
| was_skipped = false;
|
| return true;
|
| }
|
|
|
| // Check CPU budget
|
| if(m_cpu_budget_pct < 20) // Under high load
|
| {
|
| was_skipped = true;
|
| return false;
|
| }
|
|
|
| was_skipped = false;
|
| return true;
|
| }
|
|
|
| void PostGateRecord(const string gate_name, bool passed, double confidence)
|
| {
|
| // Record gate result for auditing
|
| int idx = m_gate_record_count;
|
| ArrayResize(m_gate_records, idx + 1);
|
| m_gate_records[idx].name = gate_name;
|
| m_gate_records[idx].passed = passed;
|
| m_gate_records[idx].confidence = confidence;
|
| m_gate_records[idx].timestamp = TimeCurrent();
|
| m_gate_record_count++;
|
| }
|
|
|
| bool SelectStrategyForExecution(const string strategy_name, const double &signals[])
|
| {
|
| // P2-5: Correlation-aware strategy selection
|
| return true; // Simplified - always allow in stub
|
| }
|
|
|
| bool CheckCircuitBreakers(double daily_pnl_pct, double drawdown_pct,
|
| int consecutive_losses, string &reason)
|
| {
|
| // P4-3: Nuclear risk engine circuit breakers
|
| if(drawdown_pct > 10.0)
|
| {
|
| reason = "Max drawdown exceeded: " + DoubleToString(drawdown_pct, 2) + "%";
|
| return true; // Circuit breaker triggered
|
| }
|
|
|
| if(consecutive_losses > 5)
|
| {
|
| reason = "Max consecutive losses: " + IntegerToString(consecutive_losses);
|
| return true;
|
| }
|
|
|
| return false; // No circuit breaker
|
| }
|
|
|
| double GetRecommendedPositionSize(double base_size)
|
| {
|
| // P4-3: Kelly criterion position sizing (simplified)
|
| return base_size;
|
| }
|
|
|
| string GetStatusReport()
|
| {
|
| string report = "=== DualEA Controller Status ===\n";
|
| report += "Initialized: " + (m_initialized ? "Yes" : "No") + "\n";
|
| report += "SQLite KB: " + (m_sqlite_kb != NULL ? "Active" : "Inactive") + "\n";
|
| report += "Gate records: " + IntegerToString(m_gate_record_count) + "\n";
|
| return report;
|
| }
|
| };
|
|
|
| // Static instance initialization
|
| CDualEAController* CDualEAController::s_instance = NULL;
|
|
|
| // Global pointer for P0-P5 integration (defined in PaperEA_v2_P0P5_Integration.mqh)
|
| // extern CDualEAController* g_dual_ea_controller;
|
|
|
| #endif // CDUALEACONTROLLER_MQH
|