//+------------------------------------------------------------------+ //| CRiskManager.mqh | //| v2.0 - Multi-Mode Money Management Module | //+------------------------------------------------------------------+ #ifndef CRISKMANAGER_MQH #define CRISKMANAGER_MQH #include "CEnumSharing.mqh" class CRiskManager { private: ENUM_MONEY_MANAGEMENT_MODE m_mm_mode; double m_fixed_lots; double m_risk_percent; double m_base_lot_scaling; double m_balance_step_scaling; public: CRiskManager(ENUM_MONEY_MANAGEMENT_MODE mm_mode, double fixed_lot, double risk_pct, double base_lot, double balance_step) { m_mm_mode = mm_mode; m_fixed_lots = fixed_lot; m_risk_percent = risk_pct; m_base_lot_scaling = base_lot; m_balance_step_scaling = balance_step; } ~CRiskManager(){} double GetLotSize(double sl_distance_points) { double lots = 0.0; switch(m_mm_mode) { case MM_MODE_FIXED_LOT: lots = m_fixed_lots; break; case MM_MODE_RISK_PERCENT: lots = CalculateLotByRiskPercent(sl_distance_points); break; case MM_MODE_LOT_PER_BALANCE: lots = CalculateLotByBalanceScaling(); break; } // --- Normalize Lot Size --- double min_lots = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double max_lots = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double step_lots = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); if (step_lots > 0) { lots = MathRound(lots / step_lots) * step_lots; } if(lots < min_lots) lots = 0; // Don't trade if calculated lot is too small if(lots > max_lots) lots = max_lots; return lots; } private: double CalculateLotByRiskPercent(double sl_distance_points) { if(sl_distance_points <= 0) return 0.0; double balance = AccountInfoDouble(ACCOUNT_BALANCE); // Using Balance as requested double risk_amount = balance * (m_risk_percent / 100.0); double tick_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); if(tick_size <= 0 || tick_value <= 0) return 0.0; double loss_per_lot_at_sl = sl_distance_points * _Point / tick_size * tick_value; if(loss_per_lot_at_sl <= 0) return 0.0; return risk_amount / loss_per_lot_at_sl; } double CalculateLotByBalanceScaling() { if(m_balance_step_scaling <= 0) return 0.0; double balance = AccountInfoDouble(ACCOUNT_BALANCE); // Example: Balance=5300, Step=1000, BaseLot=0.01 -> (5300/1000) * 0.01 = 5.3 * 0.01 = 0.053 return (balance / m_balance_step_scaling) * m_base_lot_scaling; } }; #endif