Let's trade using computer science!

Hi fellow traders!

One of the most frequently asked questions I get from my blog readers is how to handle market spread when opening new orders using MetaTrader platform. So in this section I will try to illustrate how I handle Spread vs Stop Loss and Take Profit levels. So let’s first look in the MQL4 manual (MQL4 is the programming language of MT4).

Source: https://docs.mql4.com/trading/ordersend ordersend with stoploss

In the example above a ‘Buy’ order is opened at ‘Ask’ price, with a StopLoss and TakeProfit levels equal to minimum allowed StopLoss distance from the current ‘Bid’ price. Using the ‘Bid’ price as reference for SL/TP levels, is the recommended way of opening orders, but is this really the best way?..So it depends on your risk-reward ratio. Most of my own trading systems require a risk-reward of 1:1, so for example: StopLoss = 10 Pips and TakeProfit = 10 Pips. Let’s see what would happen if I have followed recommendation from the MT4 manual and used ‘Bid’ price as reference point for my TP and SL levels: In this configuration, with assumed spread of 2 Pips, my EA would make only 8 Pips hitting profit and would loss 12 Pips when hitting my StopLoss level. If my trading system had a 50% winning ratio I would be only losing my money!

So how to deal with spread when opening new market positions?


The answer is very simple: Always use your entry price as SL and TP reference. This means using ‘Ask’ for Buy orders and ‘Bid’ levels for ‘Sell’ orders. In this configuration the EA will always win and lose the same amount of money. Using this approach you need only a winning ratio of 51% in order to be profitable on the long term. (this of course not including slippages and broker commissions).

However, there is a big ‘BUT’ for this strategy! You should avoid spread widening, which can be introduced by your broker e.g.: during high volatile events like market news release. The code below show how to avoid spread widening and how to set SL and TP using entry levels.


bool OpenBuy()
{
   //Get new market prices
   RefreshRates();
   
   //Define lot size
   double Lots = 0.1;
   int LotDigits = (int) - MathLog10(SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP));
   double LotSize=NormalizeDouble(Lots,LotDigits); 
   
   //Calculate and check spread  
   double MaxSpreadInPoints = 50; 
   double Spread = Ask - Bid;
   if(Spread>MaxSpreadInPoints*Point)
      return(false);
   
   //Define allowed slippage
   int SlippageInPoints = 20;
   
   //Define TakeProfit and StopLoss levels 
   double TakeProfit = NormalizeDouble(Bid+Spread+10*PIP,Digits);
   double StopLoss = NormalizeDouble(Bid+Spread-10*PIP,Digits);;

   Ticket=OrderSend(Symbol(),OP_BUY,LotSize,Ask,SlippageInPoints,StopLoss,TakeProfit,"Spread Test",MagicNr,0,Green);
   
   if(Ticket==-1)
   {
      Alert("Buy Error: " ,GetLastError());
      return(false); 
   }
   if(Ticket>=0)
   {
      return(true);
   }
   
   return(false);
}

bool OpenSell()
{
   //Get new market prices
   RefreshRates();
   
   //Define lot size
   double Lots = 0.1;
   int LotDigits = (int) - MathLog10(SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP));
   double LotSize=NormalizeDouble(Lots,LotDigits); 
   
   //Calculate and check spread  
   double MaxSpreadInPoints = 50; 
   double Spread = Ask - Bid;
   if(Spread>MaxSpreadInPoints*Point)
      return(false);
   
   //Define allowed slippage
   int SlippageInPoints = 20;
   
   //Define TakeProfit and StopLoss levels 
   double TakeProfit = NormalizeDouble(Bid-10*PIP,Digits);
   double StopLoss = NormalizeDouble(Bid+10*PIP,Digits);;

   Ticket=OrderSend(Symbol(),OP_SELL,LotSize,Bid,SlippageInPoints,StopLoss,TakeProfit,"Spread Test",MagicNr,0,Red);
   
   if(Ticket==-1)
   {
      Alert("Sell Error: " ,GetLastError());
      return(false); 
   }
   if(Ticket>=0)
   {
      return(true);
   }
   
   return(false);
}	

As you can see only 'Buy' orders need an additional entry level correction, since 'Sell' orders are using 'Bid' as entry price. The following figure shows the outcome of this approach: 1:1 risk-reward example
The EA based on this strategy always wins and losses equal amount of money, which in this example is equal to $10.

That's it;)
Greets,
Chris  

15 Responses to Spread, Stop Loss and Take Profit

  • check this plz

    place two order in a same time

    buy with sl 10 and dont set tp but set a time for closing the order(like 15 candls)

    sell with sl 10 and dont set tp but set a time for closing the order(like 15 candls)

    if you can make it as a expert plz send it to me.
    thanks
    mojtaba.shiezadeh@gmail.com

  • Interesting, so if trades are taken on daily moving average and TP > then SL this EA could be a good average winner? Or am i not understand it right? If i am right, can we download an EA that does just that?

    Thanks

    • It is not a complete EA but just a piece of sample code that shows how to get this done MQL4. Using this piece of code the EA will average on 0 profit and 0 loss. Of course assuming the price movement is enough to overcome spread difference.

  • Do you have an ea that has the said parameters sl ten pips tp 10pips that places the order same time
    if so can I get the trial version

  • Hi Chris,

    Doesn’t “MaxSpreadInPoints = 50” need to multiply with Point?

    Regards,
    Nutchapon

  • Thank you so much for the article, it is really
    helpful

  • I love this snippet but I’m unable to get it to work with my EA. It’s giving me Error 129 – i.e. invalid SL and TP.

    1. Please, is this tactic still valid and what can I do to make it work, especially on ECN platform?

    2 Can you please, throw more lights on these variables and their interpretations?
    i. PIP
    ii. SlippageInPoints
    iii. MaxSpreadInPoints

    3. What’s the difference between Spread and Slippage? How do we make provision for them in entering a trade?

    Thank you very much for taking time to respond.
    Regards.

    • Hi,

      For the most ECN borkers you need first to open an order with SL=0; and then use OrderModify() function to set your valid SL levels.

      I hope this is clear.
      Gr
      Chris

  • Dear Chris,

    You wrote to use “‘Ask’ for Buy orders and ‘Bid’ levels for ‘Sell’ orders”.
    But in your example code you use ‘Bid’ for buy orders and ‘Bid’ for sell orders.
    I hope this is a tipo.

    Your comment will be much appreciated.

    • Hi,

      No it is not a typo, just run the code on your tester to see it in action.

      Gr
      chris

  • hi
    your discussion on SL/TP reference entry price is good.however one thing to point out
    In openbuy() function shouldnt it be like this as you say?
    SL=Ask+spread-10*pip
    TP=Ask+spread+10*pip

    also screenshot shown doesnt show the sell orders execution so i do not know whether it is executing as expected.hope you ll clarify

    • Hi,

      No the buy orders are closed using BID price so you need to use BID as reference for your SL/TP BUY levels.

      Gr
      Chris

Leave a Reply to Nutchapon Namsutto Cancel reply

Your email address will not be published. Required fields are marked *

Short about me

Welcome to my Blog!

My name is Chris, I'm a Dutch engineer with Polish roots. By day I'm an engineer, forex trader and an internet entrepreneur, and by night I'm fighting internet crime;) I hope you will enjoy my website and my free MT4 software. Do not forget to check out my blog.
B.t.w: 'coensio' (Latin) = assessing, assessment, census, estimating, opinion, rating, taxing.

Ads
ArrowHunterEA project
My StrategyQuant Portfolio
StrategyQuant strategy builder:
Follow me on Facebook!

My newsletter

Subscribe to my newsletter

Ads