Martingale MQL Implementation for MetaTrader 4

Introduction



Martingale per definition is a gambling system of continually doubling the stakes in the hope of an eventual win that must yield a net profit. It is based on the mathematical statement that:

Sum 2^[0... (k-1)]<2^k, meaning the previous sum is always small than the next 2 exponent.

Originally, the method was used in casinos to overcome loses by taking a double position each time. In trading, the method was adopted by setting a target imaginary stop loss, once crossed, a double size position with the same direction would open. If the position will go back enough, the whole structure would close, otherwise, another double position will open after the target point.

What I would like to present in this post is a raw implementation of the martingale strategy in less than 50 lines of code. It is only for educational purposes, so use it on your own risk. Personally, I am using a modified version of the martingale which has a better risk management feature. Nevertheless, it can give you a good starting point to implement your own version.

From performance point of view, you can see in the following picture a typical graph of the martingale strategy:

Martingale

Which is a smooth graph going up with little hills from time to time. These "hills" are the martingale strategy opening and doubling the positions until the overall account P&L is positive. The higher the hill, the bigger the position which was used to close the martingale.

Implementation



The full code is available here.

Let's look at the main parts of the code:

extern double MartingalePips=100;//Pips gap between Martingale levels


That's the only input the Martingale expert adviser has. This is the gap, or so called the imaginary stop loss level where we will double the position in attempt to close the martingale. Whenever the position goes against it's take profit direction for 100 pips as the default value, a new order will open up.




int OnInit()
{
MartingalePips*=Point;
MathSrand(GetTickCount());
return INIT_SUCCEEDED;
}


The initialization function is straight forward, I convert the input points to pips and set the seed for the random numbers we will use later on using the recommend value of GetTickCount() as per https://docs.mql4.com/math/mathsrand.




The main body is what makes the martingale magic works:

void OnTick()
{
if(OrdersTotal()==0)
{
if(MathRand()%2==0 && OrderSend(Symbol(),OP_BUY,MarketInfo(Symbol(),MODE_MINLOT),Ask,3,0,NormalizeDouble(Bid+MartingalePips,Digits))==-1)
{
SendNotification("Something went wrong when opening an order, existing");
ExpertRemove();
return;
}
else if(OrdersTotal()==0 && OrderSend(Symbol(),OP_SELL,MarketInfo(Symbol(),MODE_MINLOT),Bid,3,0,NormalizeDouble(Ask-MartingalePips,Digits))==-1)
{
SendNotification("Something went wrong when opening an order, existing");
ExpertRemove();
return;
}
}


If there are no orders open, I use a random number and decide based if it's even or not to go long or short. I do this as I have no idea in which direction the market will go and I am using the martingale input pips as the take profit level. For example, if the random number is 11232 I will open a long position with a take profit target of Bid+MartingalePips.
Of course, you may improve this logic and decide smarter using indicators or some statistical values to take a long or short position, I kept it simple for the sake of education.

Next is where the real martingale kicks in:

else
{
if(OrdersTotal()>1 && AccountProfit()>0)
{
for(int i=OrdersTotal()-1; i>=0; i--)
if(OrderSelect(i,SELECT_BY_POS) && OrderClose(OrderTicket(),OrderLots(),OrderType()==OP_BUY?Bid:Ask,3)==false)
{
SendNotification("Something went wrong when closing an order, existing");
ExpertRemove();
return;
}
}
else if(OrderSelect(OrdersTotal()-1,SELECT_BY_POS) && MathAbs(OrderOpenPrice()-(OrderType()==OP_BUY?Ask:Bid))>MartingalePips
&& OrderSend(Symbol(),OrderType(),2*OrderLots(),OrderType()==OP_BUY?Ask:Bid,3,0,0)==-1)
{
SendNotification("Something went wrong when opening an order, existing");
ExpertRemove();
return;
}
}
}


As soon as the position was opened, there could be two options:


  1. The take profit level reached and the position is closed successfully.

  2. The price went against us MartingalePips so we must double our position to close it.



The first case is where we make the money. The second is only to be able to close the martingale with 0 profit (again, you can improve this logic and try capturing some profit when the trend changes).

The first case checks if we have more than one trade and whether the account profit is larger than 0. This case relates to the open martingale, and can only happen when the last order is big enough to cover the other open orders. For example, having 0.01, 0.02, 0.04 and then the last order of the 0.08 profit is larger than the sum of the first three orders.

The second case checks if the last order which was open went  below the imaginary stop loss of MartingalePips. If yes, then it opens a new order with the same direction but double the lot size - 2*OrderLots(). Then, if the trend reverses and last position gets stronger than the others, the martingale closes and we open a new position with a take profit.

Run the code yourself, just download the mq4 file, compile it and back test it. There is always a trade off between the martingale pips and the risk, the smaller the more frequent a new position will open with double size.

Summary



I introduced a simple working MQL Martingale code for MetaTrader 4. This strategy doubles the position every X pips aiming to close all the positions as soon as the trend changes. It carries significant risk and I would not recommend using it with real money, rather as an educational or a starting point for improved strategy.

As always, feel free to leave comments or join our discussion in Facebook.

Comments