//+------------------------------------------------------------------+ //| EventBus.mqh - Unified Event System for Cross-Component Communication | //+------------------------------------------------------------------+ #ifndef __EVENTBUS_MQH__ #define __EVENTBUS_MQH__ #include // Event types enumeration enum EVENT_TYPE { EVENT_GATE_PROCESSED, // Gate processing completed EVENT_SIGNAL_GENERATED, // New trading signal generated EVENT_INSIGHTS_UPDATED, // Insights data updated EVENT_TRADE_EXECUTED, // Trade execution completed EVENT_SYSTEM_STATUS, // System status change EVENT_CONFIG_CHANGED, // Configuration updated EVENT_ERROR_OCCURRED, // Error event EVENT_PERFORMANCE_METRIC // Performance metric update }; // Event data structure struct EventData { EVENT_TYPE type; string source; string data; datetime timestamp; int priority; // 0=low, 1=normal, 2=high, 3=critical EventData() { type = EVENT_SYSTEM_STATUS; source = ""; data = ""; timestamp = TimeCurrent(); priority = 1; } }; // Event subscriber interface class IEventSubscriber { public: virtual ~IEventSubscriber() {} virtual void OnEvent(const EventData& event) = 0; virtual string GetSubscriberName() = 0; }; // Simple event subscriber for function callbacks class CFunctionSubscriber : public IEventSubscriber { private: string m_name; public: CFunctionSubscriber(const string& name) : m_name(name) {} void OnEvent(const EventData& event) override { // Default implementation - can be overridden Print("[", m_name, "] Received event: ", EnumToString(event.type), " from ", event.source); } string GetSubscriberName() override { return m_name; } }; // Event bus singleton class CEventBus { private: static CEventBus* instance; IEventSubscriber* subscribers[EVENT_PERFORMANCE_METRIC + 1][10]; // Max 10 subscribers per event type int subscriber_counts[EVENT_PERFORMANCE_METRIC + 1]; EventData event_history[100]; // Keep last 100 events int history_index; bool verbose_logging; CEventBus() { // Initialize subscriber arrays for(int i = 0; i <= EVENT_PERFORMANCE_METRIC; i++) { subscriber_counts[i] = 0; for(int j = 0; j < 10; j++) subscribers[i][j] = NULL; } history_index = 0; verbose_logging = false; } public: static CEventBus* GetInstance() { if(instance == NULL) instance = new CEventBus(); return instance; } static void Cleanup() { if(instance != NULL) { delete instance; instance = NULL; } } // Subscribe to events bool Subscribe(EVENT_TYPE event_type, IEventSubscriber* subscriber) { if(subscriber == NULL || event_type < 0 || event_type > EVENT_PERFORMANCE_METRIC) return false; int count = subscriber_counts[event_type]; if(count >= 10) // Max subscribers reached { Print("EventBus: Maximum subscribers reached for event type ", EnumToString(event_type)); return false; } subscribers[event_type][count] = subscriber; subscriber_counts[event_type]++; if(verbose_logging) Print("EventBus: Subscriber '", subscriber.GetSubscriberName(), "' registered for ", EnumToString(event_type)); return true; } // Unsubscribe from events bool Unsubscribe(EVENT_TYPE event_type, IEventSubscriber* subscriber) { if(subscriber == NULL || event_type < 0 || event_type > EVENT_PERFORMANCE_METRIC) return false; int count = subscriber_counts[event_type]; for(int i = 0; i < count; i++) { if(subscribers[event_type][i] == subscriber) { // Shift remaining subscribers for(int j = i; j < count - 1; j++) subscribers[event_type][j] = subscribers[event_type][j + 1]; subscribers[event_type][count - 1] = NULL; subscriber_counts[event_type]--; if(verbose_logging) Print("EventBus: Subscriber '", subscriber.GetSubscriberName(), "' unregistered from ", EnumToString(event_type)); return true; } } return false; } // Publish event to all subscribers void Publish(EVENT_TYPE event_type, const string& source, const string& data, int priority = 1) { EventData event; event.type = event_type; event.source = source; event.data = data; event.timestamp = TimeCurrent(); event.priority = priority; // Store in history event_history[history_index] = event; history_index = (history_index + 1) % 100; // Log event if verbose if(verbose_logging || priority >= 2) // Always log high priority events { Print("EventBus: [", source, "] ", EnumToString(event_type), " - ", data); } // Notify all subscribers int count = subscriber_counts[event_type]; for(int i = 0; i < count; i++) { if(subscribers[event_type][i] != NULL) { subscribers[event_type][i].OnEvent(event); } } } // Convenience methods for common events void PublishGateEvent(const string& gate_name, bool passed, const string& reason) { string data = StringFormat("%s|%s|%s", gate_name, (passed ? "PASS" : "FAIL"), reason); Publish(EVENT_GATE_PROCESSED, "GateManager", data, 1); } void PublishSignalEvent(const string& signal_id, const string& symbol, double confidence) { string data = StringFormat("%s|%s|%s", signal_id, symbol, DoubleToString(confidence, 3)); Publish(EVENT_SIGNAL_GENERATED, "SignalGenerator", data, 1); } void PublishInsightsEvent(const string& action, const string& details) { string data = StringFormat("%s|%s", action, details); Publish(EVENT_INSIGHTS_UPDATED, "InsightsManager", data, 1); } void PublishTradeEvent(const string& trade_id, const string& action, double result) { string data = StringFormat("%s|%s|%s", trade_id, action, DoubleToString(result, 2)); Publish(EVENT_TRADE_EXECUTED, "TradeManager", data, 2); } void PublishSystemEvent(const string& component, const string& status) { Publish(EVENT_SYSTEM_STATUS, component, status, 1); } void PublishErrorEvent(const string& component, const string& error_msg) { Publish(EVENT_ERROR_OCCURRED, component, error_msg, 3); } void PublishPerformanceEvent(const string& metric_name, double value) { string data = metric_name + "|" + DoubleToString(value, 4); Publish(EVENT_PERFORMANCE_METRIC, "SystemMonitor", data, 1); } // Configuration void SetVerboseLogging(bool enabled) { verbose_logging = enabled; } bool IsVerboseLogging() { return verbose_logging; } // Event history access EventData GetLastEvent(EVENT_TYPE event_type) { // Search backwards through history for the last event of this type for(int i = 0; i < 100; i++) { int index = (history_index - 1 - i + 100) % 100; if(event_history[index].type == event_type && event_history[index].timestamp > 0) return event_history[index]; } EventData empty; return empty; } int GetEventCount(EVENT_TYPE event_type) { int count = 0; for(int i = 0; i < 100; i++) { if(event_history[i].type == event_type && event_history[i].timestamp > 0) count++; } return count; } // Debug information void PrintSubscriberInfo() { Print("=== EventBus Subscriber Information ==="); for(int i = 0; i <= EVENT_PERFORMANCE_METRIC; i++) { if(subscriber_counts[i] > 0) { Print("Event Type ", EnumToString((EVENT_TYPE)i), ": ", subscriber_counts[i], " subscribers"); for(int j = 0; j < subscriber_counts[i]; j++) { if(subscribers[i][j] != NULL) Print(" - ", subscribers[i][j].GetSubscriberName()); } } } } void PrintEventHistory(int count = 10) { Print("=== EventBus Recent Events (last ", count, ") ==="); for(int i = 0; i < MathMin(count, 100); i++) { int index = (history_index - 1 - i + 100) % 100; EventData event = event_history[index]; if(event.timestamp > 0) { Print("[", TimeToString(event.timestamp), "] ", event.source, " -> ", EnumToString(event.type), ": ", event.data); } } } }; // Static instance declaration static CEventBus* CEventBus::instance = NULL; #endif