forked from ntsinh90/EA_SMC_Mql5
155 lines
No EOL
12 KiB
MQL5
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 |