277 строки
8,4 КиБ
MQL5
277 строки
8,4 КиБ
MQL5
//+------------------------------------------------------------------+
| |||
//| EAState.mqh |
| |||
//| Copyright 2025, Your Company Name |
| |||
//| https://www.yoursite.com |
| |||
//+------------------------------------------------------------------+
| |||
#property copyright "Copyright 2025, Your Company Name"
| |||
#property link "https://www.yoursite.com"
| |||
#property version "1.00"
| |||
#property strict
| |||
| |||
#include "EALogger.mqh"
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Market data state |
| |||
//+------------------------------------------------------------------+
| |||
struct SMarketData
| |||
{
| |||
MqlTick lastTick; // Last tick data
| |||
datetime lastUpdate; // Last update time
| |||
double bid, ask; // Current prices
| |||
double spread; // Current spread
| |||
| |||
// Initialize structure
| |||
void Init()
| |||
{
| |||
ZeroMemory(lastTick);
| |||
lastUpdate = 0;
| |||
bid = ask = spread = 0.0;
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Trade state |
| |||
//+------------------------------------------------------------------+
| |||
struct STradeState
| |||
{
| |||
int totalPositions; // Total open positions
| |||
double totalProfit; // Total profit/loss
| |||
double maxDrawdown; // Maximum drawdown
| |||
datetime lastTradeTime; // Time of last trade
| |||
| |||
// Initialize structure
| |||
void Init()
| |||
{
| |||
totalPositions = 0;
| |||
totalProfit = 0.0;
| |||
maxDrawdown = 0.0;
| |||
lastTradeTime = 0;
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| EA State Manager |
| |||
//+------------------------------------------------------------------+
| |||
class CEAState
| |||
{
| |||
private:
| |||
CEALogger* m_logger; // Logger instance
| |||
SMarketData m_marketData; // Market data state
| |||
STradeState m_tradeState; // Trade state
| |||
| |||
// Indicators
| |||
int m_maHandle; // Moving average handle
| |||
double m_maBuffer[]; // MA buffer
| |||
| |||
// Locks
| |||
bool m_isUpdating; // Update flag
| |||
| |||
// Internal methods
| |||
void UpdateIndicators();
| |||
| |||
public:
| |||
CEAState() : m_logger(NULL), m_maHandle(INVALID_HANDLE), m_isUpdating(false)
| |||
{
| |||
m_marketData.Init();
| |||
m_tradeState.Init();
| |||
}
| |||
| |||
~CEAState() { Deinitialize(); }
| |||
| |||
// Initialization
| |||
bool Initialize(CEALogger* logger);
| |||
void Deinitialize();
| |||
| |||
// State updates
| |||
void UpdateMarketData(const string symbol, ENUM_TIMEFRAMES timeframe);
| |||
void UpdateLastTick(const CTickEvent* tick);
| |||
void UpdateTradeState();
| |||
| |||
// Getters
| |||
const SMarketData& GetMarketData() const { return m_marketData; }
| |||
const STradeState& GetTradeState() const { return m_tradeState; }
| |||
| |||
// Indicator access
| |||
double GetMA(int shift = 0) const;
| |||
| |||
// State validation
| |||
bool IsMarketOpen() const;
| |||
bool IsTradingAllowed() const;
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Initialize state manager |
| |||
//+------------------------------------------------------------------+
| |||
bool CEAState::Initialize(CEALogger* logger)
| |||
{
| |||
if (logger == NULL)
| |||
return false;
| |||
| |||
m_logger = logger;
| |||
| |||
// Initialize indicators
| |||
m_maHandle = iMA(NULL, 0, 14, 0, MODE_SMA, PRICE_CLOSE);
| |||
if (m_maHandle == INVALID_HANDLE)
| |||
{
| |||
m_logger.LogError("Failed to initialize MA indicator");
| |||
return false;
| |||
}
| |||
| |||
// Set indicator buffers
| |||
ArraySetAsSeries(m_maBuffer, true);
| |||
| |||
m_logger.LogInfo("State manager initialized");
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Deinitialize state manager |
| |||
//+------------------------------------------------------------------+
| |||
void CEAState::Deinitialize()
| |||
{
| |||
// Release indicators
| |||
if (m_maHandle != INVALID_HANDLE)
| |||
{
| |||
IndicatorRelease(m_maHandle);
| |||
m_maHandle = INVALID_HANDLE;
| |||
}
| |||
| |||
// Clear buffers
| |||
ArrayFree(m_maBuffer);
| |||
| |||
m_logger = NULL;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Update market data |
| |||
//+------------------------------------------------------------------+
| |||
void CEAState::UpdateMarketData(const string symbol, ENUM_TIMEFRAMES timeframe)
| |||
{
| |||
if (m_isUpdating)
| |||
return;
| |||
| |||
m_isUpdating = true;
| |||
| |||
// Update tick data
| |||
MqlTick lastTick;
| |||
if (SymbolInfoTick(symbol, lastTick))
| |||
{
| |||
m_marketData.lastTick = lastTick;
| |||
m_marketData.bid = lastTick.bid;
| |||
m_marketData.ask = lastTick.ask;
| |||
m_marketData.spread = lastTick.ask - lastTick.bid;
| |||
m_marketData.lastUpdate = TimeCurrent();
| |||
}
| |||
| |||
// Update indicators
| |||
UpdateIndicators();
| |||
| |||
m_isUpdating = false;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Update last tick |
| |||
//+------------------------------------------------------------------+
| |||
void CEAState::UpdateLastTick(const CTickEvent* tick)
| |||
{
| |||
if (tick == NULL)
| |||
return;
| |||
| |||
// Update tick data from event
| |||
// Implementation depends on CTickEvent structure
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Update trade state |
| |||
//+------------------------------------------------------------------+
| |||
void CEAState::UpdateTradeState()
| |||
{
| |||
// Update positions count
| |||
m_tradeState.totalPositions = PositionsTotal();
| |||
| |||
// Update total profit
| |||
double totalProfit = 0;
| |||
for (int i = 0; i < m_tradeState.totalPositions; i++)
| |||
{
| |||
if (m_position.SelectByIndex(i))
| |||
totalProfit += m_position.Profit() + m_position.Swap() + m_position.Commission();
| |||
}
| |||
m_tradeState.totalProfit = totalProfit;
| |||
| |||
// Update max drawdown
| |||
if (totalProfit < m_tradeState.maxDrawdown)
| |||
m_tradeState.maxDrawdown = totalProfit;
| |||
| |||
// Update last trade time
| |||
if (m_tradeState.totalPositions > 0)
| |||
m_tradeState.lastTradeTime = TimeCurrent();
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Update indicators |
| |||
//+------------------------------------------------------------------+
| |||
void CEAState::UpdateIndicators()
| |||
{
| |||
if (m_maHandle == INVALID_HANDLE)
| |||
return;
| |||
| |||
// Copy MA values
| |||
if (CopyBuffer(m_maHandle, 0, 0, 1, m_maBuffer) != 1)
| |||
{
| |||
if (m_logger != NULL)
| |||
m_logger.LogError("Failed to copy MA buffer");
| |||
return;
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Get moving average value |
| |||
//+------------------------------------------------------------------+
| |||
double CEAState::GetMA(int shift = 0) const
| |||
{
| |||
if (shift < 0 || shift >= ArraySize(m_maBuffer))
| |||
return 0.0;
| |||
| |||
return m_maBuffer[shift];
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Check if market is open |
| |||
//+------------------------------------------------------------------+
| |||
bool CEAState::IsMarketOpen() const
| |||
{
| |||
// Check if current time is within trading hours
| |||
MqlDateTime dt;
| |||
TimeToStruct(TimeCurrent(), dt);
| |||
| |||
// Example: Check if it's a weekday and within trading hours
| |||
if (dt.day_of_week == 0 || dt.day_of_week == 6) // Weekend
| |||
return false;
| |||
| |||
// Example: Check trading hours (9:30 AM - 4:00 PM)
| |||
int currentMinute = dt.hour * 60 + dt.min;
| |||
if (currentMinute < 570 || currentMinute >= 960) // Before 9:30 AM or after 4:00 PM
| |||
return false;
| |||
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Check if trading is allowed |
| |||
//+------------------------------------------------------------------+
| |||
bool CEAState::IsTradingAllowed() const
| |||
{
| |||
// Check if market is open
| |||
if (!IsMarketOpen())
| |||
return false;
| |||
| |||
// Check if max positions reached
| |||
if (m_tradeState.totalPositions >= 10) // Example limit
| |||
return false;
| |||
| |||
// Check if max drawdown reached
| |||
if (m_tradeState.maxDrawdown <= -1000.0) // Example limit
| |||
return false;
| |||
| |||
return true;
| |||
}
|