forked from ntsinh90/EA_SMC_Mql5
94 lines
No EOL
6.3 KiB
MQL5
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 |