303 lines
10 KiB
Plaintext
303 lines
10 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| StateManager.mqh |
|
|
//| Universal Buffer Reader EA v2.0 |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2025"
|
|
#property link ""
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| CStateManager - Manages persistent state using Global Variables |
|
|
//+------------------------------------------------------------------+
|
|
class CStateManager
|
|
{
|
|
private:
|
|
string m_symbol;
|
|
int m_magic_number;
|
|
string m_prefix;
|
|
|
|
string m_gv_accum_loss;
|
|
string m_gv_consec_loss;
|
|
|
|
// Logging
|
|
bool m_enable_debug;
|
|
|
|
public:
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor |
|
|
//+------------------------------------------------------------------+
|
|
CStateManager()
|
|
{
|
|
m_symbol = "";
|
|
m_magic_number = 0;
|
|
m_prefix = "UnivBufEA";
|
|
m_enable_debug = false;
|
|
|
|
m_gv_accum_loss = "";
|
|
m_gv_consec_loss = "";
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Destructor |
|
|
//+------------------------------------------------------------------+
|
|
~CStateManager()
|
|
{
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Set parameters |
|
|
//+------------------------------------------------------------------+
|
|
void SetParameters(string symbol, int magic_number, bool enable_debug = false)
|
|
{
|
|
// Validate parameters
|
|
if(symbol == "")
|
|
{
|
|
Print("[ERROR] Invalid symbol: empty string");
|
|
}
|
|
m_symbol = symbol;
|
|
|
|
if(magic_number <= 0)
|
|
{
|
|
Print("[ERROR] Invalid magic number: ", magic_number, ". Using default 24680");
|
|
m_magic_number = 24680;
|
|
}
|
|
else
|
|
{
|
|
m_magic_number = magic_number;
|
|
}
|
|
|
|
m_enable_debug = enable_debug;
|
|
|
|
// Build Global Variable names
|
|
m_gv_accum_loss = BuildGVName("_AccumLoss");
|
|
m_gv_consec_loss = BuildGVName("_ConsecLoss");
|
|
|
|
if(m_enable_debug)
|
|
{
|
|
Print("[StateManager] Parameters set:");
|
|
Print(" Symbol: ", m_symbol);
|
|
Print(" Magic number: ", m_magic_number);
|
|
Print(" GV Accum Loss: ", m_gv_accum_loss);
|
|
Print(" GV Consec Loss: ", m_gv_consec_loss);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Set debug mode |
|
|
//+------------------------------------------------------------------+
|
|
void SetDebugMode(bool enable_debug)
|
|
{
|
|
m_enable_debug = enable_debug;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Load state from Global Variables |
|
|
//+------------------------------------------------------------------+
|
|
bool LoadState(double &accumulated_loss, int &consecutive_losses)
|
|
{
|
|
if(m_enable_debug)
|
|
{
|
|
Print("[StateManager] Loading state...");
|
|
}
|
|
|
|
accumulated_loss = 0;
|
|
consecutive_losses = 0;
|
|
|
|
// Load accumulated loss
|
|
if(GlobalVariableCheck(m_gv_accum_loss))
|
|
{
|
|
accumulated_loss = GlobalVariableGet(m_gv_accum_loss);
|
|
|
|
// Validate accumulated loss
|
|
if(accumulated_loss < 0)
|
|
{
|
|
Print("[WARNING] Invalid accumulated loss found: ", accumulated_loss, ". Resetting to 0");
|
|
accumulated_loss = 0;
|
|
GlobalVariableSet(m_gv_accum_loss, 0);
|
|
}
|
|
|
|
Print("[StateManager] Loaded accumulated loss: ", DoubleToString(accumulated_loss, 2));
|
|
}
|
|
else
|
|
{
|
|
if(!GlobalVariableSet(m_gv_accum_loss, 0))
|
|
{
|
|
Print("[ERROR] Failed to initialize accumulated loss Global Variable");
|
|
return false;
|
|
}
|
|
Print("[StateManager] Initialized accumulated loss: 0");
|
|
}
|
|
|
|
// Load consecutive losses
|
|
if(GlobalVariableCheck(m_gv_consec_loss))
|
|
{
|
|
consecutive_losses = (int)GlobalVariableGet(m_gv_consec_loss);
|
|
|
|
// Validate consecutive losses
|
|
if(consecutive_losses < 0)
|
|
{
|
|
Print("[WARNING] Invalid consecutive losses found: ", consecutive_losses, ". Resetting to 0");
|
|
consecutive_losses = 0;
|
|
GlobalVariableSet(m_gv_consec_loss, 0);
|
|
}
|
|
|
|
Print("[StateManager] Loaded consecutive losses: ", consecutive_losses);
|
|
}
|
|
else
|
|
{
|
|
if(!GlobalVariableSet(m_gv_consec_loss, 0))
|
|
{
|
|
Print("[ERROR] Failed to initialize consecutive losses Global Variable");
|
|
return false;
|
|
}
|
|
Print("[StateManager] Initialized consecutive losses: 0");
|
|
}
|
|
|
|
if(m_enable_debug)
|
|
{
|
|
Print("[StateManager] State loaded successfully");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Save state to Global Variables |
|
|
//+------------------------------------------------------------------+
|
|
bool SaveState(double accumulated_loss, int consecutive_losses)
|
|
{
|
|
if(m_enable_debug)
|
|
{
|
|
Print("[StateManager] Saving state...");
|
|
Print(" Accumulated loss: ", DoubleToString(accumulated_loss, 2));
|
|
Print(" Consecutive losses: ", consecutive_losses);
|
|
}
|
|
|
|
// Validate inputs
|
|
if(accumulated_loss < 0)
|
|
{
|
|
Print("[ERROR] Invalid accumulated loss to save: ", accumulated_loss);
|
|
return false;
|
|
}
|
|
|
|
if(consecutive_losses < 0)
|
|
{
|
|
Print("[ERROR] Invalid consecutive losses to save: ", consecutive_losses);
|
|
return false;
|
|
}
|
|
|
|
bool result = true;
|
|
|
|
// Save accumulated loss
|
|
if(!GlobalVariableSet(m_gv_accum_loss, accumulated_loss))
|
|
{
|
|
int error = GetLastError();
|
|
Print("[ERROR] Failed to save accumulated loss. Error code: ", error);
|
|
result = false;
|
|
}
|
|
|
|
// Save consecutive losses
|
|
if(!GlobalVariableSet(m_gv_consec_loss, consecutive_losses))
|
|
{
|
|
int error = GetLastError();
|
|
Print("[ERROR] Failed to save consecutive losses. Error code: ", error);
|
|
result = false;
|
|
}
|
|
|
|
if(result && m_enable_debug)
|
|
{
|
|
Print("[StateManager] State saved successfully");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Clear state (for backtesting) |
|
|
//+------------------------------------------------------------------+
|
|
bool ClearState()
|
|
{
|
|
if(m_enable_debug)
|
|
{
|
|
Print("[StateManager] Clearing state...");
|
|
}
|
|
|
|
bool result = true;
|
|
|
|
// Delete accumulated loss
|
|
if(GlobalVariableCheck(m_gv_accum_loss))
|
|
{
|
|
if(!GlobalVariableDel(m_gv_accum_loss))
|
|
{
|
|
int error = GetLastError();
|
|
Print("[ERROR] Failed to delete accumulated loss. Error code: ", error);
|
|
result = false;
|
|
}
|
|
else
|
|
{
|
|
Print("[StateManager] Deleted accumulated loss Global Variable");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print("[StateManager] Accumulated loss Global Variable not found (already cleared)");
|
|
}
|
|
|
|
// Delete consecutive losses
|
|
if(GlobalVariableCheck(m_gv_consec_loss))
|
|
{
|
|
if(!GlobalVariableDel(m_gv_consec_loss))
|
|
{
|
|
int error = GetLastError();
|
|
Print("[ERROR] Failed to delete consecutive losses. Error code: ", error);
|
|
result = false;
|
|
}
|
|
else
|
|
{
|
|
Print("[StateManager] Deleted consecutive losses Global Variable");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print("[StateManager] Consecutive losses Global Variable not found (already cleared)");
|
|
}
|
|
|
|
if(result)
|
|
{
|
|
Print("[StateManager] State cleared successfully");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Get Global Variable names |
|
|
//+------------------------------------------------------------------+
|
|
void GetGVNames(string &accum_loss_name, string &consec_loss_name)
|
|
{
|
|
accum_loss_name = m_gv_accum_loss;
|
|
consec_loss_name = m_gv_consec_loss;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check if state exists |
|
|
//+------------------------------------------------------------------+
|
|
bool StateExists()
|
|
{
|
|
bool accum_exists = GlobalVariableCheck(m_gv_accum_loss);
|
|
bool consec_exists = GlobalVariableCheck(m_gv_consec_loss);
|
|
|
|
return (accum_exists || consec_exists);
|
|
}
|
|
|
|
private:
|
|
//+------------------------------------------------------------------+
|
|
//| Build Global Variable name |
|
|
//+------------------------------------------------------------------+
|
|
string BuildGVName(string suffix)
|
|
{
|
|
return m_prefix + "_" + m_symbol + "_" + IntegerToString(m_magic_number) + suffix;
|
|
}
|
|
};
|
|
//+------------------------------------------------------------------+ |