136 lines
6.8 KiB
MQL5
136 lines
6.8 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| 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;
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|