forked from Princeec13/mql5
308 lines
11 KiB
MQL5
308 lines
11 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|