//+------------------------------------------------------------------+ //| MoneyFixedRisk.mqh | //| Copyright 2000-2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "..\Expert\ExpertMoneyCustom.mqh" // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Trading with fixed risk | //| Type=Money | //| Name=FixRisk | //| Class=CMoneyFixedRisk | //| Page= | //| Parameter=Percent,double,10.0,Risk percentage | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CMoneyFixedRisk. | //| Purpose: Class of money management with fixed percent risk. | //| Derives from class CExpertMoney. | //+------------------------------------------------------------------+ class CMoneyFixedRisk : public CExpertMoneyCustom { public: virtual double CheckOpenLong(double price, double sl); virtual double CheckOpenShort(double price, double sl); virtual double CheckClose(CPositionInfo *position) { return(0.0); } private: double CalculatePotentialLoss(ENUM_ORDER_TYPE orderType, double price, double sl); double CalculateLotSize(double loss); }; //+------------------------------------------------------------------+ //| Getting lot size for open long position. | //+------------------------------------------------------------------+ double CMoneyFixedRisk::CheckOpenLong(double price, double sl) { if(m_symbol == NULL) return 0.0; double loss = CalculatePotentialLoss(ORDER_TYPE_BUY, price, sl); if(loss <= 0.0) return m_symbol.LotsMin(); double lot = CalculateLotSize(loss); string description; // Adjust the lot size within allowed bounds and ensure sufficient margin if(CheckAndCorrectVolumeValue(lot, description) && CheckAndAdjustMoneyForTrade(m_symbol.Name(), lot, ORDER_TYPE_BUY)) return lot; else return 0.0; // Handle as needed or inform the user } //+------------------------------------------------------------------+ //| Getting lot size for open short position. | //+------------------------------------------------------------------+ double CMoneyFixedRisk::CheckOpenShort(double price, double sl) { if(m_symbol == NULL) return 0.0; double loss = CalculatePotentialLoss(ORDER_TYPE_SELL, price, sl); if(loss <= 0.0) return m_symbol.LotsMin(); double lot = CalculateLotSize(loss); string description; // Adjust the lot size within allowed bounds and ensure sufficient margin if(CheckAndCorrectVolumeValue(lot, description) && CheckAndAdjustMoneyForTrade(m_symbol.Name(), lot, ORDER_TYPE_SELL)) return lot; else return 0.0; // Handle as needed or inform the user } //+------------------------------------------------------------------+ //| Calculate potential loss | //+------------------------------------------------------------------+ double CMoneyFixedRisk::CalculatePotentialLoss(ENUM_ORDER_TYPE orderType, double price, double sl) { if(price == 0.0) price = (orderType == ORDER_TYPE_BUY) ? m_symbol.Ask() : m_symbol.Bid(); return -m_account.OrderProfitCheck(m_symbol.Name(), orderType, 1.0, price, sl); } //+------------------------------------------------------------------+ //| Calculate the lot size based on potential loss and account balance| //+------------------------------------------------------------------+ double CMoneyFixedRisk::CalculateLotSize(double loss) { double riskAmount = m_account.Balance() * m_percent / 100.0; double stepvol = m_symbol.LotsStep(); return MathFloor(riskAmount / loss / stepvol) * stepvol; } //+------------------------------------------------------------------+