2025-05-30 16:35:54 +02:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| MoneyFixedLot.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 trade volume |
|
|
|
|
|
//| Type=Money |
|
|
|
|
|
//| Name=FixLot |
|
|
|
|
|
//| Class=CMoneyFixedLot |
|
|
|
|
|
//| Page= |
|
|
|
|
|
//| Parameter=Percent,double,10.0,Percent |
|
|
|
|
|
//| Parameter=Lots,double,0.1,Fixed volume |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
// wizard description end
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Class CMoneyFixedLot. |
|
|
|
|
|
//| Purpose: Class of money management with fixed lot. |
|
|
|
|
|
//| Derives from class CExpertMoney. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
class CMoneyFixedLot : public CExpertMoneyCustom
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
//--- input parameters
|
|
|
|
|
double m_lots;
|
2026-07-26 23:08:32 -04:00
|
|
|
//--- declared ahead of the inline CheckOpenLong/Short bodies below that call it
|
|
|
|
|
double CheckedLot(ENUM_ORDER_TYPE type);
|
2025-05-30 16:35:54 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
//---
|
|
|
|
|
void Lots(double lots) { m_lots=lots; }
|
|
|
|
|
virtual bool ValidationSettings(void);
|
2026-07-26 23:08:32 -04:00
|
|
|
//--- The fixed lot from the input is a REQUEST, not a guarantee: it still has to clear the
|
|
|
|
|
//--- broker's volume grid, the per-symbol SYMBOL_VOLUME_LIMIT and free margin before it can be
|
|
|
|
|
//--- sent (article 2555 #2/#3/#5). Returning m_lots raw - as this class used to - meant a
|
|
|
|
|
//--- Money_FixLot_Lots that a small/loaded account cannot margin was handed straight to
|
|
|
|
|
//--- OrderSend() and rejected server-side with "not enough money" every single signal.
|
|
|
|
|
virtual double CheckOpenLong(double price,double sl) { return(CheckedLot(ORDER_TYPE_BUY)); }
|
|
|
|
|
virtual double CheckOpenShort(double price,double sl) { return(CheckedLot(ORDER_TYPE_SELL)); }
|
2025-05-30 16:35:54 +02:00
|
|
|
};
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-07-26 23:08:32 -04:00
|
|
|
//| Run the configured fixed lot through the shared pre-OrderSend |
|
|
|
|
|
//| volume gate; 0.0 means "no legal volume right now", which |
|
|
|
|
|
//| CExpert::OpenLong/OpenShort treat as "do not trade this tick". |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
double CMoneyFixedLot::CheckedLot(ENUM_ORDER_TYPE type)
|
|
|
|
|
{
|
|
|
|
|
double lot = m_lots;
|
|
|
|
|
string description;
|
|
|
|
|
if(!ValidateLotForTrade(MoneySymbol(), lot, type, description))
|
|
|
|
|
return(0.0);
|
|
|
|
|
return(lot);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
2025-05-30 16:35:54 +02:00
|
|
|
//| Validation settings protected data. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CMoneyFixedLot::ValidationSettings(void)
|
|
|
|
|
{
|
|
|
|
|
if(!CExpertMoney::ValidationSettings())
|
|
|
|
|
return(false);
|
|
|
|
|
//--- initial data checks
|
|
|
|
|
if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax())
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__+": lots amount must be in the range from %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax());
|
|
|
|
|
return(false);
|
|
|
|
|
}
|
2026-07-26 23:08:32 -04:00
|
|
|
//--- article 2555 #10: LotsStep() is 0 until the broker syncs SYMBOL_VOLUME_STEP, and the
|
|
|
|
|
//--- multiple-of-step test below divides by it twice
|
|
|
|
|
if(m_symbol.LotsStep()<=0.0)
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__+": SYMBOL_VOLUME_STEP for %s is not available yet (%f)",m_symbol.Name(),m_symbol.LotsStep());
|
|
|
|
|
return(false);
|
|
|
|
|
}
|
2025-05-30 16:35:54 +02:00
|
|
|
if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10)
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__+": lots amount is not corresponding with lot step %f",m_symbol.LotsStep());
|
|
|
|
|
return(false);
|
|
|
|
|
}
|
|
|
|
|
//--- ok
|
|
|
|
|
return(true);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|