259 lines
8.7 KiB
MQL5
259 lines
8.7 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| 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"
| |
| |
#include "Configs/EAConfig.mqh"
| |
#include "Events/EventBus/EventBus.mqh"
| |
#include "Events/LoadingListener.mqh"
| |
| |
#include "Analysers/IAnalyser.mqh"
| |
#include "Strategies/AbstractStrategy.mqh"
| |
| |
#include "Trade/TradeExecutor.mqh"
| |
#include "Trade/TradeManager.mqh"
| |
#include "Trade/RiskManager.mqh"
| |
| |
#include "Trade/Trackers/OrderTracker.mqh"
| |
#include "ProcessController.mqh"
| |
| |
//+------------------------------------------------------------------+
| |
//| Helper struct for registration storage |
| |
//+------------------------------------------------------------------+
| |
class ListenerRegistration
| |
{
| |
public:
| |
EventType eventType;
| |
IEventListener* listener;
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
class Re : public IEventListener
| |
{
| |
public:
| |
virtual void OnEvent(AbstractEvent* event) override
| |
{
| |
| |
if(event.GetType() != RISK_REJECTED)
| |
return;
| |
RiskRejectedEvent* sig = (RiskRejectedEvent*)event;
| |
| |
// Print("RiskRejected: ", sig.GetReason());
| |
}
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| Main runtime class |
| |
//+------------------------------------------------------------------+
| |
class Runtime final
| |
{
| |
private:
| |
DataManager m_dataManager;
| |
EventBus* m_eventBus;
| |
ProcessController m_controller;
| |
| |
LoadingListener m_loader;
| |
TimeHelpers m_timeHelper;
| |
| |
CTradeExecutor* executor;
| |
TradeManager* tradeMgr;
| |
RiskManager* riskMgr;
| |
OrderTracker* orderTracker;
| |
Re re;
| |
CArrayList<ListenerRegistration*> m_registrations;
| |
| |
void SubscribeAll();
| |
void UnsubscribeAll();
| |
void ClearRegistrations();
| |
| |
public:
| |
Runtime();
| |
~Runtime();
| |
| |
int Initialize(EAConfig &eaConfig);
| |
void Update(int count =3);
| |
| |
// Registration helpers
| |
void AddListener(int eventType, IEventListener* listener);
| |
void AddAnalyser(IAnalyser* analyser)
| |
{
| |
// analyser.Init(m_eventBus);
| |
m_controller.AddChapter(analyser, m_eventBus);
| |
}
| |
| |
void AddStrategy(AbstractStrategy* strategy);
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| Constructor |
| |
//+------------------------------------------------------------------+
| |
Runtime::Runtime()
| |
{
| |
m_eventBus = new EventBus();
| |
| |
tradeMgr = new TradeManager();
| |
executor = new CTradeExecutor();
| |
riskMgr = new RiskManager();
| |
orderTracker = new OrderTracker();
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Destructor |
| |
//+------------------------------------------------------------------+
| |
Runtime::~Runtime()
| |
{
| |
UnsubscribeAll(); // automatic bulk unsubscribe
| |
ClearRegistrations(); // free registration objects
| |
| |
delete m_eventBus;
| |
delete tradeMgr;
| |
delete executor;
| |
delete orderTracker;
| |
delete riskMgr;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| One‑time initialisation |
| |
//+------------------------------------------------------------------+
| |
int Runtime::Initialize(EAConfig &eaConfig)
| |
{
| |
if(!m_loader.Initialize())
| |
return INIT_FAILED;
| |
| |
// --- 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..."));
| |
m_eventBus.Dispatch();
| |
Sleep(500 * 4);
| |
| |
m_eventBus.Push(new LoadingEvent(UPDATE, "Initializing Data Manager..."));
| |
m_eventBus.Dispatch();
| |
m_dataManager.Initialize(m_eventBus, eaConfig.tfConfigs, eaConfig.indConfigs,eaConfig.asSeries);
| |
Sleep(500);
| |
| |
m_eventBus.Push(new LoadingEvent(UPDATE, "Subscribing..."));
| |
m_eventBus.Dispatch();
| |
SubscribeAll(); // bulk subscribe
| |
| |
m_eventBus.Push(new LoadingEvent(UPDATE, "Initializing Trade Executor..."));
| |
m_eventBus.Dispatch();
| |
executor.SetMagic(eaConfig.magicNumber);
| |
executor.SetDeviation(eaConfig.Slippage);
| |
Sleep(500);
| |
| |
m_eventBus.Push(new LoadingEvent(UPDATE, "Initializing Systems..."));
| |
m_eventBus.Dispatch();
| |
m_controller.Initialize(m_eventBus, m_dataManager);
| |
| |
riskMgr.Initialize(m_eventBus, eaConfig);
| |
tradeMgr.Initialize(m_eventBus, executor, eaConfig);
| |
orderTracker.Initialize(m_eventBus);
| |
| |
| |
| |
Sleep(500);
| |
| |
m_eventBus.Push(new LoadingEvent(UPDATE, "Launching..."));
| |
m_eventBus.Dispatch();
| |
m_controller.Launch();
| |
Sleep(500);
| |
| |
m_eventBus.Push(new LoadingEvent(UPDATE, "Finished"));
| |
m_eventBus.Dispatch();
| |
Sleep(125);
| |
| |
m_eventBus.Push(new LoadingEvent(CLOSE, ""));
| |
m_eventBus.Dispatch();
| |
riskMgr.SetLaunching(false);
| |
return INIT_SUCCEEDED;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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);
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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);
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Delete all registration objects |
| |
//+------------------------------------------------------------------+
| |
void Runtime::ClearRegistrations()
| |
{
| |
for(int i = 0; i < m_registrations.Size(); i++)
| |
delete m_registrations.At(i);
| |
m_registrations.Clear();
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Per‑tick update |
| |
//+------------------------------------------------------------------+
| |
void Runtime::Update(int count =3)
| |
{
| |
m_dataManager.Update(count);
| |
| |
CArrayList<TfBarSeries*> rawData = m_dataManager.GetRawData();
| |
for(int i = 0; i < rawData.Size(); i++)
| |
if(m_dataManager.CheckAndRelaunch(i))
| |
m_controller.RelaunchSeries(i);
| |
| |
m_controller.Update();
| |
m_eventBus.Dispatch();
| |
}
| |
//+------------------------------------------------------------------+
| |
//+------------------------------------------------------------------+
|