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
|