Risk Management Features and Functions in MQL4 Language (MT4)

Some of the most important features are required for risk management in trading forex because it is most volatile and risky market all over the world and majority of the forex trader uses MT4 platform to automate their trading strategy using technical or custom indicators. Here is how you can code trailing stop, Auto lot sizing and Partial closing function in MT4 platform.

Trailing Stop in MQL4

A trailing stop is a type of stock order. It allows an investor to set a maximum loss on a position in a security, while the stop-loss price follows (or "trails") the security's market price as it rises. For example, an investor might set a trailing stop of 10% on a stock they own. If the stock price rises, the stop-loss price will also rise by the same percentage, but if the stock price falls by more than 10%, the stop-loss order will be triggered and the stock will be sold at the market price.

Trailing stops can be a useful tool for managing risk in a portfolio, as they allow investors to lock in gains on a security while still allowing for the possibility of further price appreciation. However, it's important to note that trailing stops do not guarantee that an investor will sell a security at a certain price, as the order will only be triggered if the market price falls below the stop-loss price. Additionally, trailing stops can be subject to slippage, which means that the actual selling price of the security may be different from the stop-loss price.

input string Trailing_Stop________________="Trailing _Stop______________";

input double TrailingStop   = 10;

input double TrailingStep   = 10; 

Use the above as external variables to control the system

Use the below line in Ontick() Function.

 if(TrailingStop>0&&Orderscnt()>=1)MoveTrailingStop();

void MoveTrailingStop()

{

 bool s,mod;

 for(int cnt=0;cnt<OrdersTotal();cnt++)

 {

  s=OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);

  string sy=OrderSymbol();

  int    tk=OrderTicket(),

         ot=OrderType(),

         mn=OrderMagicNumber();

  double op=OrderOpenPrice(),

         sl=OrderStopLoss(),

         tp=OrderTakeProfit();

  if(sy==Symbol()&&mn==MagicNo&&ot<=OP_SELL)

  {

   if(ot==OP_BUY)

   {

    if(TrailingStop>

    0&&NormalizeDouble(Ask-(TrailingStep*point),Digits)>NormalizeDouble((op+(TrailingStop*point)),Digits)) 

    {                 

     if((NormalizeDouble(sl,Digits)<NormalizeDouble(Bid-(TrailingStop*point),Digits))||(sl==0))

     {

      mod=OrderModify(tk,op,NormalizeDouble(Bid-(TrailingStop*point),Digits),tp,0,Blue);

     }

    }

   }

   else

   {

    if(TrailingStop>0&&NormalizeDouble(Bid+(TrailingStep*point),Digits)<NormalizeDouble((op-(TrailingStop*point)),Digits))  

    {                 

     if((NormalizeDouble(sl,Digits)>(NormalizeDouble(Ask+(TrailingStop*point),Digits)))||(sl==0))

     {

      mod=OrderModify(tk,op,NormalizeDouble(Ask+(TrailingStop*point),Digits),tp,0,Red);

     }

    }

   }

  }

 }

}


Use the above trailing stop function.

int Orderscnt(int type=-1)

{

 int cnt=0;

 for(int i=0;i<OrdersTotal();i++)

 {

  if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))

  {

   if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MagicNo&&(OrderType()==type||type==-1))

   {

    cnt++;

   }

  }

 }

 return(cnt);

Orders Counting Function

AUTO LOT SIZING USING STOP LOSS

It is possible to use a trailing stop to determine the size of your position (also known as the "lot size") in a security. This can be done by setting the stop-loss price at a certain percentage of your account value and then calculating the size of the position based on the stop-loss price and the risk you are willing to take on the trade.

For example, let's say you have a $100,000 account and you want to risk no more than 1% of your account value on a trade. You could set a trailing stop at -1% and then calculate the size of your position based on the stop-loss price and the risk you are willing to take.

Here's an example of how to do this:

Determine the stop-loss price: $100,000 x 1% = $1,000

Calculate the size of the position: $1,000 / (stop-loss price - entry price) = number of shares

In this example, let's say the entry price of the security is $50. The size of the position would be calculated as follows:

$1,000 / ($50 - $1,000) = 20 shares

Auto Lot sizing code in MQL4

extern double MaxRiskPerTrade = 1; // % of balance to risk in one trade.

extern int StopLoss = 20; // Stop Loss in pips.

double CalculateLotSize(double SL){         

   double LotSize = 0;

   // We get the value of a tick.

   double Tickvalue = MarketInfo(Symbol(), MODE_TICKVALUE);

   // If the digits are 3 or 5, we normalize multiplying by 10.

   if ((Digits == 3) || (Digits == 5)){

      Tickvalue = Tickvalue * 10;

   }

 

   LotSize = (AccountBalance() * MaxRiskPerTrade / 100) / (SL * Tickvalue);

   LotSize = MathRound(LotSize / MarketInfo(Symbol(), MODE_LOTSTEP)) * MarketInfo(Symbol(), MODE_LOTSTEP);

   return LotSize;

}


void OnTick()

{

   // We print the position size in lots.

   Print("Position size in lots? ", CalculateLotSize(StopLoss));

}

This means that if the market price of the security falls below $50 by more than 1%, the trailing stop will be triggered and the position will be sold. The size of the position (20 shares) was calculated based on the stop-loss price and the risk you were willing to take on the trade.

It's important to note that this is just one way to use a trailing stop to determine the size of a position, and different investors may have different strategies for managing risk. It's always a good idea to carefully consider your own risk tolerance and investment objectives before making any trades.

PARTIAL CLOSE TP1, TP2 and TP3 in MQL4 

Partial close is a term used to describe the process of closing only a portion of a position in a security rather than the entire position. This can be useful for a number of reasons, such as locking in profits on a portion of a position while still holding the remainder of the position for the potential for further price appreciation.

To partially close a position, an investor would place an order to sell only a portion of the shares they hold in a security. For example, if an investor owns 100 shares of a stock and wants to partially close their position, they might place an order to sell 50 shares. This would leave them with a remaining position of 50 shares.

Partial close can be a useful tool for managing risk in a portfolio, as it allows investors to take profits on a portion of their position while still allowing for the possibility of further price appreciation on the remainder of the position. However, it's important to note that the market price of the security may fluctuate after a partial close, and investors should carefully consider their risk tolerance and investment objectives before making any trades.

  string TP1_TP2_TP3="___TP1_TP2_TP3___";             

  double PartialProfit1=0,

             PartialProfit2=0,

             PartialProfit3=0;

 string Percent_Lot_To_close="______________";            

  double LotsPercent1=0,                 

             LotsPercent2=0,                        

             LotsPercent3=0;

void PartialClose()

{

 bool close;

 for(int cnt=0;cnt<OrdersTotal();cnt++)

 {

  bool select=OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);

  string   sy=OrderSymbol();

  datetime ot=OrderOpenTime();

  double   op=OrderOpenPrice(),

           ol=OrderLots(),

           sl=OrderStopLoss(),

           tp=OrderTakeProfit();

  int      tk=OrderTicket(),

           ty=OrderType(),

           mn=OrderMagicNumber(),

           closecount=OrderCloseCount(op,ot);

  double   pc1=NormalizeDouble(LotsPercent1*ol/100,2),

           pc2=NormalizeDouble(LotsPercent2*ol/100,2),

           pc3=NormalizeDouble(LotsPercent3*ol/100,2);

  if(sy==Symbol()&&mn==MagicNo)

  {

   if(ty==OP_BUY)

   {

    if(PartialProfit1>0&&Bid>=op+PartialProfit1*point&&closecount<1){close=OrderClose(tk,pc1,Bid,3*Q);}

    if(PartialProfit2>0&&Bid>=op+PartialProfit2*point&&closecount<2){close=OrderClose(tk,pc2,Bid,3*Q);}

    if(PartialProfit3>0&&Bid>=op+PartialProfit3*point&&closecount<3){close=OrderClose(tk,pc3,Bid,3*Q);}

   } 

   if(ty==OP_SELL)

   {

    if(PartialProfit1>0&&Ask<=op-PartialProfit1*point&&closecount<1){close=OrderClose(tk,pc1,Ask,3*Q);}

    if(PartialProfit2>0&&Ask<=op-PartialProfit2*point&&closecount<2){close=OrderClose(tk,pc2,Ask,3*Q);}

    if(PartialProfit3>0&&Ask<=op-PartialProfit3*point&&closecount<3){close=OrderClose(tk,pc3,Ask,3*Q);}

   } 

  }  

 }

}  


int OrderCloseCount(double openprice,datetime opentime)

{

 int closecount=0;

 int i=0;

 while(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))

 {

  i++;

  if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MagicNo)

  {

   if(OrderOpenPrice()==openprice&&OrderOpenTime()==opentime)closecount++;

  }

 } 

 return(closecount);   

}


Comments