Warrior_EA/Money/MoneyIntelligent.mqh
super.admin 0a527b0cf9 convert
2025-05-30 16:35:54 +02:00

140 lines
5.8 KiB
MQL5

//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//+------------------------------------------------------------------+
#include "..\Expert\ExpertMoneyCustom.mqh"
#include <Trade\DealInfo.mqh>
class CMoneyIntelligent : public CExpertMoneyCustom
{
protected:
double m_factor;
public:
// Constructor
CMoneyIntelligent() : m_factor(1.0) {} // Default decrease factor is set to 1
virtual double CheckOpenLong(double price, double sl);
virtual double CheckOpenShort(double price, double sl);
virtual double CheckClose(CPositionInfo *position) { return(0.0); }
void Factor(double factor) { m_factor = factor; }
private:
double CalculatePotentialLoss(ENUM_ORDER_TYPE orderType, double price, double sl);
double CalculateLotSize(double loss);
double Optimize(double lots);
};
//+------------------------------------------------------------------+
//| Getting lot size for open long position. |
//+------------------------------------------------------------------+
double CMoneyIntelligent::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);
lot = Optimize(lot);
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;
}
//+------------------------------------------------------------------+
//| Getting lot size for open short position. |
//+------------------------------------------------------------------+
double CMoneyIntelligent::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);
lot = Optimize(lot);
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;
}
//+------------------------------------------------------------------+
//| Calculate potential loss |
//+------------------------------------------------------------------+
double CMoneyIntelligent::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 CMoneyIntelligent::CalculateLotSize(double loss)
{
double riskAmount = m_account.Balance() * m_percent / 100.0;
double stepvol = m_symbol.LotsStep();
return MathFloor(riskAmount / loss / stepvol) * stepvol;
}
//+------------------------------------------------------------------+
//| Optimizing lot size for open based on trade history. |
//+------------------------------------------------------------------+
double CMoneyIntelligent::Optimize(double lots)
{
double lot = lots;
// Calculate number of consecutive winning and losing orders without a break
int orders = HistoryDealsTotal(); // Total history deals
int streak = 0; // Number of consecutive winning or losing orders
int streakDirection = 0; // 1 for winning streak, -1 for losing streak
CDealInfo deal;
for(int i = orders - 1; i >= 0; i--)
{
deal.Ticket(HistoryDealGetTicket(i));
if(deal.Ticket() == 0)
{
Print(__FUNCTION__, ": 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)
{
if(streakDirection == -1) // if the previous streak was a losing streak
{
// Adjust the lot based on the number of consecutive losses
if(streak > 1)
lot = NormalizeDouble(lot + lot * streak / m_factor, m_symbol.Digits());
streak = 1; // reset streak count
}
else
{
streak++; // increment winning streak count
}
streakDirection = 1; // set direction to winning streak
}
else
if(profit < 0.0)
{
if(streakDirection == 1) // if the previous streak was a winning streak
{
// Adjust the lot based on the number of consecutive losses
if(streak > 1)
lot = NormalizeDouble(lot - lot * streak / m_factor, m_symbol.Digits());
streak = 1; // reset streak count
}
else
{
streak++; // increment losing streak count
}
streakDirection = -1; // set direction to losing streak
}
}
return lot;
}
//+------------------------------------------------------------------+