626 lines
21 KiB
MQL5
626 lines
21 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| DualEA_MasterIntegration.mqh - Complete P0/P1 Integration |
| |||
//| Master include file that initializes all hardened components |
| |||
//| Version: 2.0 - Comprehensive EA Hardening & Intelligence Upgrade |
| |||
//+------------------------------------------------------------------+
| |||
#ifndef DUALEA_MASTERINTEGRATION_MQH
| |||
#define DUALEA_MASTERINTEGRATION_MQH
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| P0 Components - Critical Fixes |
| |||
//+------------------------------------------------------------------+
| |||
#include "CShadowLogger.mqh" // P0-1: Atomic CSV writes
| |||
#include "CGateFeatureCache.mqh" // P0-5: Feature caching
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| P1 Components - Architecture Upgrades |
| |||
//+------------------------------------------------------------------+
| |||
#include "CSQLiteKnowledgeBase.mqh" // P1-1: SQLite KB
| |||
#include "CInsightGateBridge.mqh" // P1-2: O(1) insights bridge
| |||
#include "CRegimeAwareStrategy.mqh" // P1-3: Regime adaptation
| |||
#include "CSystemMonitor.mqh" // P1-4: Health circuit breaker
| |||
// Replaced Redis with SQLite - zero external dependencies
| |||
#include "CSQLiteExplorationCounter.mqh"// P1-5: Redis counters
| |||
#include "CPositionManager.mqh" // P1-6: Correlation sizing
| |||
| |||
// Include existing components
| |||
#include "EnhancedEfficientGateSystem.mqh"
| |||
#include "CMLPolishGateONNX.mqh"
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Configuration Structure |
| |||
//+------------------------------------------------------------------+
| |||
struct SDualEAConfig
| |||
{
| |||
// P0-1: Shadow logging
| |||
bool shadow_logging_enabled;
| |||
bool shadow_mode_only;
| |||
string shadow_log_directory;
| |||
| |||
// P0-4: ONNX monitoring
| |||
bool onnx_health_monitor_enabled;
| |||
int onnx_max_latency_ms;
| |||
| |||
// P0-5: Feature cache
| |||
int feature_cache_max_age_seconds;
| |||
| |||
// P1-1: SQLite
| |||
bool sqlite_enabled;
| |||
string sqlite_db_name;
| |||
| |||
// P1-2: Insight bridge
| |||
int insight_cache_sync_seconds;
| |||
| |||
// P1-4: System monitor
| |||
bool circuit_breaker_enabled;
| |||
double max_tick_latency_ms;
| |||
double max_error_rate_per_hour;
| |||
int circuit_breaker_cooldown_minutes;
| |||
| |||
// P1-5: Redis
| |||
bool redis_enabled;
| |||
string redis_host;
| |||
int redis_port;
| |||
| |||
// P1-6: Position management
| |||
bool correlation_sizing_enabled;
| |||
bool volatility_exits_enabled;
| |||
double max_risk_per_trade_pct;
| |||
double max_total_risk_pct;
| |||
int max_positions;
| |||
| |||
void SetDefaults()
| |||
{
| |||
// P0 defaults
| |||
shadow_logging_enabled = true;
| |||
shadow_mode_only = false;
| |||
shadow_log_directory = "DualEA\\ShadowLogs";
| |||
| |||
// P0-4 defaults
| |||
onnx_health_monitor_enabled = true;
| |||
onnx_max_latency_ms = 100;
| |||
| |||
// P0-5 defaults
| |||
feature_cache_max_age_seconds = 5;
| |||
| |||
// P1-1 defaults
| |||
sqlite_enabled = true;
| |||
sqlite_db_name = "dualea_kb.db";
| |||
| |||
// P1-2 defaults
| |||
insight_cache_sync_seconds = 60;
| |||
| |||
// P1-4 defaults
| |||
circuit_breaker_enabled = true;
| |||
max_tick_latency_ms = 50.0;
| |||
max_error_rate_per_hour = 50.0;
| |||
circuit_breaker_cooldown_minutes = 15;
| |||
| |||
// P1-5 defaults
| |||
redis_enabled = false; // Disabled by default (requires Redis server)
| |||
redis_host = "127.0.0.1";
| |||
redis_port = 6379;
| |||
| |||
// P1-6 defaults
| |||
correlation_sizing_enabled = true;
| |||
volatility_exits_enabled = true;
| |||
max_risk_per_trade_pct = 1.0;
| |||
max_total_risk_pct = 5.0;
| |||
max_positions = 10;
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Dual EA Master Controller |
| |||
//+------------------------------------------------------------------+
| |||
class CDualEAMasterController
| |||
{
| |||
private:
| |||
SDualEAConfig m_config;
| |||
bool m_initialized;
| |||
datetime m_last_status_log;
| |||
| |||
// Component references
| |||
CShadowLogger* m_shadow_logger;
| |||
CGateFeatureCache* m_feature_cache;
| |||
CSQLiteKnowledgeBase* m_sqlite_kb;
| |||
CInsightGateBridge* m_insight_bridge;
| |||
CRegimeAwareStrategy* m_regime_strategy;
| |||
CSystemMonitor* m_system_monitor;
| |||
CSQLiteExplorationCounter* m_explore_counter;
| |||
CPositionManager* m_position_manager;
| |||
| |||
public:
| |||
// Constructor
| |||
CDualEAMasterController()
| |||
{
| |||
m_config.SetDefaults();
| |||
m_initialized = false;
| |||
m_last_status_log = 0;
| |||
m_shadow_logger = NULL;
| |||
m_feature_cache = NULL;
| |||
m_sqlite_kb = NULL;
| |||
m_insight_bridge = NULL;
| |||
m_regime_strategy = NULL;
| |||
m_system_monitor = NULL;
| |||
m_explore_counter = NULL;
| |||
m_position_manager = NULL;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Initialize all components |
| |||
//+------------------------------------------------------------------+
| |||
bool Initialize(const SDualEAConfig &config)
| |||
{
| |||
m_config = config;
| |||
| |||
Print("=== DualEA Master Controller v2.0 Initializing ===");
| |||
| |||
// P0-5: Initialize feature cache first (others depend on it)
| |||
if(!InitializeFeatureCache()) return false;
| |||
| |||
// P1-1: Initialize SQLite KB
| |||
if(m_config.sqlite_enabled)
| |||
{
| |||
if(!InitializeSQLiteKB()) return false;
| |||
}
| |||
| |||
// P1-3: Initialize regime strategy (depends on feature cache)
| |||
if(!InitializeRegimeStrategy()) return false;
| |||
| |||
// P1-2: Initialize insight bridge (depends on SQLite KB)
| |||
if(m_config.sqlite_enabled)
| |||
{
| |||
if(!InitializeInsightBridge()) return false;
| |||
}
| |||
| |||
// P1-4: Initialize system monitor
| |||
if(m_config.circuit_breaker_enabled)
| |||
{
| |||
if(!InitializeSystemMonitor()) return false;
| |||
}
| |||
| |||
// P1-5: Initialize exploration counter (SQLite-based)
| |||
if(!InitializeExploreCounter()) return false;
| |||
| |||
// P1-6: Initialize position manager (depends on feature cache and regime)
| |||
if(!InitializePositionManager()) return false;
| |||
| |||
// P0-1: Initialize shadow logger
| |||
if(m_config.shadow_logging_enabled)
| |||
{
| |||
if(!InitializeShadowLogger()) return false;
| |||
}
| |||
| |||
m_initialized = true;
| |||
Print("=== DualEA Master Controller v2.0 Ready ===");
| |||
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Component initializers |
| |||
//+------------------------------------------------------------------+
| |||
bool InitializeFeatureCache()
| |||
{
| |||
m_feature_cache = new CGateFeatureCache();
| |||
if(!m_feature_cache.Initialize())
| |||
{
| |||
Print("[MasterController] ERROR: Feature cache initialization failed");
| |||
return false;
| |||
}
| |||
| |||
// Set global reference for gates
| |||
g_gate_feature_cache = m_feature_cache;
| |||
| |||
Print("[MasterController] P0-5: Feature cache initialized");
| |||
return true;
| |||
}
| |||
| |||
bool InitializeSQLiteKB()
| |||
{
| |||
m_sqlite_kb = new CSQLiteKnowledgeBase(m_config.sqlite_db_name);
| |||
if(!m_sqlite_kb.Initialize())
| |||
{
| |||
Print("[MasterController] WARNING: SQLite KB init failed, continuing with reduced functionality");
| |||
// Don't fail completely - we can work without SQLite
| |||
delete m_sqlite_kb;
| |||
m_sqlite_kb = NULL;
| |||
m_config.sqlite_enabled = false;
| |||
return true;
| |||
}
| |||
| |||
g_sqlite_kb = m_sqlite_kb;
| |||
Print("[MasterController] P1-1: SQLite KB initialized");
| |||
return true;
| |||
}
| |||
| |||
bool InitializeInsightBridge()
| |||
{
| |||
m_insight_bridge = new CInsightGateBridge(m_sqlite_kb);
| |||
if(!m_insight_bridge.Initialize(m_sqlite_kb))
| |||
{
| |||
Print("[MasterController] WARNING: Insight bridge init failed");
| |||
delete m_insight_bridge;
| |||
m_insight_bridge = NULL;
| |||
return true; // Don't fail completely
| |||
}
| |||
| |||
// CRITICAL: Preload historical data to populate bridge stats immediately
| |||
m_insight_bridge.PreloadHotStrategies();
| |||
| |||
g_insight_gate_bridge = m_insight_bridge;
| |||
Print("[MasterController] P1-2: Insight-Gate bridge initialized with historical data");
| |||
return true;
| |||
}
| |||
| |||
bool InitializeRegimeStrategy()
| |||
{
| |||
m_regime_strategy = new CRegimeAwareStrategy(m_feature_cache);
| |||
| |||
g_regime_strategy = m_regime_strategy;
| |||
Print("[MasterController] P1-3: Regime-aware strategy initialized");
| |||
return true;
| |||
}
| |||
| |||
bool InitializeSystemMonitor()
| |||
{
| |||
m_system_monitor = new CSystemMonitor();
| |||
| |||
// Thresholds are configured internally via SHealthThresholds.SetDefaults()
| |||
// m_system_monitor.SetThresholds() is not available - using default thresholds
| |||
| |||
g_system_monitor = m_system_monitor;
| |||
Print("[MasterController] P1-4: System monitor with circuit breaker initialized");
| |||
return true;
| |||
}
| |||
| |||
bool InitializeExploreCounter()
| |||
{
| |||
m_explore_counter = new CSQLiteExplorationCounter();
| |||
if(!m_explore_counter.Initialize())
| |||
{
| |||
Print("[MasterController] WARNING: Exploration counter init failed, using fallback");
| |||
delete m_explore_counter;
| |||
m_explore_counter = NULL;
| |||
return true; // Don't fail - fallback is built-in
| |||
}
| |||
| |||
g_sqliteCounter = m_explore_counter;
| |||
Print("[MasterController] P1-5: SQLite exploration counter initialized");
| |||
return true;
| |||
}
| |||
| |||
bool InitializePositionManager()
| |||
{
| |||
m_position_manager = new CPositionManager(m_feature_cache, m_regime_strategy);
| |||
| |||
// Configure
| |||
m_position_manager.SetMaxPositions(m_config.max_positions);
| |||
m_position_manager.SetMaxRiskPerTrade(m_config.max_risk_per_trade_pct);
| |||
m_position_manager.SetMaxTotalRisk(m_config.max_total_risk_pct);
| |||
| |||
SVolatilityExitConfig vol_config;
| |||
vol_config.SetDefaults();
| |||
m_position_manager.SetVolatilityExitConfig(vol_config);
| |||
| |||
g_position_manager = m_position_manager;
| |||
Print("[MasterController] P1-6: Position manager with correlation sizing initialized");
| |||
return true;
| |||
}
| |||
| |||
bool InitializeShadowLogger()
| |||
{
| |||
m_shadow_logger = new CShadowLogger();
| |||
| |||
if(!m_shadow_logger.Initialize(m_config.shadow_mode_only, m_config.shadow_log_directory))
| |||
{
| |||
Print("[MasterController] WARNING: Shadow logger init failed");
| |||
delete m_shadow_logger;
| |||
m_shadow_logger = NULL;
| |||
return true; // Don't fail
| |||
}
| |||
| |||
Print("[MasterController] P0-1: Shadow logger with atomic CSV initialized");
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| OnTick processing - call from EA's OnTick() |
| |||
//+------------------------------------------------------------------+
| |||
void OnTick()
| |||
{
| |||
if(!m_initialized) return;
| |||
| |||
// P0-5: Update feature cache
| |||
if(m_feature_cache != NULL)
| |||
m_feature_cache.Update();
| |||
| |||
// P1-3: Update regime detection
| |||
if(m_regime_strategy != NULL)
| |||
m_regime_strategy.Update();
| |||
| |||
// P1-4: Update system monitor
| |||
if(m_system_monitor != NULL)
| |||
m_system_monitor.OnTickUpdate();
| |||
| |||
// P1-6: Check volatility exits
| |||
if(m_position_manager != NULL)
| |||
m_position_manager.CheckVolatilityExits();
| |||
| |||
// P1-2: Sync insight bridge periodically
| |||
if(m_insight_bridge != NULL && m_system_monitor != NULL)
| |||
{
| |||
static int tick_counter = 0;
| |||
tick_counter++;
| |||
if(tick_counter % 600 == 0) // Every ~10 seconds (assuming 60 ticks/sec)
| |||
{
| |||
m_insight_bridge.OnTickSync();
| |||
}
| |||
}
| |||
| |||
// Log status periodically
| |||
if(TimeCurrent() - m_last_status_log > 300) // Every 5 minutes
| |||
{
| |||
LogSystemStatus();
| |||
m_last_status_log = TimeCurrent();
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Check if trading is allowed (circuit breaker) |
| |||
//+------------------------------------------------------------------+
| |||
bool IsTradingAllowed(string &reason)
| |||
{
| |||
reason = "";
| |||
| |||
// P1-4: Check system monitor circuit breaker
| |||
if(m_system_monitor != NULL && m_system_monitor.IsCircuitBreakerActive())
| |||
{
| |||
reason = "Circuit breaker: " + m_system_monitor.GetCircuitBreakerReason();
| |||
return false;
| |||
}
| |||
| |||
// P1-3: Check regime allows trading
| |||
if(m_regime_strategy != NULL)
| |||
{
| |||
if(!m_regime_strategy.IsTradingAllowed(reason))
| |||
{
| |||
return false;
| |||
}
| |||
}
| |||
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Process trade signal through all gates |
| |||
//+------------------------------------------------------------------+
| |||
bool ProcessTradeSignal(TradingSignal &signal,
| |||
CEfficientGateManagerEnhanced &gate_manager,
| |||
string &block_reason)
| |||
{
| |||
// P1-3: Apply regime-adjusted parameters
| |||
if(m_regime_strategy != NULL)
| |||
{
| |||
double min_confidence = m_regime_strategy.GetMinConfidenceThreshold();
| |||
// Could adjust gate thresholds here
| |||
}
| |||
| |||
// P1-2: Fast gate decision using insights
| |||
if(m_insight_bridge != NULL)
| |||
{
| |||
double signal_confidence = m_insight_bridge.GetSignalConfidence(
| |||
signal.strategy, signal.symbol);
| |||
| |||
if(signal_confidence < 0.4)
| |||
{
| |||
// Adjust-only mode: do not block, but penalize confidence and annotate reason
| |||
signal.confidence = MathMax(0.05, MathMin(1.0, signal.confidence * signal_confidence));
| |||
block_reason = "Low insight confidence (soft): " + DoubleToString(signal_confidence, 2);
| |||
}
| |||
}
| |||
| |||
// P1-6: Check position limits
| |||
if(m_position_manager != NULL)
| |||
{
| |||
double risk_amount = 0; // Calculate based on signal
| |||
if(!m_position_manager.CanOpenPosition(signal.symbol, signal.type,
| |||
risk_amount, block_reason))
| |||
{
| |||
return false;
| |||
}
| |||
}
| |||
| |||
// Process through gate cascade
| |||
CSignalDecision decision;
| |||
return gate_manager.ProcessSignalEnhanced(signal, decision, block_reason);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Log gate decision to shadow log |
| |||
//+------------------------------------------------------------------+
| |||
void LogGateDecision(const string &gate_name, const TradingSignal &signal,
| |||
bool passed, double confidence, double threshold)
| |||
{
| |||
if(m_shadow_logger != NULL)
| |||
{
| |||
SShadowLogEntry entry;
| |||
entry.Init(signal.symbol, signal.direction == 0 ? "BUY" : "SELL",
| |||
signal.price, signal.volume, signal.strategy);
| |||
| |||
// Convert gate_name to gate number for entry
| |||
int gate_num = 0;
| |||
if(gate_name == "G1") gate_num = 0;
| |||
else if(gate_name == "G2") gate_num = 1;
| |||
else if(gate_name == "G3") gate_num = 2;
| |||
else if(gate_name == "G4") gate_num = 3;
| |||
else if(gate_name == "G5") gate_num = 4;
| |||
else if(gate_name == "G6") gate_num = 5;
| |||
else if(gate_name == "G7") gate_num = 6;
| |||
else if(gate_name == "G8") gate_num = 7;
| |||
| |||
entry.gate_passed[gate_num] = passed;
| |||
entry.gate_confidence[gate_num] = confidence;
| |||
entry.gate_threshold[gate_num] = threshold;
| |||
entry.gate_block_reason[gate_num] = passed ? "" : "Below threshold";
| |||
| |||
m_shadow_logger.LogGateDecision(entry);
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Record completed trade |
| |||
//+------------------------------------------------------------------+
| |||
void RecordTrade(const STradeRecord &trade)
| |||
{
| |||
// P1-1: Log to SQLite
| |||
if(m_sqlite_kb != NULL)
| |||
{
| |||
m_sqlite_kb.LogTrade(trade);
| |||
}
| |||
| |||
// P1-2: Update insight bridge
| |||
if(m_insight_bridge != NULL)
| |||
{
| |||
m_insight_bridge.OnTradeCompleted(trade.strategy, trade.symbol,
| |||
trade.pnl, trade.r_multiple);
| |||
}
| |||
| |||
// P1-4: Update system monitor
| |||
if(m_system_monitor != NULL)
| |||
{
| |||
m_system_monitor.RecordTrade();
| |||
}
| |||
| |||
// P1-6: Remove from position tracking
| |||
if(m_position_manager != NULL && trade.id > 0)
| |||
{
| |||
// m_position_manager->RemovePosition((ulong)trade.id);
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Get position size with all adjustments |
| |||
//+------------------------------------------------------------------+
| |||
double CalculatePositionSize(const TradingSignal &signal, double risk_pct)
| |||
{
| |||
if(m_position_manager == NULL) return 0;
| |||
| |||
double account_balance = AccountInfoDouble(ACCOUNT_BALANCE);
| |||
| |||
return m_position_manager.CalculatePositionSize(
| |||
signal.symbol,
| |||
signal.type,
| |||
signal.price,
| |||
signal.sl,
| |||
risk_pct,
| |||
account_balance
| |||
);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Log system status |
| |||
//+------------------------------------------------------------------+
| |||
void LogSystemStatus()
| |||
{
| |||
string status = "=== DualEA System Status ===\n";
| |||
| |||
// P1-4: System monitor status
| |||
if(m_system_monitor != NULL)
| |||
{
| |||
status += "Health: " + m_system_monitor.GetHealthReport() + "\n";
| |||
}
| |||
| |||
// P1-3: Regime status
| |||
if(m_regime_strategy != NULL)
| |||
{
| |||
status += "Regime: " + m_regime_strategy.RegimeToString(
| |||
m_regime_strategy.GetCurrentRegime()) + "\n";
| |||
}
| |||
| |||
// P1-6: Position status
| |||
if(m_position_manager != NULL)
| |||
{
| |||
status += "Positions: " + m_position_manager.GetRiskReport() + "\n";
| |||
}
| |||
| |||
// P1-2: Bridge status
| |||
if(m_insight_bridge != NULL)
| |||
{
| |||
double hit_rate, avg_lookup;
| |||
int cache_size;
| |||
m_insight_bridge.GetStats(hit_rate, avg_lookup, cache_size);
| |||
status += StringFormat("Insights: HitRate=%.1f%% Latency=%.2fus Cache=%d\n",
| |||
hit_rate * 100, avg_lookup, cache_size);
| |||
}
| |||
| |||
Print(status);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Shutdown all components |
| |||
//+------------------------------------------------------------------+
| |||
void Shutdown()
| |||
{
| |||
Print("=== DualEA Master Controller v2.0 Shutting Down ===");
| |||
| |||
// Save all data
| |||
if(m_sqlite_kb != NULL) m_sqlite_kb.Close();
| |||
| |||
// Cleanup
| |||
if(m_shadow_logger != NULL) { delete m_shadow_logger; m_shadow_logger = NULL; }
| |||
if(m_position_manager != NULL) { delete m_position_manager; m_position_manager = NULL; }
| |||
if(m_system_monitor != NULL) { delete m_system_monitor; m_system_monitor = NULL; }
| |||
if(m_insight_bridge != NULL) { delete m_insight_bridge; m_insight_bridge = NULL; }
| |||
if(m_regime_strategy != NULL) { delete m_regime_strategy; m_regime_strategy = NULL; }
| |||
if(m_sqlite_kb != NULL) { delete m_sqlite_kb; m_sqlite_kb = NULL; }
| |||
if(m_feature_cache != NULL) { delete m_feature_cache; m_feature_cache = NULL; }
| |||
| |||
m_initialized = false;
| |||
Print("=== DualEA Master Controller v2.0 Shutdown Complete ===");
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Getters |
| |||
//+------------------------------------------------------------------+
| |||
CRegimeAwareStrategy* GetRegimeStrategy() { return m_regime_strategy; }
| |||
CPositionManager* GetPositionManager() { return m_position_manager; }
| |||
CSystemMonitor* GetSystemMonitor() { return m_system_monitor; }
| |||
CInsightGateBridge* GetInsightBridge() { return m_insight_bridge; }
| |||
CSQLiteKnowledgeBase* GetSQLiteKB() { return m_sqlite_kb; }
| |||
bool IsInitialized() { return m_initialized; }
| |||
};
| |||
| |||
// Global master controller instance
| |||
CDualEAMasterController* g_master_controller = NULL;
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Initialize DualEA Master Controller |
| |||
//+------------------------------------------------------------------+
| |||
bool InitializeDualEAMasterController(const SDualEAConfig &config)
| |||
{
| |||
if(g_master_controller != NULL)
| |||
{
| |||
g_master_controller.Shutdown();
| |||
delete g_master_controller;
| |||
}
| |||
| |||
g_master_controller = new CDualEAMasterController();
| |||
return g_master_controller.Initialize(config);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Shutdown DualEA Master Controller |
| |||
//+------------------------------------------------------------------+
| |||
void ShutdownDualEAMasterController()
| |||
{
| |||
if(g_master_controller != NULL)
| |||
{
| |||
g_master_controller.Shutdown();
| |||
delete g_master_controller;
| |||
g_master_controller = NULL;
| |||
}
| |||
}
| |||
| |||
#endif // DUALEA_MASTERINTEGRATION_MQH
|