//+------------------------------------------------------------------+ //| RiskManager.mqh | //| Copyright 2025, EscapeEA | //| https://www.escapeea.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, EscapeEA" #property link "https://www.escapeea.com" #property version "2.20" // Version bump for major enhancements #property strict // Standard Library Includes #include #include #include #include #include #include #include #include #include #include #include // Forward declarations class CSecurityManager; // Risk error codes enum ENUM_RISK_ERROR_CODES { RISK_ERROR_NONE = 0, // No error RISK_ERROR_INVALID_STATE = 1000, // Invalid object state RISK_ERROR_MEMORY = 1001, // Memory allocation failure RISK_ERROR_INVALID_PARAM = 1002, // Invalid parameter RISK_ERROR_IO = 1003, // I/O operation failed RISK_ERROR_RATE_LIMIT = 1004, // Rate limit exceeded RISK_ERROR_DAILY_LIMIT = 1005, // Daily limit reached RISK_ERROR_TRADE_LIMIT = 1006, // Trade limit reached RISK_ERROR_CONFIG = 1007, // Configuration error RISK_ERROR_THREAD = 1008, // Threading error RISK_ERROR_NOT_INITIALIZED = 1009, // Manager not initialized RISK_ERROR_SYMBOL = 1010, // Invalid symbol RISK_ERROR_VOLUME = 1011, // Invalid volume RISK_ERROR_PRICE = 1012, // Invalid price RISK_ERROR_STOPLOSS = 1013, // Invalid stop loss RISK_ERROR_TAKEPROFIT = 1014, // Invalid take profit RISK_ERROR_MARGIN = 1015, // Not enough margin RISK_ERROR_MARKET_CLOSED = 1016, // Market is closed RISK_ERROR_TRADE_DISABLED = 1017, // Trading is disabled RISK_ERROR_ACCOUNT = 1018, // Account error RISK_ERROR_TIMEOUT = 1019, // Operation timeout RISK_ERROR_CONNECTION = 1020 // Connection error }; // Risk error severity levels enum ENUM_RISK_ERROR_SEVERITY { RISK_SEVERITY_NONE = 0, // No error RISK_SEVERITY_INFO = 1, // Informational message RISK_SEVERITY_WARNING = 2, // Warning - non-critical issue RISK_SEVERITY_CRITICAL = 3, // Critical error - trading should be paused RISK_SEVERITY_FATAL = 4 // Fatal error - immediate action required }; // Position sizing methods enum ENUM_POSITION_SIZING_METHOD { POSITION_SIZING_FIXED = 0, // Fixed lot size POSITION_SIZING_RISK_BASED, // Based on account risk percentage POSITION_SIZING_VOLATILITY, // Based on market volatility (ATR) POSITION_SIZING_KELLY, // Kelly Criterion POSITION_SIZING_OPTIMAL_F, // Optimal F POSITION_SIZING_HYBRID, // Hybrid approach POSITION_SIZING_MARTINGALE, // Martingale (use with caution) POSITION_SIZING_ANTI_MARTINGALE // Anti-Martingale }; // Position scaling methods enum ENUM_POSITION_SCALING { SCALING_NONE = 0, // No scaling SCALING_LINEAR, // Linear scaling with account growth SCALING_SQRT, // Square root scaling SCALING_LOGARITHMIC, // Logarithmic scaling SCALING_AGGRESSIVE, // Aggressive scaling (exponential) SCALING_CONSERVATIVE // Conservative scaling (diminishing returns) }; // Trade direction enum ENUM_TRADE_DIRECTION { TRADE_DIRECTION_LONG = 1, // Long position TRADE_DIRECTION_SHORT = -1, // Short position TRADE_DIRECTION_BOTH = 0 // Both directions }; // Trade metrics structure for performance analysis struct STradeMetrics { datetime timestamp; // Time of the trade string symbol; // Symbol double volume; // Trade volume in lots double entryPrice; // Entry price double exitPrice; // Exit price (0 if still open) double stopLoss; // Stop loss level double takeProfit; // Take profit level double pips; // Pips gained/lost double profit; // Profit/loss in account currency double drawdown; // Drawdown at time of trade double volatility; // Market volatility (ATR) double spread; // Spread at time of trade int duration; // Trade duration in seconds string comment; // Additional comments double winRate; // Current win rate when trade was opened double riskReward; // Risk/reward ratio double kellySize; // Kelly position size double optimalFSize; // Optimal F position size // Default constructor STradeMetrics() : timestamp(0), symbol(""), volume(0), entryPrice(0), exitPrice(0), stopLoss(0), takeProfit(0), pips(0), profit(0), drawdown(0), volatility(0), spread(0), duration(0), winRate(0), riskReward(0), kellySize(0), optimalFSize(0) {} }; //+------------------------------------------------------------------+ //| CRiskManager - Advanced Risk Management Class | //+------------------------------------------------------------------+ class CRiskManager { private: // Thread synchronization CCriticalSection m_cs; // Thread synchronization object // Configuration double m_riskPerTrade; // Risk percentage per trade (0.1-5.0%) double m_dailyLossLimit; // Daily loss limit (% of account) int m_maxOpenTrades; // Maximum number of open trades int m_maxOrdersPerDay; // Maximum orders per day // State double m_dailyPnL; // Today's P&L int m_todayTrades; // Trades executed today bool m_initialized; // Initialization flag datetime m_lastTradeDay; // Last trading day // Error handling string m_lastError; // Last error message ENUM_RISK_ERROR_CODES m_lastErrorCode; // Last error code ENUM_RISK_ERROR_SEVERITY m_lastErrorSeverity; // Error severity // Position sizing ENUM_POSITION_SIZING_METHOD m_sizingMethod; // Current sizing method ENUM_POSITION_SCALING m_scalingMethod; // Position scaling method double m_minPositionSize; // Minimum position size double m_maxPositionSize; // Maximum position size double m_positionSizeStep; // Position size step double m_kellyFraction; // Kelly fraction (0-1) double m_optimalFFraction; // Optimal F fraction (0-1) double m_volatilityPeriod; // Period for volatility calculation double m_volatilityMultiplier; // Volatility multiplier // Caching struct SSymbolCache { double lastPrice; // Last price double atrValue; // Last ATR value datetime lastUpdate; // Last update time double spread; // Current spread double pointValue; // Point value in account currency SSymbolCache() : lastPrice(0), atrValue(0), lastUpdate(0), spread(0), pointValue(0) {} }; CArrayObj* m_symbolCache; // Cache for symbol data // Trade history CArrayObj* m_tradeHistory; // Trade history for analysis int m_maxHistorySize; // Maximum number of trades to keep in history // Performance metrics double m_equityPeak; // Peak equity for drawdown calculation double m_maxDrawdown; // Maximum drawdown percentage double m_winRate; // Current win rate double m_avgWin; // Average win amount double m_avgLoss; // Average loss amount double m_riskRewardRatio; // Average risk/reward ratio // Private methods double CalculateRiskBasedSize(const string symbol, double entryPrice, double stopLoss, double riskAmount); double CalculateVolatilitySize(const string symbol, double entryPrice, double stopLoss, double riskAmount); double CalculateKellySize(double winRate, double winLossRatio, double riskAmount); double CalculateOptimalFSize(double winRate, double winLossRatio, double riskAmount); double CalculateHybridSize(const string symbol, double entryPrice, double stopLoss, double riskAmount); double ScalePositionSize(double size, double accountGrowth); // Helper methods bool IsValidSymbol(const string symbol) const; double NormalizeLotSize(double lots) const; double GetATR(const string symbol, int timeframe, int period, int shift = 0) const; void UpdateSymbolCache(const string symbol); void UpdateTradeMetrics(const STradeMetrics& metrics); double CalculateWinRate() const; double CalculateWinLossRatio() const; public: // Constructor/Destructor CRiskManager(); ~CRiskManager(); // Initialization bool Initialize(); void Deinitialize(); bool IsInitialized() const { return m_initialized; } // Configuration void SetRiskParameters(double riskPerTrade, double dailyLossLimit, int maxOpenTrades, int maxOrdersPerDay); void SetPositionSizingMethod(ENUM_POSITION_SIZING_METHOD method) { m_sizingMethod = method; } void SetPositionScaling(ENUM_POSITION_SCALING method) { m_scalingMethod = method; } void SetPositionSizeLimits(double minSize, double maxSize, double step = 0.01); void SetKellyFraction(double fraction) { m_kellyFraction = MathClamp(fraction, 0.0, 1.0); } void SetOptimalFFraction(double fraction) { m_optimalFFraction = MathClamp(fraction, 0.0, 1.0); } void SetVolatilityPeriod(int period) { m_volatilityPeriod = MathMax(5, period); } void SetVolatilityMultiplier(double multiplier) { m_volatilityMultiplier = MathMax(0.1, multiplier); } // Position sizing double CalculatePositionSize(const string symbol, double entryPrice, double stopLoss, double riskAmount); // Risk management bool CheckTradeRisk(const string symbol, double lots, double entryPrice, double stopLoss, double takeProfit, ENUM_ORDER_TYPE orderType); bool CheckDailyLossLimit() const; bool CheckMaxOpenTrades() const; bool CheckDrawdownLimit() const; bool CheckVolatility(const string symbol) const; // Trade event handlers void OnTradeOpen(ulong ticket, const string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double stopLoss, double takeProfit); void OnTradeClose(ulong ticket, const string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double profit, double swap); // Performance analysis double GetWinRate() const { return m_winRate; } double GetMaxDrawdown() const { return m_maxDrawdown; } double GetRiskRewardRatio() const { return m_riskRewardRatio; } int GetTotalTrades() const { return m_tradeHistory.Total(); } // Error handling string GetLastError() const { return m_lastError; } ENUM_RISK_ERROR_CODES GetLastErrorCode() const { return m_lastErrorCode; } ENUM_RISK_ERROR_SEVERITY GetLastErrorSeverity() const { return m_lastErrorSeverity; } // State management void ResetDailyMetrics(); void ResetAllMetrics(); double GetDailyPnL() const { return m_dailyPnL; } int GetTodayTrades() const { return m_todayTrades; } // Reporting string GenerateReport() const; // Adversarial testing hooks #ifdef ADVSECURITY_ENABLE_TESTING friend class CRiskManagerTester; #endif }; // Include implementation #include "RiskManager_Impl.mqh"