2026-08-04 23:54:09 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| Runtime.mqh |
|
| | | //| Copyright 2025, MetaQuotes Ltd. |
|
| | | //| https://www.mql5.com |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2025, MetaQuotes Ltd."
|
| | | #property link "https://www.mql5.com"
|
| | | #property version "1.00"
|
| | |
|
| | | #include "Market/DataManager.mqh"
|
| | |
|
2026-08-10 20:23:58 +02:00 | | | #include "Configs/EAConfig.mqh"
|
2026-08-06 00:19:52 +02:00 | | | #include "Events/EventBus/EventBus.mqh"
|
| | | #include "Events/LoadingListener.mqh"
|
| | |
|
2026-08-14 16:18:08 +02:00 | | | #include "Analysers/IAnalyser.mqh"
|
| | | #include "Strategies/AbstractStrategy.mqh"
|
2026-08-10 20:23:58 +02:00 | | |
|
| | | #include "Trade/TradeExecutor.mqh"
|
| | | #include "Trade/TradeManager.mqh"
|
| | | #include "Trade/RiskManager.mqh"
|
| | |
|
| | | #include "Trade/Trackers/OrderTracker.mqh"
|
2026-08-14 16:18:08 +02:00 | | | #include "ProcessController.mqh"
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| Helper struct for registration storage |
|
| | | //+------------------------------------------------------------------+
|
| | | class ListenerRegistration
|
| | | {
|
| | | public:
|
| | | EventType eventType;
|
| | | IEventListener* listener;
|
| | | };
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-04 23:54:09 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-08-14 16:18:08 +02:00 | | | class Re : public IEventListener
|
2026-08-04 23:54:09 +02:00 | | | {
|
2026-08-14 16:18:08 +02:00 | | | public:
|
| | | virtual void OnEvent(AbstractEvent* event) override
|
| | | {
|
| | |
|
| | | if(event.GetType() != RISK_REJECTED)
|
| | | return;
|
| | | RiskRejectedEvent* sig = (RiskRejectedEvent*)event;
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | // Print("RiskRejected: ", sig.GetReason());
|
| | | }
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Main runtime class |
|
| | | //+------------------------------------------------------------------+
|
| | | class Runtime final
|
| | | {
|
| | | private:
|
| | | DataManager m_dataManager;
|
| | | EventBus* m_eventBus;
|
| | | ProcessController m_controller;
|
2026-08-09 07:14:59 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | LoadingListener m_loader;
|
| | | TimeHelpers m_timeHelper;
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | CTradeExecutor* executor;
|
| | | TradeManager* tradeMgr;
|
| | | RiskManager* riskMgr;
|
| | | OrderTracker* orderTracker;
|
| | | Re re;
|
| | | CArrayList<ListenerRegistration*> m_registrations;
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | void SubscribeAll();
|
| | | void UnsubscribeAll();
|
| | | void ClearRegistrations();
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-04 23:54:09 +02:00 | | | public:
|
| | | Runtime();
|
| | | ~Runtime();
|
| | |
|
2026-08-10 20:23:58 +02:00 | | | int Initialize(EAConfig &eaConfig);
|
2026-08-14 16:18:08 +02:00 | | | void Update(int count =3);
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | // Registration helpers
|
| | | void AddListener(int eventType, IEventListener* listener);
|
| | | void AddAnalyser(IAnalyser* analyser)
|
| | | {
|
| | | // analyser.Init(m_eventBus);
|
| | | m_controller.AddChapter(analyser, m_eventBus);
|
| | | }
|
2026-08-04 23:54:09 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | void AddStrategy(AbstractStrategy* strategy);
|
2026-08-04 23:54:09 +02:00 | | | };
|
2026-08-14 16:18:08 +02:00 | | |
|
2026-08-04 23:54:09 +02:00 | | | //+------------------------------------------------------------------+
|
2026-08-14 16:18:08 +02:00 | | | //| Constructor |
|
2026-08-04 23:54:09 +02:00 | | | //+------------------------------------------------------------------+
|
| | | Runtime::Runtime()
|
| | | {
|
2026-08-10 20:23:58 +02:00 | | | m_eventBus = new EventBus();
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | tradeMgr = new TradeManager();
|
| | | executor = new CTradeExecutor();
|
| | | riskMgr = new RiskManager();
|
2026-08-10 20:23:58 +02:00 | | | orderTracker = new OrderTracker();
|
2026-08-04 23:54:09 +02:00 | | | }
|
2026-08-14 16:18:08 +02:00 | | |
|
2026-08-04 23:54:09 +02:00 | | | //+------------------------------------------------------------------+
|
2026-08-14 16:18:08 +02:00 | | | //| Destructor |
|
2026-08-04 23:54:09 +02:00 | | | //+------------------------------------------------------------------+
|
| | | Runtime::~Runtime()
|
| | | {
|
2026-08-14 16:18:08 +02:00 | | | UnsubscribeAll(); // automatic bulk unsubscribe
|
| | | ClearRegistrations(); // free registration objects
|
2026-08-10 20:23:58 +02:00 | | |
|
| | | delete m_eventBus;
|
| | | delete tradeMgr;
|
| | | delete executor;
|
| | | delete orderTracker;
|
| | | delete riskMgr;
|
2026-08-04 23:54:09 +02:00 | | | }
|
2026-08-14 16:18:08 +02:00 | | |
|
2026-08-04 23:54:09 +02:00 | | | //+------------------------------------------------------------------+
|
2026-08-14 16:18:08 +02:00 | | | //| One‑time initialisation |
|
2026-08-04 23:54:09 +02:00 | | | //+------------------------------------------------------------------+
|
2026-08-10 20:23:58 +02:00 | | | int Runtime::Initialize(EAConfig &eaConfig)
|
2026-08-04 23:54:09 +02:00 | | | {
|
2026-08-09 07:14:59 +02:00 | | | if(!m_loader.Initialize())
|
| | | return INIT_FAILED;
|
| | |
|
2026-08-14 16:18:08 +02:00 | | | // --- Register all event listeners (subscription happens later) ---
|
| | | AddListener(LOADING, &m_loader);
|
| | | AddListener(RISK_REJECTED, &re);
|
| | | AddListener(NEW_BAR, tradeMgr);
|
| | | AddListener(EXECUTE_MARKET_ORDER, tradeMgr);
|
| | | AddListener(EXECUTE_PENDING_ORDER, tradeMgr);
|
| | | AddListener(SIGNAL, riskMgr);
|
| | | AddListener(POSITION_OPENED, riskMgr);
|
| | | AddListener(PENDING_ORDER_PLACED, orderTracker);
|
| | | AddListener(ORDER_DELETED, orderTracker);
|
| | |
|
| | | // --- Loading sequence -------------------------------------------
|
| | | m_eventBus.Push(new LoadingEvent(START, 6, "Starting..."));
|
2026-08-10 20:23:58 +02:00 | | | m_eventBus.Dispatch();
|
2026-08-09 07:14:59 +02:00 | | | Sleep(500 * 4);
|
| | |
|
2026-08-14 16:18:08 +02:00 | | | m_eventBus.Push(new LoadingEvent(UPDATE, "Initializing Data Manager..."));
|
2026-08-09 07:14:59 +02:00 | | | m_eventBus.Dispatch();
|
2026-08-14 16:18:08 +02:00 | | | m_dataManager.Initialize(m_eventBus, eaConfig.tfConfigs, eaConfig.indConfigs,eaConfig.asSeries);
|
| | | Sleep(500);
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | m_eventBus.Push(new LoadingEvent(UPDATE, "Subscribing..."));
|
2026-08-10 20:23:58 +02:00 | | | m_eventBus.Dispatch();
|
2026-08-14 16:18:08 +02:00 | | | SubscribeAll(); // bulk subscribe
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | m_eventBus.Push(new LoadingEvent(UPDATE, "Initializing Trade Executor..."));
|
2026-08-10 20:23:58 +02:00 | | | m_eventBus.Dispatch();
|
2026-08-14 16:18:08 +02:00 | | | executor.SetMagic(eaConfig.magicNumber);
|
| | | executor.SetDeviation(eaConfig.Slippage);
|
2026-08-10 20:23:58 +02:00 | | | Sleep(500);
|
| | |
|
2026-08-14 16:18:08 +02:00 | | | m_eventBus.Push(new LoadingEvent(UPDATE, "Initializing Systems..."));
|
2026-08-10 20:23:58 +02:00 | | | m_eventBus.Dispatch();
|
2026-08-14 16:18:08 +02:00 | | | m_controller.Initialize(m_eventBus, m_dataManager);
|
2026-08-10 20:23:58 +02:00 | | |
|
| | | riskMgr.Initialize(m_eventBus, eaConfig);
|
2026-08-14 16:18:08 +02:00 | | | tradeMgr.Initialize(m_eventBus, executor, eaConfig);
|
| | | orderTracker.Initialize(m_eventBus);
|
2026-08-10 20:23:58 +02:00 | | |
|
| | |
|
| | |
|
| | | Sleep(500);
|
| | |
|
2026-08-14 16:18:08 +02:00 | | | m_eventBus.Push(new LoadingEvent(UPDATE, "Launching..."));
|
2026-08-10 20:23:58 +02:00 | | | m_eventBus.Dispatch();
|
2026-08-14 16:18:08 +02:00 | | | m_controller.Launch();
|
2026-08-10 20:23:58 +02:00 | | | Sleep(500);
|
| | |
|
2026-08-14 16:18:08 +02:00 | | | m_eventBus.Push(new LoadingEvent(UPDATE, "Finished"));
|
2026-08-10 20:23:58 +02:00 | | | m_eventBus.Dispatch();
|
2026-08-14 16:18:08 +02:00 | | | Sleep(125);
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | m_eventBus.Push(new LoadingEvent(CLOSE, ""));
|
| | | m_eventBus.Dispatch();
|
| | | riskMgr.SetLaunching(false);
|
| | | return INIT_SUCCEEDED;
|
| | | }
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| Add a listener to the registration list (does NOT subscribe yet) |
|
| | | //+------------------------------------------------------------------+
|
| | | void Runtime::AddListener(int eventType, IEventListener* listener)
|
| | | {
|
| | | ListenerRegistration* reg = new ListenerRegistration();
|
| | | reg.eventType = eventType;
|
| | | reg.listener = listener;
|
| | | m_registrations.Add(reg);
|
| | | }
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| Convenience: adds a strategy, sets its EventBus, subscribes it |
|
| | | //+------------------------------------------------------------------+
|
| | | void Runtime::AddStrategy(AbstractStrategy* strategy)
|
| | | {
|
| | | strategy.SetEventBus(m_eventBus); // inject bus
|
| | | AddListener(ANALYSIS, strategy); // register for ANALYSIS events
|
| | | }
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| Subscribe all registered listeners to the event bus |
|
| | | //+------------------------------------------------------------------+
|
| | | void Runtime::SubscribeAll()
|
| | | {
|
| | | for(int i = 0; i < m_registrations.Size(); i++)
|
| | | {
|
| | | ListenerRegistration* reg = m_registrations.At(i);
|
| | | m_eventBus.Subscribe(reg.eventType, reg.listener);
|
| | | }
|
| | | }
|
2026-08-09 07:14:59 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| Unsubscribe all registered listeners |
|
| | | //+------------------------------------------------------------------+
|
| | | void Runtime::UnsubscribeAll()
|
| | | {
|
| | | for(int i = 0; i < m_registrations.Size(); i++)
|
| | | {
|
| | | ListenerRegistration* reg = m_registrations.At(i);
|
| | | m_eventBus.Unsubscribe(reg.eventType, reg.listener);
|
| | | }
|
| | | }
|
2026-08-10 20:23:58 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| Delete all registration objects |
|
| | | //+------------------------------------------------------------------+
|
| | | void Runtime::ClearRegistrations()
|
| | | {
|
| | | for(int i = 0; i < m_registrations.Size(); i++)
|
| | | delete m_registrations.At(i);
|
| | | m_registrations.Clear();
|
2026-08-04 23:54:09 +02:00 | | | }
|
2026-08-09 07:14:59 +02:00 | | |
|
2026-08-04 23:54:09 +02:00 | | | //+------------------------------------------------------------------+
|
2026-08-14 16:18:08 +02:00 | | | //| Per‑tick update |
|
2026-08-06 00:19:52 +02:00 | | | //+------------------------------------------------------------------+
|
2026-08-14 16:18:08 +02:00 | | | void Runtime::Update(int count =3)
|
2026-08-06 00:19:52 +02:00 | | | {
|
2026-08-14 16:18:08 +02:00 | | | m_dataManager.Update(count);
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-09 07:14:59 +02:00 | | | CArrayList<TfBarSeries*> rawData = m_dataManager.GetRawData();
|
| | | for(int i = 0; i < rawData.Size(); i++)
|
| | | if(m_dataManager.CheckAndRelaunch(i))
|
| | | m_controller.RelaunchSeries(i);
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-09 07:14:59 +02:00 | | | m_controller.Update();
|
| | | m_eventBus.Dispatch();
|
2026-08-06 00:19:52 +02:00 | | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-14 16:18:08 +02:00 | | | //+------------------------------------------------------------------+
|