AntRobot/models/RiskInfo.mqh

136 lines
6.8 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 14:40:14 +02:00
//+------------------------------------------------------------------+
//| RiskInfo.mqh |
//| Copyright 2021, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include "PositionInfo.mqh"
int lastsOpenPositionsChecked = 0;
struct RiskInfo {
double MaxRiskByTradeInPercent;
double MaxDrawdownInPercent;
double moneyAllowToLoss;
double moneyLoss;
int consecutiveLossUmbral;
int stopAfterConsecutiveLossTime;
int currConsecutiveLoss;
datetime currlossGreaterThanUmbralTime;
datetime initTimeToAnalizeHistoryOrder;
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double moneyInRiskInOpenPosition (RiskInfo &riskInfoParam, int &periodInBarsParam[], PositionInfo &positionsInfoParam[], int periodInBarsLengthParam) {
double moneyInOpenPosition = 0;
for(int i=0; i<periodInBarsLengthParam && !IsStopped(); i++) {
int bars = periodInBarsParam[i];
bool madeTrade = madeTradeInPosition(positionsInfoParam, bars);
if(madeTrade) {
moneyInOpenPosition += positionsInfoParam[bars].riskInMoney;
}
}
return moneyInOpenPosition;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int getConsecutiveLosser(RiskInfo &riskInfoParam, int TOPO_MAGIC_PARAM) {
int result = 0;
HistorySelect(riskInfoParam.initTimeToAnalizeHistoryOrder, TimeCurrent());
int totals = HistoryOrdersTotal();
if(totals <= 0)
return 0;
for(int i = totals - 1; i >= 0; i-- ) {
ulong ticket = HistoryOrderGetTicket(i);
if(HistoryOrderSelect(ticket) && HistoryOrderGetString(ticket,ORDER_SYMBOL) == Symbol() && HistoryOrderGetInteger(ticket,ORDER_MAGIC) == TOPO_MAGIC_PARAM) {
if(HistoryDealSelect(ticket)) {
double profit = HistoryDealGetDouble(ticket,DEAL_PROFIT);
if(profit <= 0) {
if(profit < 0)
result += 1;
} else {
break;
}
}
}
}
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool canMakeTradeFromRiskInfo (RiskInfo &riskInfoParam, int &periodInBarsParam[], PositionInfo &positionsInfoParam[], int periodInBarsLengthParam, datetime initTimeParam) {
double riskInMoney = NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE)*(riskInfoParam.MaxRiskByTradeInPercent/100),_Digits);
double moneyInOpenPosition = moneyInRiskInOpenPosition(riskInfoParam,periodInBarsParam,positionsInfoParam,periodInBarsLengthParam);
double moneyLossed = riskInfoParam.moneyLoss + riskInMoney + moneyInOpenPosition;
if(riskInfoParam.moneyAllowToLoss < moneyLossed) {
string msj = StringFormat("Alert: we can't make a new trade becouse constraint risk. money allow to loss(%f) ,money lossed:(%f) ,number of consecutive loss:(%d)", riskInfoParam.moneyAllowToLoss, riskInfoParam.moneyLoss, riskInfoParam.currConsecutiveLoss);
Print(msj);
Alert(msj);
}
if(riskInfoParam.currConsecutiveLoss >= riskInfoParam.consecutiveLossUmbral) {
if(riskInfoParam.currlossGreaterThanUmbralTime == initTimeParam) {
riskInfoParam.currlossGreaterThanUmbralTime = TimeCurrent();
}
if((TimeCurrent() - riskInfoParam.currlossGreaterThanUmbralTime) < riskInfoParam.stopAfterConsecutiveLossTime) {
return false;
} else {
riskInfoParam.currConsecutiveLoss = 0;
riskInfoParam.currlossGreaterThanUmbralTime = initTimeParam;
riskInfoParam.initTimeToAnalizeHistoryOrder = TimeCurrent();
return true;
}
}
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void updateRiskInfo (RiskInfo &riskInfoParam, int TOPO_MAGIC_PARAM) {
double currAccountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
double accountBalanceFromMoneyAllowToLoss = (riskInfoParam.moneyAllowToLoss*100) / riskInfoParam.MaxDrawdownInPercent;
double currRiskInMoney = NormalizeDouble(currAccountBalance*(riskInfoParam.MaxDrawdownInPercent/100),_Digits);
int currentPositions = PositionsTotal();
// when accountBalanceFromMoneyAllowToLoss == currAccountBalance || currentPositions == lastsOpenPositionsChecked already analize this risk
if(accountBalanceFromMoneyAllowToLoss == currAccountBalance || currentPositions == lastsOpenPositionsChecked)
return;
if(accountBalanceFromMoneyAllowToLoss <= currAccountBalance) {
riskInfoParam.moneyAllowToLoss = currRiskInMoney;
riskInfoParam.initTimeToAnalizeHistoryOrder = TimeCurrent();
} else {
riskInfoParam.moneyLoss = accountBalanceFromMoneyAllowToLoss - currAccountBalance;
}
lastsOpenPositionsChecked = currentPositions;
riskInfoParam.currConsecutiveLoss = getConsecutiveLosser(riskInfoParam, TOPO_MAGIC_PARAM);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
RiskInfo initRiskInfo(double MaxRiskByTradeInPercentParam, double MaxDrawdownInPercentParam, datetime initTimeParam, double moneyAllowToLossParam, int consecutiveLossUmbral, int stopAfterConsecutiveLossTimeInMinute) {
RiskInfo riskInfoTmp;
riskInfoTmp.MaxRiskByTradeInPercent = MaxRiskByTradeInPercentParam;
riskInfoTmp.MaxDrawdownInPercent = MaxDrawdownInPercentParam;
riskInfoTmp.currConsecutiveLoss = 0;
riskInfoTmp.currlossGreaterThanUmbralTime = initTimeParam;
riskInfoTmp.initTimeToAnalizeHistoryOrder = initTimeParam;
riskInfoTmp.moneyAllowToLoss = moneyAllowToLossParam;
riskInfoTmp.moneyLoss = 0;
riskInfoTmp.consecutiveLossUmbral = consecutiveLossUmbral;
riskInfoTmp.stopAfterConsecutiveLossTime = stopAfterConsecutiveLossTimeInMinute * 60;
return riskInfoTmp;
}
//+------------------------------------------------------------------+