EA_SMC_Mql5/Include/CRiskManager.mqh
2025-07-03 23:37:44 +07:00

94 lines
No EOL
6.3 KiB
MQL5

//+------------------------------------------------------------------+
//| 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