//+------------------------------------------------------------------+ //| RiskManager_Advanced.mqh | //| Copyright 2023, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property strict // Include the base RiskManager class #include "RiskManager.mqh" //+------------------------------------------------------------------+ //| Calculate correlation-adjusted position size | //+------------------------------------------------------------------+ double CRiskManager::CalculateCorrelationAdjustedSize(double baseLots, string symbol1, string symbol2, ENUM_TIMEFRAMES timeframe, int period) { if(baseLots <= 0 || symbol1 == "" || symbol2 == "" || period <= 0) return baseLots; // Get correlation between the two symbols double correlation = CalculateCorrelationIndex(symbol1, symbol2, timeframe, period); // Convert correlation from -100..100 to 0..1 range double correlationFactor = (correlation + 100.0) / 200.0; // Adjust position size based on correlation // Higher correlation = smaller position size to reduce risk double adjustedLots = baseLots * (1.0 - (correlationFactor * 0.5)); // Ensure we don't go below minimum lot size double minLot = SymbolInfoDouble(symbol1, SYMBOL_VOLUME_MIN); return MathMax(adjustedLots, minLot); } //+------------------------------------------------------------------+ //| Calculate regime-adjusted position size | //+------------------------------------------------------------------+ double CRiskManager::CalculateRegimeAdjustedSize(double baseLots, ENUM_MARKET_REGIME regime) { if(baseLots <= 0) return 0.0; double adjustedLots = baseLots; switch(regime) { case REGIME_TRENDING_UP: case REGIME_TRENDING_DOWN: // Increase position size in strong trends adjustedLots *= 1.2; break; case REGIME_RANGING: // Reduce position size in ranging markets adjustedLots *= 0.7; break; case REGIME_VOLATILE: // Reduce position size in high volatility adjustedLots *= 0.6; break; case REGIME_LOW_VOLATILITY: // Slightly reduce position size in low volatility adjustedLots *= 0.9; break; default: break; } // Ensure we don't exceed maximum position size double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); return MathMin(adjustedLots, maxLot); } //+------------------------------------------------------------------+ //| Calculate ML-adjusted position size | //+------------------------------------------------------------------+ double CRiskManager::CalculateMLAdjustedSize(double baseLots, double mlConfidence) { if(baseLots <= 0) return 0.0; // Ensure confidence is in valid range (0-1) mlConfidence = MathMax(0.0, MathMin(1.0, mlConfidence)); // Calculate position size adjustment based on confidence // Higher confidence = larger position size (up to 2x) // Lower confidence = smaller position size (down to 0.1x) double adjustmentFactor = 0.1 + (mlConfidence * 1.9); // Apply adjustment double adjustedLots = baseLots * adjustmentFactor; // Ensure we don't exceed maximum position size double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); return MathMin(adjustedLots, maxLot); } //+------------------------------------------------------------------+ //| Calculate correlation index between two symbols | //+------------------------------------------------------------------+ double CRiskManager::CalculateCorrelationIndex(string symbol1, string symbol2, ENUM_TIMEFRAMES timeframe, int period) { if(period <= 0) return 0.0; // Get close prices for both symbols double closes1[], closes2[]; ArraySetAsSeries(closes1, true); ArraySetAsSeries(closes2, true); int copied1 = CopyClose(symbol1, timeframe, 0, period, closes1); int copied2 = CopyClose(symbol2, timeframe, 0, period, closes2); if(copied1 != period || copied2 != period || copied1 != copied2) return 0.0; // Calculate correlation coefficient (Pearson's r) double sum1 = 0, sum2 = 0, sum1Sq = 0, sum2Sq = 0, sumProd = 0; for(int i = 0; i < period; i++) { sum1 += closes1[i]; sum2 += closes2[i]; sum1Sq += closes1[i] * closes1[i]; sum2Sq += closes2[i] * closes2[i]; sumProd += closes1[i] * closes2[i]; } double numerator = sumProd - (sum1 * sum2 / period); double denominator = MathSqrt((sum1Sq - (sum1 * sum1 / period)) * (sum2Sq - (sum2 * sum2 / period))); if(denominator == 0) return 0.0; double correlation = numerator / denominator; // Convert to -100..100 range return correlation * 100.0; } //+------------------------------------------------------------------+ //| Calculate volatility index | //+------------------------------------------------------------------+ double CRiskManager::CalculateVolatilityIndex(int period = 14) { if(m_symbol == NULL || period <= 0) return 0.0; // Calculate ATR as percentage of price double atr = m_atr != NULL ? m_atr.Main(0) : 0; double price = m_symbol.Ask(); if(price <= 0) return 0.0; double atrPercent = (atr / price) * 100.0; // Convert to 0-100 scale (adjust these thresholds based on your needs) const double MIN_ATR = 0.2; // 0.2% const double MAX_ATR = 2.0; // 2.0% double volatilityIndex = 100.0 * (atrPercent - MIN_ATR) / (MAX_ATR - MIN_ATR); // Ensure within bounds return MathMax(0.0, MathMin(100.0, volatilityIndex)); } //+------------------------------------------------------------------+ //| Calculate trend strength | //+------------------------------------------------------------------+ double CRiskManager::CalculateTrendStrength(int period = 20) { if(m_symbol == NULL || period <= 0) return 0.0; // Simple implementation using ADX int adxHandle = iADX(m_symbol.Name(), PERIOD_CURRENT, period); if(adxHandle == INVALID_HANDLE) return 0.0; double adx[]; ArraySetAsSeries(adx, true); if(CopyBuffer(adxHandle, 0, 0, 1, adx) != 1) { IndicatorRelease(adxHandle); return 0.0; } IndicatorRelease(adxHandle); // ADX is already on a 0-100 scale return adx[0]; } //+------------------------------------------------------------------+ //| Save risk manager state to file | //+------------------------------------------------------------------+ void CRiskManager::SaveState() { int handle = FileOpen("RiskManagerState.dat", FILE_WRITE|FILE_BIN); if(handle != INVALID_HANDLE) { // Save basic risk parameters FileWriteDouble(handle, m_riskPerTrade); FileWriteDouble(handle, m_maxLeverage); FileWriteInteger(handle, m_maxOpenTrades); FileWriteDouble(handle, m_dailyLossLimit); FileWriteDouble(handle, m_maxPortfolioRisk); FileWriteDouble(handle, m_maxDrawdown); // Save advanced risk metrics FileWriteDouble(handle, m_riskOfRuin); FileWriteDouble(handle, m_sharpeRatio); FileWriteDouble(handle, m_sortinoRatio); FileWriteDouble(handle, m_valueAtRisk); FileWriteDouble(handle, m_expectedShortfall); FileWriteDouble(handle, m_maxAdverseExcursion); FileWriteDouble(handle, m_winLossRatio); FileWriteDouble(handle, m_profitFactor); FileWriteDouble(handle, m_recoveryFactor); FileWriteInteger(handle, m_consecutiveLosses); FileWriteInteger(handle, m_consecutiveWins); FileWriteDouble(handle, m_avgWin); FileWriteDouble(handle, m_avgLoss); FileWriteInteger(handle, m_totalTrades); FileWriteDouble(handle, m_winRate); // Save market regime info FileWriteInteger(handle, (int)m_marketRegime); FileWriteDouble(handle, m_volatilityIndex); FileWriteDouble(handle, m_trendStrength); FileWriteDouble(handle, m_correlationIndex); FileClose(handle); } } //+------------------------------------------------------------------+ //| Load risk manager state from file | //+------------------------------------------------------------------+ bool CRiskManager::LoadState() { int handle = FileOpen("RiskManagerState.dat", FILE_READ|FILE_BIN); if(handle != INVALID_HANDLE) { // Load basic risk parameters m_riskPerTrade = FileReadDouble(handle); m_maxLeverage = FileReadDouble(handle); m_maxOpenTrades = (int)FileReadInteger(handle); m_dailyLossLimit = FileReadDouble(handle); m_maxPortfolioRisk = FileReadDouble(handle); m_maxDrawdown = FileReadDouble(handle); // Load advanced risk metrics m_riskOfRuin = FileReadDouble(handle); m_sharpeRatio = FileReadDouble(handle); m_sortinoRatio = FileReadDouble(handle); m_valueAtRisk = FileReadDouble(handle); m_expectedShortfall = FileReadDouble(handle); m_maxAdverseExcursion = FileReadDouble(handle); m_winLossRatio = FileReadDouble(handle); m_profitFactor = FileReadDouble(handle); m_recoveryFactor = FileReadDouble(handle); m_consecutiveLosses = (int)FileReadInteger(handle); m_consecutiveWins = (int)FileReadInteger(handle); m_avgWin = FileReadDouble(handle); m_avgLoss = FileReadDouble(handle); m_totalTrades = (int)FileReadInteger(handle); m_winRate = FileReadDouble(handle); // Load market regime info m_marketRegime = (ENUM_MARKET_REGIME)FileReadInteger(handle); m_volatilityIndex = FileReadDouble(handle); m_trendStrength = FileReadDouble(handle); m_correlationIndex = FileReadDouble(handle); FileClose(handle); return true; } return false; } //+------------------------------------------------------------------+ //| Trigger recovery mode | //+------------------------------------------------------------------+ void CRiskManager::TriggerRecovery() { // Set risk state to recovery m_riskState = RISK_STATE_RECOVERY; // Log the recovery trigger Print("RiskManager: Recovery mode triggered. Risk state set to RECOVERY."); // Implement any additional recovery logic here // For example, you might want to close some positions, reduce position sizes, etc. // Save the current state SaveState(); } //+------------------------------------------------------------------+