//+------------------------------------------------------------------+ //| MonteCarloSimulator.mqh | //| Copyright 2024, MT5 Sniper Strategy Team | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MT5 Sniper Strategy Team" #property link "https://www.mql5.com" #include "../Utils/Logger.mqh" #include "../Utils/CacheManager.mqh" //+------------------------------------------------------------------+ //| Monte Carlo Simulation Enums | //+------------------------------------------------------------------+ enum ENUM_SIMULATION_TYPE { SIMULATION_POSITION_SIZING, // Position sizing optimization SIMULATION_RISK_ASSESSMENT, // Risk assessment and validation SIMULATION_STRATEGY_PERFORMANCE, // Strategy performance analysis SIMULATION_DRAWDOWN_ANALYSIS, // Drawdown and recovery analysis SIMULATION_PORTFOLIO_OPTIMIZATION // Portfolio optimization }; enum ENUM_DISTRIBUTION_TYPE { DISTRIBUTION_NORMAL, // Normal distribution DISTRIBUTION_LOG_NORMAL, // Log-normal distribution DISTRIBUTION_UNIFORM, // Uniform distribution DISTRIBUTION_EXPONENTIAL, // Exponential distribution DISTRIBUTION_HISTORICAL // Historical data distribution }; enum ENUM_RISK_METRIC { RISK_VAR_95, // Value at Risk 95% RISK_VAR_99, // Value at Risk 99% RISK_CVAR_95, // Conditional VaR 95% RISK_CVAR_99, // Conditional VaR 99% RISK_MAX_DRAWDOWN, // Maximum drawdown RISK_SHARPE_RATIO, // Sharpe ratio RISK_SORTINO_RATIO, // Sortino ratio RISK_CALMAR_RATIO // Calmar ratio }; //+------------------------------------------------------------------+ //| Simulation Parameters Structure | //+------------------------------------------------------------------+ struct SSimulationParams { ENUM_SIMULATION_TYPE simulationType; int iterations; // Number of Monte Carlo iterations int timeHorizon; // Time horizon in days double initialCapital; // Initial capital double riskFreeRate; // Risk-free rate (annual) bool useHistoricalData; // Use historical data for distributions int historicalPeriod; // Historical data period (days) double confidenceLevel; // Confidence level (0.0-1.0) bool enableCorrelation; // Enable correlation modeling string outputPath; // Output path for results }; //+------------------------------------------------------------------+ //| Market Scenario Structure | //+------------------------------------------------------------------+ struct SMarketScenario { double priceReturn; // Price return double volatility; // Volatility double correlation; // Correlation with other assets double volume; // Trading volume double spread; // Bid-ask spread double slippage; // Slippage factor bool isNewsEvent; // News event flag double newsImpact; // News impact factor datetime timestamp; // Scenario timestamp }; //+------------------------------------------------------------------+ //| Trade Simulation Structure | //+------------------------------------------------------------------+ struct STradeSimulation { double entryPrice; // Entry price double exitPrice; // Exit price double positionSize; // Position size double pnl; // Profit/Loss double commission; // Commission cost double slippage; // Slippage cost double holdingPeriod; // Holding period (hours) bool isWinner; // Is winning trade double riskReward; // Risk-reward ratio double maxFavorable; // Maximum favorable excursion double maxAdverse; // Maximum adverse excursion }; //+------------------------------------------------------------------+ //| Simulation Results Structure | //+------------------------------------------------------------------+ struct SSimulationResults { // Performance metrics double totalReturn; // Total return double annualizedReturn; // Annualized return double volatility; // Portfolio volatility double sharpeRatio; // Sharpe ratio double sortinoRatio; // Sortino ratio double calmarRatio; // Calmar ratio // Risk metrics double var95; // Value at Risk 95% double var99; // Value at Risk 99% double cvar95; // Conditional VaR 95% double cvar99; // Conditional VaR 99% double maxDrawdown; // Maximum drawdown double avgDrawdown; // Average drawdown double drawdownDuration; // Average drawdown duration // Trade statistics int totalTrades; // Total number of trades int winningTrades; // Number of winning trades double winRate; // Win rate percentage double avgWin; // Average winning trade double avgLoss; // Average losing trade double profitFactor; // Profit factor double expectancy; // Mathematical expectancy // Distribution statistics double meanReturn; // Mean return double medianReturn; // Median return double stdDeviation; // Standard deviation double skewness; // Skewness double kurtosis; // Kurtosis // Confidence intervals double ci95Lower; // 95% CI lower bound double ci95Upper; // 95% CI upper bound double ci99Lower; // 99% CI lower bound double ci99Upper; // 99% CI upper bound }; //+------------------------------------------------------------------+ //| Portfolio Simulation Structure | //+------------------------------------------------------------------+ struct SPortfolioSimulation { double portfolioValue[]; // Portfolio value over time double returns[]; // Portfolio returns double drawdowns[]; // Drawdown series double positions[]; // Position sizes over time double riskMetrics[]; // Risk metrics over time int tradeCount[]; // Trade count over time datetime timestamps[]; // Timestamps }; //+------------------------------------------------------------------+ //| Monte Carlo Simulator Class | //+------------------------------------------------------------------+ class CMonteCarloSimulator { private: // Core properties CLogger* m_logger; CCacheManager* m_cacheManager; bool m_isInitialized; // Simulation configuration SSimulationParams m_params; string m_symbol; ENUM_TIMEFRAMES m_timeframe; // Random number generation int m_randomSeed; double m_lastNormal; bool m_hasSpareNormal; // Historical data double m_historicalReturns[]; double m_historicalVolatility[]; double m_correlationMatrix[][]; // Simulation state SMarketScenario m_scenarios[]; STradeSimulation m_trades[]; SPortfolioSimulation m_portfolio; SSimulationResults m_results; // Performance tracking datetime m_simulationStart; datetime m_simulationEnd; double m_simulationTime; // Helper methods - Random number generation double GenerateNormal(double mean = 0.0, double stdDev = 1.0); double GenerateUniform(double min = 0.0, double max = 1.0); double GenerateExponential(double lambda = 1.0); double GenerateLogNormal(double mu = 0.0, double sigma = 1.0); // Market scenario generation void GenerateMarketScenarios(); SMarketScenario GenerateScenario(int step); void ApplyCorrelation(SMarketScenario &scenario); void AddNewsEvents(SMarketScenario &scenario); // Trade simulation void SimulateTrades(); STradeSimulation SimulateTrade(const SMarketScenario &scenario); double CalculateOptimalPositionSize(const SMarketScenario &scenario); double CalculateSlippage(double positionSize, double volume); // Statistical analysis void CalculateStatistics(); void CalculateRiskMetrics(); void CalculateConfidenceIntervals(); double CalculateVaR(double confidenceLevel); double CalculateCVaR(double confidenceLevel); // Historical data analysis bool LoadHistoricalData(); void CalculateCorrelationMatrix(); void FitDistributions(); public: CMonteCarloSimulator(); ~CMonteCarloSimulator(); // Initialization bool Initialize(string symbol, ENUM_TIMEFRAMES timeframe, CLogger* logger, CCacheManager* cacheManager = NULL); void SetSimulationParameters(const SSimulationParams ¶ms); void SetRandomSeed(int seed); // Simulation execution bool RunSimulation(); bool RunPositionSizingSimulation(double riskPercent, double stopLoss); bool RunRiskAssessmentSimulation(double positionSize); bool RunStrategyPerformanceSimulation(); bool RunDrawdownAnalysis(); bool RunPortfolioOptimization(); // Results and analysis SSimulationResults GetResults(); string GetResultsReport(); bool ExportResults(string filename); // Risk assessment double GetOptimalPositionSize(double riskTolerance); double GetRiskMetric(ENUM_RISK_METRIC metric); double GetProbabilityOfLoss(double threshold); double GetExpectedReturn(int timeHorizon); // Scenario analysis bool RunStressTest(double stressLevel); bool RunSensitivityAnalysis(string parameter, double minValue, double maxValue, int steps); SSimulationResults GetWorstCaseScenario(); SSimulationResults GetBestCaseScenario(); // Validation and backtesting bool ValidateStrategy(double minSharpe, double maxDrawdown); bool BacktestWithMonteCarlo(datetime startDate, datetime endDate); double CalculateStrategyRobustness(); // Diagnostics and reporting string GetDiagnosticsReport(); bool ValidateSimulation(); void PlotResults(string chartName = ""); // Advanced features bool EnableMultiAssetSimulation(string symbols[]); void SetCustomDistribution(double data[]); bool OptimizeParameters(); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CMonteCarloSimulator::CMonteCarloSimulator() { m_logger = NULL; m_cacheManager = NULL; m_isInitialized = false; m_randomSeed = (int)TimeCurrent(); m_lastNormal = 0.0; m_hasSpareNormal = false; m_simulationTime = 0.0; // Default simulation parameters m_params.simulationType = SIMULATION_RISK_ASSESSMENT; m_params.iterations = 10000; m_params.timeHorizon = 252; // 1 year m_params.initialCapital = 10000.0; m_params.riskFreeRate = 0.02; // 2% annual m_params.useHistoricalData = true; m_params.historicalPeriod = 1000; m_params.confidenceLevel = 0.95; m_params.enableCorrelation = true; m_params.outputPath = ""; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CMonteCarloSimulator::~CMonteCarloSimulator() { if(m_logger != NULL) { m_logger->LogInfo("Monte Carlo Simulator destroyed"); } } //+------------------------------------------------------------------+ //| Initialize simulator | //+------------------------------------------------------------------+ bool CMonteCarloSimulator::Initialize(string symbol, ENUM_TIMEFRAMES timeframe, CLogger* logger, CCacheManager* cacheManager = NULL) { m_symbol = symbol; m_timeframe = timeframe; m_logger = logger; m_cacheManager = cacheManager; // Load historical data if(!LoadHistoricalData()) { if(m_logger != NULL) { m_logger->LogError("Failed to load historical data for Monte Carlo simulation"); } return false; } // Calculate correlation matrix if enabled if(m_params.enableCorrelation) { CalculateCorrelationMatrix(); } // Fit distributions to historical data FitDistributions(); m_isInitialized = true; if(m_logger != NULL) { m_logger->LogInfo("Monte Carlo Simulator initialized for " + symbol); } return true; } //+------------------------------------------------------------------+ //| Run complete simulation | //+------------------------------------------------------------------+ bool CMonteCarloSimulator::RunSimulation() { if(!m_isInitialized) { if(m_logger != NULL) { m_logger->LogError("Monte Carlo Simulator not initialized"); } return false; } m_simulationStart = GetMicrosecondCount(); // Generate market scenarios GenerateMarketScenarios(); // Simulate trades SimulateTrades(); // Calculate statistics and risk metrics CalculateStatistics(); CalculateRiskMetrics(); CalculateConfidenceIntervals(); m_simulationEnd = GetMicrosecondCount(); m_simulationTime = (m_simulationEnd - m_simulationStart) / 1000.0; // Convert to milliseconds if(m_logger != NULL) { m_logger->LogInfo(StringFormat("Monte Carlo simulation completed in %.2f ms with %d iterations", m_simulationTime, m_params.iterations)); } return true; } //+------------------------------------------------------------------+ //| Generate normal random number (Box-Muller transform) | //+------------------------------------------------------------------+ double CMonteCarloSimulator::GenerateNormal(double mean = 0.0, double stdDev = 1.0) { if(m_hasSpareNormal) { m_hasSpareNormal = false; return m_lastNormal * stdDev + mean; } m_hasSpareNormal = true; double u = GenerateUniform(); double v = GenerateUniform(); double mag = stdDev * MathSqrt(-2.0 * MathLog(u)); m_lastNormal = mag * MathCos(2.0 * M_PI * v); return mag * MathSin(2.0 * M_PI * v) + mean; } //+------------------------------------------------------------------+ //| Get simulation results | //+------------------------------------------------------------------+ SSimulationResults CMonteCarloSimulator::GetResults() { return m_results; } //+------------------------------------------------------------------+ //| Get results report | //+------------------------------------------------------------------+ string CMonteCarloSimulator::GetResultsReport() { string report = "=== Monte Carlo Simulation Results ===\n"; report += StringFormat("Symbol: %s, Timeframe: %s\n", m_symbol, EnumToString(m_timeframe)); report += StringFormat("Iterations: %d, Time Horizon: %d days\n", m_params.iterations, m_params.timeHorizon); report += StringFormat("Simulation Time: %.2f ms\n\n", m_simulationTime); report += "=== Performance Metrics ===\n"; report += StringFormat("Total Return: %.2f%%\n", m_results.totalReturn * 100); report += StringFormat("Annualized Return: %.2f%%\n", m_results.annualizedReturn * 100); report += StringFormat("Volatility: %.2f%%\n", m_results.volatility * 100); report += StringFormat("Sharpe Ratio: %.3f\n", m_results.sharpeRatio); report += StringFormat("Sortino Ratio: %.3f\n", m_results.sortinoRatio); report += StringFormat("Calmar Ratio: %.3f\n\n", m_results.calmarRatio); report += "=== Risk Metrics ===\n"; report += StringFormat("VaR 95%%: %.2f%%\n", m_results.var95 * 100); report += StringFormat("VaR 99%%: %.2f%%\n", m_results.var99 * 100); report += StringFormat("CVaR 95%%: %.2f%%\n", m_results.cvar95 * 100); report += StringFormat("CVaR 99%%: %.2f%%\n", m_results.cvar99 * 100); report += StringFormat("Max Drawdown: %.2f%%\n", m_results.maxDrawdown * 100); report += StringFormat("Avg Drawdown: %.2f%%\n\n", m_results.avgDrawdown * 100); report += "=== Trade Statistics ===\n"; report += StringFormat("Total Trades: %d\n", m_results.totalTrades); report += StringFormat("Win Rate: %.2f%%\n", m_results.winRate * 100); report += StringFormat("Profit Factor: %.3f\n", m_results.profitFactor); report += StringFormat("Expectancy: %.2f\n", m_results.expectancy); return report; } //+------------------------------------------------------------------+ //| Get optimal position size | //+------------------------------------------------------------------+ double CMonteCarloSimulator::GetOptimalPositionSize(double riskTolerance) { if(!m_isInitialized) return 0.0; // Run position sizing simulation with different sizes double bestSize = 0.0; double bestSharpe = -999.0; for(double size = 0.01; size <= 0.10; size += 0.01) { SSimulationParams tempParams = m_params; tempParams.simulationType = SIMULATION_POSITION_SIZING; SetSimulationParameters(tempParams); if(RunPositionSizingSimulation(size, riskTolerance)) { if(m_results.sharpeRatio > bestSharpe && m_results.maxDrawdown <= riskTolerance) { bestSharpe = m_results.sharpeRatio; bestSize = size; } } } return bestSize; }