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"
|