//+------------------------------------------------------------------+ //| ConfigManager.mqh - Unified Configuration Management | //+------------------------------------------------------------------+ #ifndef __CONFIGMANAGER_MQH__ #define __CONFIGMANAGER_MQH__ #include "LogMiddleware.mqh" // Gate configuration structure struct GateConfig { bool enabled; double threshold; int cooldown_sec; double success_rate_target; string name; GateConfig() { enabled = true; threshold = 0.5; cooldown_sec = 0; success_rate_target = 0.75; name = ""; } }; // Insights configuration structure struct InsightsConfig { bool auto_reload; int freshness_minutes; int poll_interval_sec; int stale_hours; int min_source_advance_hours; int min_interval_hours; int rebuild_timeout_ms; InsightsConfig() { auto_reload = true; freshness_minutes = 60; poll_interval_sec = 30; stale_hours = 48; min_source_advance_hours = 48; min_interval_hours = 24; rebuild_timeout_ms = 1800000; // 30 minutes } }; // System configuration structure struct SystemConfig { bool no_constraints_mode; bool verbose_logging; string data_path; int max_records; SystemConfig() { no_constraints_mode = false; verbose_logging = false; data_path = "DualEA"; max_records = 10000; } }; // Singleton configuration manager class CConfigManager { private: static CConfigManager* instance; GateConfig gate_configs[8]; InsightsConfig insights_config; SystemConfig system_config; bool initialized; CConfigManager() { initialized = false; InitializeDefaults(); } int FindGateIndex(const string &gate_name) const { for(int i = 0; i < 8; i++) { if(gate_configs[i].name == gate_name) return i; } return -1; } void InitializeDefaults() { // Initialize gate configurations with defaults gate_configs[0].name = "SignalRinse"; gate_configs[0].threshold = 0.6; gate_configs[0].success_rate_target = 0.75; gate_configs[1].name = "MarketSoap"; gate_configs[1].threshold = 0.02; gate_configs[1].success_rate_target = 0.78; gate_configs[2].name = "StrategyScrub"; gate_configs[2].threshold = 0.55; gate_configs[2].success_rate_target = 0.82; gate_configs[3].name = "RiskWash"; gate_configs[3].threshold = 0.02; gate_configs[3].success_rate_target = 0.85; gate_configs[4].name = "PerformanceWax"; gate_configs[4].threshold = 0.6; gate_configs[4].success_rate_target = 0.79; gate_configs[5].name = "MLPolish"; gate_configs[5].threshold = 0.75; gate_configs[5].success_rate_target = 0.82; gate_configs[6].name = "LiveClean"; gate_configs[6].threshold = 0.001; gate_configs[6].success_rate_target = 0.88; gate_configs[7].name = "FinalVerify"; gate_configs[7].threshold = 0.0; gate_configs[7].success_rate_target = 0.95; initialized = true; } public: static CConfigManager* GetInstance() { if(instance == NULL) instance = new CConfigManager(); return instance; } static void Cleanup() { if(instance != NULL) { delete instance; instance = NULL; } } // Gate configuration methods GateConfig GetGateConfig(int gate_index) { if(gate_index >= 0 && gate_index < 8) return gate_configs[gate_index]; GateConfig empty; return empty; } GateConfig GetGateConfig(const string& gate_name) { int index = FindGateIndex(gate_name); if(index >= 0) return gate_configs[index]; GateConfig empty; return empty; } void SetGateConfig(int gate_index, const GateConfig& config) { if(gate_index >= 0 && gate_index < 8) gate_configs[gate_index] = config; } void SetGateThreshold(int gate_index, double threshold) { if(gate_index >= 0 && gate_index < 8) gate_configs[gate_index].threshold = threshold; } void SetGateEnabled(int gate_index, bool enabled) { if(gate_index >= 0 && gate_index < 8) gate_configs[gate_index].enabled = enabled; } // Insights configuration methods InsightsConfig GetInsightsConfig() { return insights_config; } void SetInsightsConfig(const InsightsConfig& config) { insights_config = config; } // System configuration methods SystemConfig GetSystemConfig() { return system_config; } void SetSystemConfig(const SystemConfig& config) { system_config = config; } // Convenience methods bool IsNoConstraintsMode() { return system_config.no_constraints_mode; } void SetNoConstraintsMode(bool enabled) { system_config.no_constraints_mode = enabled; } bool IsVerboseLogging() { return system_config.verbose_logging; } void SetVerboseLogging(bool enabled) { system_config.verbose_logging = enabled; } string GetDataPath() { return system_config.data_path; } void SetDataPath(const string& path) { system_config.data_path = path; } // Configuration persistence (optional - can be extended) void SaveToFile(const string& filename) { // Save configuration to JSON file int h = FileOpen(filename, FILE_WRITE|FILE_TXT|FILE_COMMON); if(h == INVALID_HANDLE) { string err_msg = StringFormat("ConfigManager: Cannot create config file %s, error: %d", filename, GetLastError()); LOG(err_msg); return; } FileWriteString(h, "{\n"); FileWriteString(h, " \"gate_configs\": {\n"); for(int i = 0; i < 8; i++) { GateConfig config = gate_configs[i]; string line = StringFormat( " \"%s\": { \"enabled\": %s, \"threshold\": %.6f, \"cooldown_sec\": %d, \"success_rate_target\": %.4f }", config.name, config.enabled ? "true" : "false", config.threshold, config.cooldown_sec, config.success_rate_target ); if(i < 7) line += ","; line += "\n"; FileWriteString(h, line); } FileWriteString(h, " },\n"); string system_line = StringFormat( " \"system\": { \"no_constraints_mode\": %s, \"verbose_logging\": %s, \"data_path\": \"%s\", \"max_records\": %d },\n", system_config.no_constraints_mode ? "true" : "false", system_config.verbose_logging ? "true" : "false", system_config.data_path, system_config.max_records ); FileWriteString(h, system_line); string insights_line = StringFormat( " \"insights\": { \"auto_reload\": %s, \"freshness_minutes\": %d, \"poll_interval_sec\": %d, \"stale_hours\": %d, \"min_source_advance_hours\": %d, \"min_interval_hours\": %d, \"rebuild_timeout_ms\": %d }\n", insights_config.auto_reload ? "true" : "false", insights_config.freshness_minutes, insights_config.poll_interval_sec, insights_config.stale_hours, insights_config.min_source_advance_hours, insights_config.min_interval_hours, insights_config.rebuild_timeout_ms ); FileWriteString(h, insights_line); FileWriteString(h, "}\n"); FileClose(h); string save_msg = StringFormat("Configuration saved to: %s", filename); LOG(save_msg); } void LoadFromFile(const string& filename) { // Load configuration from JSON file int h = FileOpen(filename, FILE_READ|FILE_TXT|FILE_COMMON); if(h == INVALID_HANDLE) { h = FileOpen(filename, FILE_READ|FILE_TXT); // Try user files if(h == INVALID_HANDLE) { string open_err = StringFormat("ConfigManager: Cannot open config file %s, error: %d", filename, GetLastError()); LOG(open_err); return; } } string line; while(!FileIsEnding(h)) { line = FileReadString(h); // Parse gate config entries int name_start = StringFind(line, "\""); if(name_start >= 0) { int name_end = StringFind(line, "\"", name_start + 1); if(name_end > name_start) { string gate_name = StringSubstr(line, name_start + 1, name_end - name_start - 1); GateConfig config = GetGateConfig(gate_name); // Enabled flag int enabled_pos = StringFind(line, "\"enabled\":"); if(enabled_pos >= 0) { string enabled_str = StringSubstr(line, enabled_pos + 10); if(StringFind(enabled_str, "true") >= 0) config.enabled = true; else if(StringFind(enabled_str, "false") >= 0) config.enabled = false; } // Threshold int threshold_pos = StringFind(line, "\"threshold\":"); if(threshold_pos >= 0) { string threshold_str = StringSubstr(line, threshold_pos + 12); config.threshold = StringToDouble(threshold_str); } // Cooldown int cooldown_pos = StringFind(line, "\"cooldown_sec\":"); if(cooldown_pos >= 0) { string cooldown_str = StringSubstr(line, cooldown_pos + 15); config.cooldown_sec = (int)StringToInteger(cooldown_str); } // Success rate target int target_pos = StringFind(line, "\"success_rate_target\":"); if(target_pos >= 0) { string target_str = StringSubstr(line, target_pos + 22); config.success_rate_target = StringToDouble(target_str); } int gate_index = FindGateIndex(gate_name); if(gate_index >= 0) { SetGateConfig(gate_index, config); } else if(gate_name != "") { LOG(StringFormat("ConfigManager: Unknown gate name in config file: %s", gate_name)); } } } } FileClose(h); LOG(StringFormat("Configuration loaded from: %s", filename)); } // Debug information void PrintConfiguration() { LOG("=== DualEA Configuration ==="); LOG(StringFormat("System - No Constraints: %s", system_config.no_constraints_mode ? "true" : "false")); LOG(StringFormat("System - Verbose Logging: %s", system_config.verbose_logging ? "true" : "false")); LOG(StringFormat("System - Data Path: %s", system_config.data_path)); LOG(StringFormat("Insights - Auto Reload: %s", insights_config.auto_reload ? "true" : "false")); LOG(StringFormat("Insights - Freshness Minutes: %d", insights_config.freshness_minutes)); LOG(StringFormat("Insights - Poll Interval: %d", insights_config.poll_interval_sec)); for(int i = 0; i < 8; i++) { LOG(StringFormat("Gate %d (%s) - Enabled: %s, Threshold: %.6f", i, gate_configs[i].name, gate_configs[i].enabled ? "true" : "false", gate_configs[i].threshold)); } } }; // Static instance declaration static CConfigManager* CConfigManager::instance = NULL; #endif