Trailing stop with the Max Favorable Excursion (MFE)

I already posted an article about a complete trailing stop function in the blog a short time ago. This time I’ll make it with a different logic with the help of the MFE , the Max Favorable Excursion.

What is the MFE?

The MFE is the maximum of gain a trade has met since its inception price. I can also describe it as: the highest price a long trade has encountered or the lowest one for a short trade.

What we plan here is to use the MFE to exit our trades on price retracement:

trailing stop function MFE

Max Favorable Excursion calculation

To save the actual price only if it is lower (for a short trade) or higher (for a long trade), we use the MIN and MAX mathematical function of Probuilder:

That’s it, MFE are saved for future purpose in our trailing stop function.

When not on market, we have to reset the whole variables to not interfere with the new trades that will use them for trailing purpose:

MINPRICE is set to current close, because no price can be lower than 0.


A trailing stop based on MFE

Let’s assume we want the trailing stop function to become active only if the MFE has reached 20 points from the entry price of your current trade.

First declare the parameter variable:

This variable will also be used to determine price retracement from the MFE to close the order.

Next step is to define the price level where to exit the current trade accordingly to the MFE and our trailing stop variable:

The trades will always exit if the price retrace more or equal to 20 points from the current MFE. The “exitprice” levels are moving accordingly to the MFE at each new candlestick.

Now that the “exitprice” variable is set (the price level where to exit trades), we have to deal with the orders exit, so we build STOP orders among the exit price levels:

The complete code of the MFE trailing stop function

If you have to copy/paste something in your own prorealtime code, this is the whole function for doing it:

I also attached to this blog article a “basic” EMA cross automated trading system built with this functionality.


Share this

  1. Adolfo • 06/07/2016 #

    Thanks a lot for this Nicolas! 🙂

  2. Andres • 06/07/2016 #

    Thanks, Nicolas!!!

  3. manel • 06/07/2016 #

    Thanks Nicolas, this indeed looks very useful.
    Could the trailing stop be coded as a % of the price instead of fixed amount of points in order to take into account different absolute price levels across instruments ? eg. retraces 0.5% from the MFE

  4. manel • 06/07/2016 #

    Sorry, I realise that may be a basic question so I’ve tried to code it myself, would this work ? eg:
    trailingstop = 0.5%

    //case SHORT order
    if shortonmarket then
    MINPRICE = MIN(MINPRICE,close) //saving the MFE of the current trade
    if tradeprice(1)-MINPRICE>=trailingstop*tradeprice*pointsize then //if the MFE is higher than the trailingstop then
    priceexit = MINPRICE+trailingstop*tradeprice*pointsize //set the exit price at the MFE + trailing stop price level

    • Nicolas • 06/07/2016 #

      Your code is not adapted, but your idea is good. I’ll try to write another article about it in a few days. Thanks! 😉

  5. manel • 06/07/2016 #

    Thanks for that, look forward to it. I realised that the code does not accept 0.5% so I used 0.005 instead and it seemed to work and some of the backtesting produces nice results but the calculation does not equal 0.5% when exiting so something is obviously not quite correct.

  6. Stef • 06/07/2016 #

    Hi @Nicolas. I think this should read “Max Favorable Excursion.”

    • Nicolas • 06/07/2016 #

      OMG that’s right 🙂 thanks!

  7. Stef • 06/07/2016 #

    Another idea would be to calculate the Maximum Adverse Excursion (MAE) (points/percent) for each trade, to try to determine at which point trades do not seem to recover from. This can then be used to set a catastrophic stop loss. If a trade moves beyond this point, then chances are it will not recover, and it is better to walk away.

    • Nicolas • 06/07/2016 #

      You are right, this is something often calculated while developing automated trading strategy to determine the right stoploss level for each trade. Maybe I’ll do it later, or if someone has the coding abilities to, just do it! 🙂

  8. baaz • 06/07/2016 #

    When I copy the code and use instead of the built in “pTRAILING” function, I don’t see any affect of it. The return is shown as n/a. Do I need to adjust something (thought it was straight copy and paster of above code)?

    • Nicolas • 06/07/2016 #

      Does your strategy gave result before you add the function? Without seeing the whole code, I can’t help much more, sorry..

  9. arcane • 06/07/2016 #

    Hello Nicolas
    I raise the subject.
    You can write the code for the actions, if you please
    If you do not have the time, what are the variables to change.
    Can you give a working track.
    Thank you for your help.

    • Nicolas • 06/07/2016 #

      This code is already compatible with shares. 

  10. Kenneth Kvistad • 06/07/2016 #

     Does this code work almost the same as break evean code.
    When mef is triggerd does the stop move lets say every 20pips in the favorable direction?  

  11. Nacho • 06/07/2016 #

    Buenas tardes, tengo el sistema activado en la versión original en una cuenta demo desde el día 8 de febrero con la versión 10.3 de proreal y no me coinciden los resultados con el Backtest inicial.

  12. Barney • 06/07/2016 #

    If i want to use the code in the following algo should i add the code
    instead of
    // stop and targets
    OBS. Not a good code.
    If i want trailing stop 5 i only change “Trailingstop = 20” to “Trailingstop = 5” or have i to change something else in the code?
    // Definition of code parameters
    DEFPARAM CumulateOrders = False // Cumulating positions deactivated

    // Conditions to enter long positions
    indicator1 = BollingerDown[20](close)
    c1 = (close CROSSES UNDER indicator1)

    IF c1 THEN

    // Conditions to exit long positions
    indicator2 = Average[20](close)
    indicator3 = Average[50](close)
    c2 = (indicator2 CROSSES OVER indicator3)

    IF c2 THEN

    // Conditions to enter short positions
    indicator4 = BollingerUp[20](close)
    c3 = (close CROSSES OVER indicator4)

    IF c3 THEN

    // Conditions to exit short positions
    indicator5 = Average[50](close)
    indicator6 = Average[20](close)
    c4 = (indicator5 CROSSES UNDER indicator6)

    IF c4 THEN

    // Stops and targets


    • Nicolas • 06/07/2016 #

      Yes, this code is made to be “plug an play”, but the “trailingstop” variable is the step from the MFE to set the stop order of the trade, it’s not acting like a usual trailingstop.

  13. Barney • 06/07/2016 #

    Ok, i am going to backtest the MFE code on my algos later today!

  14. Louis S • 340 days ago #

    Great code Nicolas!
    Its working as expected; However, when I checked my backtest results I noticed I got a lot (maybe 10%) of failed orders (Nbr Bars = 0 and Abs Perf = £0.00). 
    I’ve added in the following code — (BarIndex – TradeIndex) >= 1 — but I still get the exact same number of failed orders. Is there a solution for this or do you think this is simply a backtest bug that won’t occur once I  live trade this system?

    • Nicolas • 340 days ago #

      Orders are opened and closed in the same bar, did you checked tick/tick backtest?

    • Louis S • 340 days ago #

      Thanks for getting back to me Nicolas.
      Yes, 10% of orders that are opened, but are then immediately closed in the same bar (see orders I don’t think its connected to tick/tick because if I uncheck ‘tick by tick backtesting’ I get the same ‘0 bars’ orders.  When I remove the MFE Trailing Stop code and add normal stop losses it fixes this issue, but the overall results aren’t as good.

  15. beppe8949 • 81 days ago #

    Ciao Nicolas, sto letteralmente impazzendo! Facendo i vari backtest mi appaiono dei bei risultati, però il problema è che mi chiude la posizione troppo in fretta e non la lascia correre. I valori che ho messo sia come trailing, che come stop che come profit sono stati trovati come più profittevoli dal sistema, però a me sembrano troppo vicini, d’altro canto se aumento questi valori, il drawdown massimo aumenta a dismisura. Come posso fare, riusciresti gentilmente ad aiutarmi?

    • Nicolas • 80 days ago #

      Il problema non è la funzione di trailing stop, ma la tua stessa strategia. Dovresti studiare le tue voci ed uscire.

    • beppe8949 • 80 days ago #

      Perdonami nicolas cosa intendi con studiare le tue voci ed uscire? Mi piacerebbe che le posizioni appunto rimangano aperte per più tempo e non chiuse a 10 punti.. grazie mille! 🙂

  16. DEIO • 67 days ago #

    Hi Nicolas,

    I’m checking my strategy trying to use your trailing stop code (MFE), but I noticed that there is a problem
    regarding the exit order when the trade starts bad and go against me since from the first instant.

    So the question is:

    where is managed the FIRST EXIT ORDER and at which distance from the entry price tradeprice(1) ?

    I ask that because I verified in my strategy that in this case the MFE code doesn’t close the trade (loosing trade)
    at the proper SL.

    So the trade often go from loosing zone to a gaining zone and then ends with a plus, but the trade had to fisnish
    with a SL (minus) !!

    Please let me know if I have been quite clear and I’m curious to read your opinion about my issue.


  17. verdi55 • 65 days ago #

    Here is a code that moves the stop to break-even, after a position has run into positive terrain by a minimum of 20 points :

    StopdistanceBreakeven = 20
    NormalStop = 60

    nb = barindex – tradeindex
    minprice = lowest[nb + 1](Low)
    maxprice = highest[nb + 1](High)

    If longonmarket then
    If maxprice >= positionprice + StopdistanceBreakeven then
    sell at positionprice stop
    sell at positionprice – NormalStop stop

    If shortonmarket then
    If minprice <= positionprice – StopdistanceBreakeven then
    exitshort at positionprice stop
    exitshort at positionprice + NormalStop stop

    The minimum profit distance "StopdistanceBreakeven" (20 points here) is measured from positionprice to the highest high attained since opening of the position (for a long position) or to the lowest low (for a short position). As opposed to the general MFE code above, parameters do not have to be reset at the opening of a new position, and the code will also work after a long position is switched to short in the same bar, and so no "not onmarket" period occurs.

    When the minimum profit distance "StopdistanceBreakeven" has not yet been attained, the stop remains at an initial level defined by "NormalStop " (60 points here).

    • Nicolas • 65 days ago #

      Thanks. I’ll add it as a separate post. I definitely have to find time to code this long awaited code snippets library..

Register or