402 lines
13 KiB
MQL5
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);
| |||
}
| |||
}
|