263 lines
6.9 KiB
MQL5
263 lines
6.9 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| 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
|