155 lines
5.9 KiB
MQL5
155 lines
5.9 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| MoneySizeOptimized.mqh |
|
|
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#include <Expert\ExpertMoney.mqh>
|
|
#include <Trade\DealInfo.mqh>
|
|
// wizard description start
|
|
//+------------------------------------------------------------------+
|
|
//| Description of the class |
|
|
//| Title=Trading with optimized trade volume |
|
|
//| Type=Money |
|
|
//| Name=SizeOptimized |
|
|
//| Class=CMoneySizeOptimized |
|
|
//| Page= |
|
|
//| Parameter=DecreaseFactor,double,3.0,Decrease factor |
|
|
//| Parameter=Percent,double,10.0,Percent |
|
|
//+------------------------------------------------------------------+
|
|
// wizard description end
|
|
//+------------------------------------------------------------------+
|
|
//| Class CMoneySizeOptimized. |
|
|
//| Purpose: Class of money management with size optimized. |
|
|
//| Derives from class CExpertMoney. |
|
|
//+------------------------------------------------------------------+
|
|
class CMoneySizeOptimized : public CExpertMoney
|
|
{
|
|
protected:
|
|
double m_decrease_factor;
|
|
|
|
public:
|
|
CMoneySizeOptimized(void);
|
|
~CMoneySizeOptimized(void);
|
|
//---
|
|
void DecreaseFactor(double decrease_factor) { m_decrease_factor=decrease_factor; }
|
|
virtual bool ValidationSettings(void);
|
|
//---
|
|
virtual double CheckOpenLong(double price,double sl);
|
|
virtual double CheckOpenShort(double price,double sl);
|
|
|
|
protected:
|
|
double Optimize(double lots);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor |
|
|
//+------------------------------------------------------------------+
|
|
void CMoneySizeOptimized::CMoneySizeOptimized(void) : m_decrease_factor(3.0)
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Destructor |
|
|
//+------------------------------------------------------------------+
|
|
void CMoneySizeOptimized::~CMoneySizeOptimized(void)
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Validation settings protected data. |
|
|
//+------------------------------------------------------------------+
|
|
bool CMoneySizeOptimized::ValidationSettings(void)
|
|
{
|
|
if(!CExpertMoney::ValidationSettings())
|
|
return(false);
|
|
//--- initial data checks
|
|
if(m_decrease_factor<=0.0)
|
|
{
|
|
printf(__FUNCTION__+": decrease factor must be greater then 0");
|
|
return(false);
|
|
}
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Getting lot size for open long position. |
|
|
//+------------------------------------------------------------------+
|
|
double CMoneySizeOptimized::CheckOpenLong(double price,double sl)
|
|
{
|
|
if(m_symbol==NULL)
|
|
return(0.0);
|
|
//--- select lot size
|
|
double lot;
|
|
if(price==0.0)
|
|
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,m_symbol.Ask(),m_percent);
|
|
else
|
|
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent);
|
|
//--- return trading volume
|
|
return(Optimize(lot));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Getting lot size for open short position. |
|
|
//+------------------------------------------------------------------+
|
|
double CMoneySizeOptimized::CheckOpenShort(double price,double sl)
|
|
{
|
|
if(m_symbol==NULL)
|
|
return(0.0);
|
|
//--- select lot size
|
|
double lot;
|
|
if(price==0.0)
|
|
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,m_symbol.Bid(),m_percent);
|
|
else
|
|
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent);
|
|
//--- return trading volume
|
|
return(Optimize(lot));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Optimizing lot size for open. |
|
|
//+------------------------------------------------------------------+
|
|
double CMoneySizeOptimized::Optimize(double lots)
|
|
{
|
|
double lot=lots;
|
|
//--- calculate number of losses orders without a break
|
|
if(m_decrease_factor>0)
|
|
{
|
|
//--- select history for access
|
|
HistorySelect(0,TimeCurrent());
|
|
//---
|
|
int orders=HistoryDealsTotal(); // total history deals
|
|
int losses=0; // number of consequent losing orders
|
|
CDealInfo deal;
|
|
//---
|
|
for(int i=orders-1;i>=0;i--)
|
|
{
|
|
deal.Ticket(HistoryDealGetTicket(i));
|
|
if(deal.Ticket()==0)
|
|
{
|
|
Print("CMoneySizeOptimized::Optimize: HistoryDealGetTicket failed, no trade history");
|
|
break;
|
|
}
|
|
//--- check symbol
|
|
if(deal.Symbol()!=m_symbol.Name())
|
|
continue;
|
|
//--- check profit
|
|
double profit=deal.Profit();
|
|
if(profit>0.0)
|
|
break;
|
|
if(profit<0.0)
|
|
losses++;
|
|
}
|
|
//---
|
|
if(losses>1)
|
|
lot=NormalizeDouble(lot-lot*losses/m_decrease_factor,2);
|
|
}
|
|
//--- normalize and check limits
|
|
double stepvol=m_symbol.LotsStep();
|
|
lot=stepvol*NormalizeDouble(lot/stepvol,0);
|
|
//---
|
|
double minvol=m_symbol.LotsMin();
|
|
if(lot<minvol)
|
|
lot=minvol;
|
|
//---
|
|
double maxvol=m_symbol.LotsMax();
|
|
if(lot>maxvol)
|
|
lot=maxvol;
|
|
//---
|
|
return(lot);
|
|
}
|
|
//+------------------------------------------------------------------+
|