//+------------------------------------------------------------------+ //| CZoneManager.mqh | //| The central Hub for storing and managing all zones. | //| v7.0 - Final Stable Version | //+------------------------------------------------------------------+ #ifndef CZONEMANAGER_MQH #define CZONEMANAGER_MQH #include #include "SMC_DataStructures.mqh" #include "CEnumSharing.mqh" class CZoneManager { private: CArrayObj* m_swings_all; CArrayObj* m_swings_major; CArrayObj* m_swings_inducement; CArrayObj* m_zone_list; CArrayObj* m_zones_significant; CArrayObj* m_traded_levels; // The new central blacklist system public: CZoneManager() { m_swings_all = new CArrayObj(); m_swings_all.FreeMode(false); m_swings_major = new CArrayObj(); m_swings_major.FreeMode(false); m_swings_inducement = new CArrayObj(); m_swings_inducement.FreeMode(false); m_zone_list = new CArrayObj(); m_zone_list.FreeMode(true); m_zones_significant = new CArrayObj(); m_zones_significant.FreeMode(false); m_traded_levels = new CArrayObj(); m_traded_levels.FreeMode(true); } ~CZoneManager() { if(CheckPointer(m_swings_all)) { m_swings_all.FreeMode(true); delete m_swings_all; } if(CheckPointer(m_swings_major)) delete m_swings_major; if(CheckPointer(m_swings_inducement)) delete m_swings_inducement; if(CheckPointer(m_zone_list)) delete m_zone_list; if(CheckPointer(m_zones_significant)) delete m_zones_significant; if(CheckPointer(m_traded_levels)) delete m_traded_levels; } // --- Public Getters --- CArrayObj* GetAllSwings() { return m_swings_all; } CArrayObj* GetMajorSwings() { return m_swings_major; } CArrayObj* GetZoneList() { return m_zone_list; } CArrayObj* GetSignificantZones() { return m_zones_significant; } // --- Public Adders --- void AddSwing(SwingPoint* swing) { if(swing) m_swings_all.Add(swing); } void AddZone(CSignalZone* zone) { if(zone) m_zone_list.Add(zone); } // --- Core Management Functions --- void ClearAllSwingData() { if(m_swings_all == NULL) return; m_swings_all.FreeMode(true); m_swings_all.Clear(); m_swings_all.FreeMode(false); if(m_swings_major) m_swings_major.Clear(); if(m_swings_inducement) m_swings_inducement.Clear(); } // --- Centralized Trade Tracking Functions --- CTradedLevel* GetTradedLevelInfo(datetime time) { if(m_traded_levels == NULL) return NULL; for(int i=0; i < m_traded_levels.Total(); i++) { CTradedLevel *level = m_traded_levels.At(i); if(level != NULL && level.level_time == time) return level; } return NULL; } void IncrementTradeCountForLevel(datetime time) { if(m_traded_levels == NULL || time == 0) return; CTradedLevel *level_info = GetTradedLevelInfo(time); if(level_info != NULL) { level_info.trade_count++; } else { m_traded_levels.Add(new CTradedLevel(time)); } } void RepopulateFilteredSwingLists() { if(m_swings_major==NULL || m_swings_inducement==NULL || m_swings_all==NULL) return; m_swings_major.Clear(); m_swings_inducement.Clear(); for(int i = 0; i < m_swings_all.Total(); i++) { SwingPoint *sp = m_swings_all.At(i); if(sp == NULL || sp.status == STATUS_NOISE) continue; if(sp.status == STATUS_MAJOR) m_swings_major.Add(sp); if(sp.status == STATUS_INDUCEMENT) m_swings_inducement.Add(sp); } } void UpdateAllZoneStates(CDataContext &context) { if(m_zone_list == NULL) return; int last_closed_bar = 1; if(ArraySize(context.rates) <= last_closed_bar) return; for(int i = 0; i < m_zone_list.Total(); i++) { CSignalZone* zone = m_zone_list.At(i); // ข้ามโซนที่ Invalidate หรือถูกใช้เทรดไปแล้ว if(zone == NULL || zone.state == STATE_INVALIDATED || zone.trades_taken_count > 0) continue; // --- Mitigation Logic --- bool is_touched = (zone.direction == DIRECTION_BULLISH && context.rates[last_closed_bar].low <= zone.top) || (zone.direction == DIRECTION_BEARISH && context.rates[last_closed_bar].high >= zone.bottom); if(is_touched && zone.state == STATE_ACTIVE) { zone.state = STATE_MITIGATED; zone.mitigation_count++; } // --- State Transition Logic --- if(zone.state == STATE_FRESH) { zone.state = STATE_ACTIVE; } } } void CleanupOldData(int days_to_keep) { if(days_to_keep <= 0 || m_zone_list == NULL) return; datetime cutoff_time = TimeCurrent() - (days_to_keep * 86400); // วนลูปจากหลังมาหน้าเพื่อความปลอดภัยในการลบ for(int i = m_zone_list.Total() - 1; i >= 0; i--) { CSignalZone* zone = m_zone_list.At(i); if(zone != NULL) { // *** FIXED: ลบเฉพาะโซนที่เก่าเกินกำหนดเท่านั้น *** if(zone.time < cutoff_time) { // FreeMode(true) จะ delete object ให้เอง m_zone_list.Delete(i); } } } // ทำความสะอาดบัญชีดำที่เก่าเกินไปด้วย if(m_traded_levels != NULL) { for(int i = m_traded_levels.Total() - 1; i >= 0; i--) { CTradedLevel* level = m_traded_levels.At(i); if(level != NULL && level.level_time < cutoff_time) { m_traded_levels.Delete(i); } } } } }; #endif