2026-08-06 00:19:52 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| ProcessController.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"
|
| | |
|
| | | // ProcessController.mqh
|
| | | #include "Market/DataManager.mqh"
|
| | | #include "Analysers/IAnalyser.mqh"
|
| | |
|
2026-08-09 07:14:59 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-08-14 16:18:08 +02:00 | | | class ProcessController final
|
2026-08-09 07:14:59 +02:00 | | | {
|
2026-08-06 00:19:52 +02:00 | | | private:
|
| | | DataManager* m_data;
|
| | | IAnalyser* m_chapters[];
|
| | | int m_chapterCount;
|
2026-08-10 20:23:58 +02:00 | | | EventBus* m_eventBus;
|
2026-08-06 00:19:52 +02:00 | | |
|
| | | // Time‑based tracking – one entry per symbol/tf (same order as rawData)
|
| | | datetime m_lastProcessedTime[];
|
| | | int m_seriesCount;
|
| | |
|
| | | // Launch progress (used only during initial replay)
|
| | | int m_launchProgress[]; // bar index for each series
|
| | |
|
2026-08-14 16:18:08 +02:00 | | | void RunAllChapters(TfBarSeries &series, int barIndex)
|
2026-08-09 07:14:59 +02:00 | | | {
|
2026-08-06 00:19:52 +02:00 | | | for(int c = 0; c < m_chapterCount; c++)
|
| | | m_chapters[c].ProcessBar(series, barIndex);
|
2026-08-09 07:14:59 +02:00 | | | }
|
2026-08-06 00:19:52 +02:00 | | |
|
| | | public:
|
2026-08-09 07:14:59 +02:00 | | | ProcessController() : m_data(NULL), m_chapterCount(0), m_seriesCount(0) {}
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-10 20:23:58 +02:00 | | | void Initialize(EventBus* eventBus, DataManager &dm)
|
2026-08-09 07:14:59 +02:00 | | | {
|
2026-08-06 00:19:52 +02:00 | | | m_eventBus = eventBus;
|
| | | m_data = &dm;
|
2026-08-09 07:14:59 +02:00 | | | }
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | void AddChapter(IAnalyser* chapter, EventBus* _eventBus)
|
2026-08-09 07:14:59 +02:00 | | | {
|
2026-08-06 00:19:52 +02:00 | | | int sz = ArraySize(m_chapters);
|
| | | ArrayResize(m_chapters, sz + 1);
|
2026-08-14 16:18:08 +02:00 | | | chapter.Init(_eventBus);
|
2026-08-06 00:19:52 +02:00 | | | m_chapters[sz] = chapter;
|
| | | m_chapterCount = sz + 1;
|
2026-08-09 07:14:59 +02:00 | | | }
|
2026-08-06 00:19:52 +02:00 | | |
|
| | | //---------------------------------------------------------------
|
| | | // Launch – replay all historical bars through every chapter
|
| | | //---------------------------------------------------------------
|
2026-08-14 16:18:08 +02:00 | | | void ProcessController::Launch()
|
| | | {
|
| | | if(m_data == NULL) return;
|
| | | CArrayList<TfBarSeries*>* rawData = m_data.GetRawData(); // pointer to list
|
| | | int totalSeries = rawData.Size();
|
| | |
|
| | | ArrayResize(m_launchProgress, totalSeries);
|
| | | ArrayResize(m_lastProcessedTime, totalSeries);
|
| | | for(int i = 0; i < totalSeries; i++)
|
| | | {
|
| | | m_launchProgress[i] = 0;
|
| | | m_lastProcessedTime[i] = 0;
|
| | | }
|
| | | m_seriesCount = totalSeries;
|
| | |
|
| | | for(int i = 0; i < totalSeries; i++)
|
| | | {
|
| | | TfBarSeries* series = rawData.At(i); // pointer
|
| | | int total = series.TotalBars();
|
| | | for(int barIdx = 0; barIdx < total; barIdx++)
|
| | | RunAllChapters(*series, barIdx);
|
| | | if(total > 0)
|
| | | m_lastProcessedTime[i] = series.Time(total - 1);
|
| | | }
|
| | | }
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | //---------------------------------------------------------------
|
| | | // Update – process only newly arrived bars using time comparison
|
| | | //---------------------------------------------------------------
|
| | | void Update()
|
| | | {
|
| | | if(m_data == NULL) return;
|
| | | CArrayList<TfBarSeries*>* rawData = m_data.GetRawData();
|
| | | int totalSeries = rawData.Size();
|
| | |
|
| | | if(totalSeries > m_seriesCount)
|
| | | {
|
2026-08-06 00:19:52 +02:00 | | | ArrayResize(m_lastProcessedTime, totalSeries);
|
2026-08-14 16:18:08 +02:00 | | | for(int i = m_seriesCount; i < totalSeries; i++)
|
2026-08-06 00:19:52 +02:00 | | | m_lastProcessedTime[i] = 0;
|
| | | m_seriesCount = totalSeries;
|
2026-08-14 16:18:08 +02:00 | | | }
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | for(int i = 0; i < totalSeries; i++)
|
| | | {
|
| | | TfBarSeries* series = rawData.At(i);
|
| | | int total = series.TotalBars();
|
| | | if(total == 0) continue;
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | datetime latestBarTime = series.Time(total - 1);
|
| | | if(latestBarTime <= m_lastProcessedTime[i]) continue;
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | for(int barIdx = 0; barIdx < total; barIdx++)
|
| | | if(series.Time(barIdx) > m_lastProcessedTime[i])
|
| | | RunAllChapters(*series, barIdx);
|
2026-08-06 00:19:52 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | m_lastProcessedTime[i] = latestBarTime;
|
| | | }
|
| | | }
|
2026-08-09 07:14:59 +02:00 | | | void RelaunchSeries(int index);
|
| | | };
|
| | | void ProcessController::RelaunchSeries(int index)
|
2026-08-14 16:18:08 +02:00 | | | {
|
| | | TfBarSeries* series = m_data.GetRawData().At(index); // pointer
|
2026-08-09 07:14:59 +02:00 | | |
|
2026-08-14 16:18:08 +02:00 | | | for(int c = 0; c < m_chapterCount; c++)
|
2026-08-09 07:14:59 +02:00 | | | m_chapters[c].Reset(series.symbol, series.tf);
|
| | |
|
| | | m_lastProcessedTime[index] = 0;
|
| | |
|
| | | int total = series.TotalBars();
|
| | | for(int barIdx = 0; barIdx < total; barIdx++)
|
| | | RunAllChapters(*series, barIdx);
|
| | |
|
| | | if(total > 0)
|
| | | m_lastProcessedTime[index] = series.Time(total - 1);
|
2026-08-14 16:18:08 +02:00 | | | }
|