EA_SMC_Mql5/Include/CZoneManager.mqh
2025-07-03 23:38:05 +07:00

155 lines
No EOL
12 KiB
MQL5

//+------------------------------------------------------------------+
//| CZoneManager.mqh |
//| The central Hub for storing and managing all zones. |
//| v7.0 - Final Stable Version |
//+------------------------------------------------------------------+
#ifndef CZONEMANAGER_MQH
#define CZONEMANAGER_MQH
#include <Arrays/ArrayObj.mqh>
#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