You're reading...
EA development, Money Management, MQL4

Maximum Relative Drawdown in MT4

This post is split into 3 parts.
Part 1 explains how MT4 records Relative Drawdown, which is not well understood.
Part 2 will show my code to calculate Relative Drawdown against Balance just prior to a trade, which I inherently find much more useful.
Part 3 shows the mql4 code for calculating and displaying this Relative Drawdown against Balance.


How MT4 calculates Relative Drawdown:

Relative Drawdown in MT4’s report is calculated as a percentage of the difference of the historical equity high and equity low, against the equity high. E.g.

    1. Account balance at the start is $100.
    2. A trade is opened and then goes into floating profit of $10. This makes the equity high $100+$10 = $110.
    3. The trade then goes into negative territory of -$20. This makes the equity low $100-$20 = $80.
    4. Relative Drawdown(MT4) is calculated as: ($110-$80)/$110 * 100 = 27.27%

Go to How to Evaluate the Expert Testing Results for the actual code involved in the report generation.


Relative Drawdown against Balance:

I calculate a drawdown as the amount going below the Balance(at the start of a trade) instead of the Equity high. Rationale is that if a trade goes into profit but is not closed out, this floating profit never ‘belonged’ to the trader, or algorithm, and should not be construed as banked profit.

I will illustrate with a breakeven trade for both methods of calculation for Relative Drawdown :

    1. Account balance at the start is $100.
    2. A trade is opened and then goes into floating profit of $10. This makes the equity high $100+$10 = $110.
    3. A breakeven is set at the entry price.
    4. The price retraces and exits at breakeven.

For MT4’s Relative Drawdown, it is:

($110-$100)/$110 * 100 = 9.09%

For Relative Drawdown based on pre-trade Balance, it is:

($100-$100)/$100 * 100 = 0%

With MT4’s calculation, even though your Equity never dropped below your starting Balance, your Relative Drawdown is 9.09%. But with Relative Drawdown calculated against Balance, it is 0%. Which makes for more meaningful interpretation. (NB. technically the moment you open a trade, the spread already incurs a drawdown on the Balance, but I leave it out in the explanation here to simplify things)

Illustrating earlier example with Relative Drawdown calculated from Balance:

    1. Account Balance at the start is $100.
    2. A trade is opened and then goes into profit of $10. This makes the equity high $100+$10 = $110.
    3. The trade then goes into negative territory of -$20. This makes the equity low $100-$20 = $80.
    4. Relative Drawdown(Balance) is calculated as: ($100-$80)/$100 * 100 = 20.00%

We see now that for an account with a remaining Balance of $80 from a starting Balance of $100, it is more meaningful to state that it has suffered a 20% drawdown, instead of a 27.27% drawdown.

An extreme example to illustrate the less meaningful use of MT4’s Relative Drawdown calculation:

    1. Account Balance at the start is $100.
    2. A trade is opened and then goes into floating profit of $500. This makes the equity high $100+$500 = $600.
    3. The trade then goes into negative territory of -$20. This makes the equity low $100-$20 = $80.
    4. Relative Drawdown(MT4) is calculated as: ($600-$80)/$600 * 100 = 86.67%

Even though the account is only 20% below the starting Balance, MT4 reports the Relative Drawdown as 86.67%. Not so meaningful.


MQL4 Code:

Now the technical bit, to display this salient information, put into your code:

int start(){
   //your code;
   MaxDD();
   MaxDDM();
   Comment(MaxDD(),"\n",MaxDDM()); //for displaying on your screen (adapt to your own comments as you see fit)
   return(0);
}

Insert this function into your EA to display as a string for printing or commenting:

    1. Maximum Relative Drawdown % against on Balance
    2. Corresponding Maximum Relative Drawdown as an amount in your Deposit Currency (not so important)
    3. Time when the this Maximum Relative Drawdown occurred (useful for analysis)
string MaxDD(){ //Maximum drawdown data; displayed as "DD%(corresponding DD$),time of occurrence"
   string DC = AccountCurrency(); //Deposit Currency
   if(DC=="JPY")int DCdeci=0;else DCdeci=2; //to display Deposit Currency JPY and non-JPY with correct decimal places
   static double mddp=0, dd=0;
   static datetime y=0, m=0, d=0;
   double ddp=(NetDC()+NetSwap()+NetComm())/AccountBalance()*100; //drawdown percent
   if(ddp<mddp){ //if current DD%(ddp) is more than previous logged DD%(mddp)
      mddp=ddp; //log current DD% as latest maximum DD%
      dd=NetDC()+NetSwap()+NetComm(); //log DD$ at the instant that DD% is greatest
      y=TimeYear(TimeCurrent());
      m=TimeMonth(TimeCurrent());
      d=TimeDay(TimeCurrent());
   }
   return(StringConcatenate("MaxDD: ", DoubleToStr(-mddp,2), "%", "(", DoubleToStr(-dd,DCdeci), " ", DC, "), ", y, ".", m, ".", d));
}

This function is the same as the above but with margin utilised added in. I find this is important as it gives a true picture of just how close you have come to a margin call. 😉 Particularly for accounts with low leverage.

string MaxDDM(){ //Maximum drawdown data including margin used
   string DC=AccountCurrency();
   if(DC=="JPY")int DCdeci=0;else DCdeci=2;
   static double mddp=0, dd=0;
   static datetime y=0, m=0, d=0;
   double ddp=(NetDC()+NetSwap()+NetComm()-AccountMargin())/AccountBalance()*100;
   if(ddp<mddp){
      mddp=ddp;
      dd=NetDC()+NetSwap()+NetComm()-AccountMargin();
      y=TimeYear(TimeCurrent());
      m=TimeMonth(TimeCurrent());
      d=TimeDay(TimeCurrent());
   }
   return(StringConcatenate("MaxDDM: ", DoubleToStr(-mddp,2), "%", "(", DoubleToStr(-dd,DCdeci), " ", DC, "), ", y, ".", m, ".", d));
}

Insert this into your deinit() to print it on deinitialisation. Useful when running non-visual backtests.

int deinit(){
   Print(MaxDD()); //to print to Journal after Strategy Tester ends or EA disabled
   Print(MaxDDM());
   return(0);
}

The result should be that you see this on your screen:

And this in your journal:


Edit:
Include these for the MaxDD() and MaxDDM() functions to work:

double NetDC(){ //Net profit in deposit currency
   double ndc=0;
   for(int i=OrdersTotal()-1;i>=0;i--){
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if(OrderSymbol()==Symbol()&&OrderMagicNumber()==Magic)ndc+=OrderProfit();
   }
   return(ndc);
}
double NetSwap(){ //Net swap in deposit currency
   double ns=0;
   for(int i=OrdersTotal()-1;i>=0;i--){
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if(OrderSymbol()==Symbol()&&OrderMagicNumber()==Magic)ns+=OrderSwap();
   }
   return(ns);
}
double NetComm(){ //Net commission in deposit currency
   double nc=0;
   for(int i=OrdersTotal()-1;i>=0;i--){
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if(OrderSymbol()==Symbol()&&OrderMagicNumber()==Magic)nc+=OrderCommission();
   }
   return(nc);
}

This post is mirrored at MT4 Relative Drawdown @ Forex Factory


Discussion

No comments yet.

Leave a comment

Archives

Visitors

Flag Counter