266 lines
12 KiB
MQL5
266 lines
12 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| 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 <Trade\Trade.mqh>
| |||
#include <Trade\PositionInfo.mqh>
| |||
#include <Trade\DealInfo.mqh>
| |||
#include <Trade\OrderInfo.mqh>
| |||
#include <Trade\HistoryOrderInfo.mqh>
| |||
#include <Arrays\ArrayObj.mqh>
| |||
#include <Arrays\ArrayString.mqh>
| |||
#include <Arrays\ArrayDouble.mqh>
| |||
#include <Files\FileBin.mqh>
| |||
#include <Math\Stat\Math.mqh>
| |||
#include <Math\Stat\Normal.mqh>
| |||
| |||
// 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"
|