mql5/Include/Experts/Risk/RiskIntegration.mqh
2025-08-16 12:30:04 -04:00

402 lines
13 KiB
MQL5

//+------------------------------------------------------------------+
//| RiskIntegration.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 all risk management components
#include "RiskParameters.mqh"
#include "RiskMetrics.mqh"
#include "PositionSizer.mqh"
#include "DrawdownManager.mqh"
#include "CorrelationMatrix.mqh"
//+------------------------------------------------------------------+
//| Risk Integration Class |
//+------------------------------------------------------------------+
class CRiskIntegration
{
private:
// Component instances
CRiskParameters* m_riskParams; // Risk parameters
CRiskMetrics* m_riskMetrics; // Risk metrics calculator
CPositionSizer* m_positionSizer; // Position sizing
CDrawdownManager* m_drawdownMgr; // Drawdown management
CCorrelationMatrix* m_corrMatrix; // Correlation analysis
// State
bool m_isInitialized; // Initialization flag
double m_accountEquity; // Current account equity
// Private methods
bool InitializeComponents();
void UpdateAccountInfo();
public:
// Constructor/Destructor
CRiskIntegration();
~CRiskIntegration();
// Initialization
bool Initialize();
void Deinitialize();
void Update();
// Risk assessment
bool CanOpenPosition(const string symbol, const ENUM_ORDER_TYPE type,
const double price, const double stopLoss,
const double takeProfit, double &suggestedSize);
// Position management
bool ValidatePositionSize(const string symbol, const double size);
bool UpdatePositionMetrics(const string symbol, const double size,
const double openPrice, const double currentPrice);
// Getters
bool IsInitialized() const { return m_isInitialized; }
double GetAccountEquity() const { return m_accountEquity; }
double GetMaxPositionSize() const;
// Component access
CRiskParameters* GetRiskParameters() { return m_riskParams; }
CRiskMetrics* GetRiskMetrics() { return m_riskMetrics; }
CPositionSizer* GetPositionSizer() { return m_positionSizer; }
CDrawdownManager* GetDrawdownManager() { return m_drawdownMgr; }
CCorrelationMatrix* GetCorrelationMatrix() { return m_corrMatrix; }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CRiskIntegration::CRiskIntegration() :
m_riskParams(NULL),
m_riskMetrics(NULL),
m_positionSizer(NULL),
m_drawdownMgr(NULL),
m_corrMatrix(NULL),
m_isInitialized(false),
m_accountEquity(0.0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CRiskIntegration::~CRiskIntegration()
{
Deinitialize();
}
//+------------------------------------------------------------------+
//| Initialize risk integration |
//+------------------------------------------------------------------+
bool CRiskIntegration::Initialize()
{
if (m_isInitialized)
return true;
// Create components
m_riskParams = new CRiskParameters();
if (m_riskParams == NULL || !m_riskParams.Initialize())
{
Print("Failed to initialize risk parameters");
return false;
}
m_riskMetrics = new CRiskMetrics();
if (m_riskMetrics == NULL || !m_riskMetrics.Initialize())
{
Print("Failed to initialize risk metrics");
return false;
}
m_positionSizer = new CPositionSizer();
if (m_positionSizer == NULL || !m_positionSizer.Initialize(m_riskParams, m_riskMetrics))
{
Print("Failed to initialize position sizer");
return false;
}
m_drawdownMgr = new CDrawdownManager();
if (m_drawdownMgr == NULL || !m_drawdownMgr.Initialize())
{
Print("Failed to initialize drawdown manager");
return false;
}
m_corrMatrix = new CCorrelationMatrix();
if (m_corrMatrix == NULL || !m_corrMatrix.Initialize())
{
Print("Failed to initialize correlation matrix");
return false;
}
// Update account information
UpdateAccountInfo();
m_isInitialized = true;
Print("Risk integration initialized successfully");
return true;
}
//+------------------------------------------------------------------+
//| Deinitialize risk integration |
//+------------------------------------------------------------------+
void CRiskIntegration::Deinitialize()
{
if (m_corrMatrix != NULL)
{
m_corrMatrix.Deinitialize();
delete m_corrMatrix;
m_corrMatrix = NULL;
}
if (m_drawdownMgr != NULL)
{
m_drawdownMgr.Deinitialize();
delete m_drawdownMgr;
m_drawdownMgr = NULL;
}
if (m_positionSizer != NULL)
{
m_positionSizer.Deinitialize();
delete m_positionSizer;
m_positionSizer = NULL;
}
if (m_riskMetrics != NULL)
{
m_riskMetrics.Deinitialize();
delete m_riskMetrics;
m_riskMetrics = NULL;
}
if (m_riskParams != NULL)
{
delete m_riskParams;
m_riskParams = NULL;
}
m_isInitialized = false;
}
//+------------------------------------------------------------------+
//| Update risk metrics and state |
//+------------------------------------------------------------------+
void CRiskIntegration::Update()
{
if (!m_isInitialized)
return;
// Update account information
UpdateAccountInfo();
// Update drawdown manager
if (m_drawdownMgr != NULL)
{
m_drawdownMgr.UpdateEquity(m_accountEquity);
}
// Update correlation matrix periodically
static datetime lastCorrelationUpdate = 0;
if (TimeCurrent() - lastCorrelationUpdate >= 3600) // Update hourly
{
if (m_corrMatrix != NULL)
{
m_corrMatrix.Update();
}
lastCorrelationUpdate = TimeCurrent();
}
// Update risk metrics
if (m_riskMetrics != NULL)
{
m_riskMetrics.Update();
}
}
//+------------------------------------------------------------------+
//| Check if a position can be opened with the given parameters |
//+------------------------------------------------------------------+
bool CRiskIntegration::CanOpenPosition(const string symbol, const ENUM_ORDER_TYPE type,
const double price, const double stopLoss,
const double takeProfit, double &suggestedSize)
{
if (!m_isInitialized || symbol == "")
return false;
// Check if we're in a drawdown that exceeds limits
if (m_drawdownMgr != NULL && m_riskParams != NULL)
{
if (m_drawdownMgr.IsDrawdownLimitReached(m_riskParams.GetMaxDrawdownPct()))
{
Print("Cannot open position: Maximum drawdown limit reached");
return false;
}
if (m_drawdownMgr.IsDailyLossLimitReached(m_riskParams.GetMaxDailyLossPct()))
{
Print("Cannot open position: Daily loss limit reached");
return false;
}
}
// Calculate stop loss in pips
double stopLossPips = 0.0;
if (stopLoss > 0.0)
{
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
if (point > 0.0 && tickSize > 0.0)
{
if (type == ORDER_TYPE_BUY)
stopLossPips = (price - stopLoss) / (point * 10.0);
else
stopLossPips = (stopLoss - price) / (point * 10.0);
stopLossPips = MathMax(1.0, stopLossPips); // Ensure at least 1 pip
}
}
// Get position size
double riskPercent = (m_riskParams != NULL) ? m_riskParams.GetRiskPerTrade() : 1.0;
double size = 0.0;
if (m_positionSizer != NULL)
{
if (!m_positionSizer.CalculateSize(symbol, stopLossPips, riskPercent, m_accountEquity, size))
{
Print("Failed to calculate position size");
return false;
}
}
// Check correlation with existing positions
if (m_corrMatrix != NULL && m_riskParams != NULL)
{
if (!m_corrMatrix.ValidateNewPosition(symbol, type, price, size))
{
Print("Cannot open position: Correlation limit exceeded");
return false;
}
}
// Check if size is within allowed limits
if (!ValidatePositionSize(symbol, size))
{
return false;
}
suggestedSize = size;
return true;
}
//+------------------------------------------------------------------+
//| Validate if position size is within allowed limits |
//+------------------------------------------------------------------+
bool CRiskIntegration::ValidatePositionSize(const string symbol, const double size)
{
if (!m_isInitialized || symbol == "" || size <= 0.0)
return false;
// Check minimum position size
double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
if (size < minLot)
{
PrintFormat("Position size (%.2f) is below minimum (%.2f)", size, minLot);
return false;
}
// Check maximum position size
double maxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
if (maxLot > 0.0 && size > maxLot)
{
PrintFormat("Position size (%.2f) exceeds maximum (%.2f)", size, maxLot);
return false;
}
// Check against risk parameters
if (m_riskParams != NULL)
{
double maxLotsPerTrade = m_riskParams.GetMaxLotsPerTrade();
if (maxLotsPerTrade > 0.0 && size > maxLotsPerTrade)
{
PrintFormat("Position size (%.2f) exceeds maximum per trade (%.2f)", size, maxLotsPerTrade);
return false;
}
double maxRiskPerTrade = m_riskParams.GetMaxRiskPerTrade();
if (maxRiskPerTrade > 0.0)
{
double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
if (tickValue > 0.0 && tickSize > 0.0 && point > 0.0)
{
double riskAmount = size * (tickValue / tickSize) * point * 10.0; // Risk per pip
double maxRiskAmount = m_accountEquity * (maxRiskPerTrade / 100.0);
if (riskAmount > maxRiskAmount)
{
PrintFormat("Position risk (%.2f) exceeds maximum risk per trade (%.2f)",
riskAmount, maxRiskAmount);
return false;
}
}
}
}
return true;
}
//+------------------------------------------------------------------+
//| Update position metrics |
//+------------------------------------------------------------------+
bool CRiskIntegration::UpdatePositionMetrics(const string symbol, const double size,
const double openPrice, const double currentPrice)
{
if (!m_isInitialized || symbol == "" || size <= 0.0 || openPrice <= 0.0)
return false;
// Update risk metrics with the new position
if (m_riskMetrics != NULL)
{
// This is a simplified example - in practice, you would update all relevant metrics
double pips = (currentPrice - openPrice) / (SymbolInfoDouble(symbol, SYMBOL_POINT) * 10.0);
m_riskMetrics.UpdateTradeMetrics(pips > 0, MathAbs(pips));
}
return true;
}
//+------------------------------------------------------------------+
//| Get maximum allowed position size based on risk parameters |
//+------------------------------------------------------------------
double CRiskIntegration::GetMaxPositionSize()
{
if (!m_isInitialized || m_riskParams == NULL)
return 0.0;
return m_riskParams.GetMaxLotsPerTrade();
}
//+------------------------------------------------------------------+
//| Update account information |
//+------------------------------------------------------------------+
void CRiskIntegration::UpdateAccountInfo()
{
m_accountEquity = AccountInfoDouble(ACCOUNT_EQUITY);
// Update risk metrics with new equity
if (m_riskMetrics != NULL)
{
m_riskMetrics.UpdateEquity(m_accountEquity);
}
}