forked from Princeec13/mql5
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);
|
|
}
|
|
}
|