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:
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:
1 2 3 4 5 6 7 8 9 10 |
//case SHORT order if shortonmarket then MINPRICE = MIN(MINPRICE,close) //saving the MFE of the current trade endif //case LONG order if longonmarket then MAXPRICE = MAX(MAXPRICE,close) //saving the MFE of the current trade endif |
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:
1 2 3 4 5 |
//resetting variables when no trades are on market if not onmarket then MAXPRICE = 0 MINPRICE = close endif |
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:
1 2 |
//trailing stop trailingstop = 20 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//case SHORT order if shortonmarket then MINPRICE = MIN(MINPRICE,close) //saving the MFE of the current trade if tradeprice(1)-MINPRICE>=trailingstop*pointsize then //if the MFE is higher than the trailingstop then priceexit = MINPRICE+trailingstop*pointsize //set the exit price at the MFE + trailing stop price level endif endif //case LONG order if longonmarket then MAXPRICE = MAX(MAXPRICE,close) //saving the MFE of the current trade if MAXPRICE-tradeprice(1)>=trailingstop*pointsize then //if the MFE is higher than the trailingstop then priceexit = MAXPRICE-trailingstop*pointsize //set the exit price at the MFE - trailing stop price level endif endif |
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:
1 2 3 4 5 |
//exit on trailing stop price levels if onmarket and priceexit>0 then EXITSHORT AT priceexit STOP SELL AT priceexit STOP endif |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
//trailing stop trailingstop = 20 //resetting variables when no trades are on market if not onmarket then MAXPRICE = 0 MINPRICE = close priceexit = 0 endif //case SHORT order if shortonmarket then MINPRICE = MIN(MINPRICE,close) //saving the MFE of the current trade if tradeprice(1)-MINPRICE>=trailingstop*pointsize then //if the MFE is higher than the trailingstop then priceexit = MINPRICE+trailingstop*pointsize //set the exit price at the MFE + trailing stop price level endif endif //case LONG order if longonmarket then MAXPRICE = MAX(MAXPRICE,close) //saving the MFE of the current trade if MAXPRICE-tradeprice(1)>=trailingstop*pointsize then //if the MFE is higher than the trailingstop then priceexit = MAXPRICE-trailingstop*pointsize //set the exit price at the MFE - trailing stop price level endif endif //exit on trailing stop price levels if onmarket and priceexit>0 then EXITSHORT AT priceexit STOP SELL AT priceexit STOP endif |
I also attached to this blog article a “basic” EMA cross automated trading system built with this functionality.
Thanks a lot for this Nicolas! 🙂
Thanks, Nicolas!!!
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
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
endif
endif
Your code is not adapted, but your idea is good. I’ll try to write another article about it in a few days. Thanks! 😉
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.
Hi @Nicolas. I think this should read “Max Favorable Excursion.”
OMG that’s right 🙂 thanks!
@Nicolas,
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.
Stef
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! 🙂
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)?
Thanks.
Does your strategy gave result before you add the function? Without seeing the whole code, I can’t help much more, sorry..
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.
This code is already compatible with shares.
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?
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.
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
BUY 2 CONTRACT AT MARKET
ENDIF
// Conditions to exit long positions
indicator2 = Average[20](close)
indicator3 = Average[50](close)
c2 = (indicator2 CROSSES OVER indicator3)
IF c2 THEN
SELL AT MARKET
ENDIF
// Conditions to enter short positions
indicator4 = BollingerUp[20](close)
c3 = (close CROSSES OVER indicator4)
IF c3 THEN
SELLSHORT 2 CONTRACT AT MARKET
ENDIF
// Conditions to exit short positions
indicator5 = Average[50](close)
indicator6 = Average[20](close)
c4 = (indicator5 CROSSES UNDER indicator6)
IF c4 THEN
EXITSHORT AT MARKET
ENDIF
// Stops and targets
SET STOP pLOSS 3
SET TARGET pPROFIT 4
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.
Ok, i am going to backtest the MFE code on my algos later today!
Thanks
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?
Thanks
Orders are opened and closed in the same bar, did you checked tick/tick backtest?
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 https://postimg.org/image/418g9qmfz/). 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.
@Nicolas Is tradeprice(1) the trade price of the current trade or the previous trade?
At the same time, the current one and the previous one.
The last opened one, to be more clear.
Yeah thanks, I used Graph to be clear … it was confusing me with the (1) but tradeprice(1) is the same as writing tradeprice … I just hope I remember this time! 🙂 Cheers
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?
Il problema non è la funzione di trailing stop, ma la tua stessa strategia. Dovresti studiare le tue voci ed uscire.
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! 🙂
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.
thx
bye
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
else
sell at positionprice – NormalStop stop
endif
endif
If shortonmarket then
If minprice <= positionprice – StopdistanceBreakeven then
exitshort at positionprice stop
else
exitshort at positionprice + NormalStop stop
endif
endif
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).
Thanks. I’ll add it as a separate post. I definitely have to find time to code this long awaited code snippets library..
I am searching for a trailing stop Code. I tried to start this one on my demo-account, but the trades doesn’t start. The orders get denied (unexpected error). I don’t know why. Has somebody an idea? Thanks 😉
The code I tested was:
BUY 1 LOT AT MARKET
//trailing stop
trailingstop = 20
//resetting variables when no trades are on market
if not onmarket then
MAXPRICE = 0
MINPRICE = close
priceexit = 0
endif
//case SHORT order
if shortonmarket then
MINPRICE = MIN(MINPRICE,close) //saving the MFE of the current trade
if tradeprice(1)-MINPRICE>=trailingstop*pointsize then //if the MFE is higher than the trailingstop then
priceexit = MINPRICE+trailingstop*pointsize //set the exit price at the MFE + trailing stop price level
endif
endif
//case LONG order
if longonmarket then
MAXPRICE = MAX(MAXPRICE,close) //saving the MFE of the current trade
if MAXPRICE-tradeprice(1)>=trailingstop*pointsize then //if the MFE is higher than the trailingstop then
priceexit = MAXPRICE-trailingstop*pointsize //set the exit price at the MFE – trailing stop price level
endif
endif
//exit on trailing stop price levels
if onmarket and priceexit>0 then
EXITSHORT AT priceexit STOP
SELL AT priceexit STOP
endif
Nicolas, I did you ever adapt this MFE trailing code for %Trailing? I have been searching but cannot find it. I replaced Pointsize with TypicalPrice but get an error message when trying to set “TrailingStop = Set Stop %Trailing X”.
Please advise and as always, thanks for your help.
Why not replace this: trailingstop = 20 , but with a percentage of the price?!
trailingstop = close*0.01 //a one percent trailingstop
Thanks Nicolas. I had it close but what you say makes more sense.
Cheers, and welcome to 2021.
Stuart
Hi Nicolas, thanks for the great code!
Hi Nicolas, thanks for the great code!
I used it for backtesting a script where I had an initial trailing stop loss of 200 set, and then wanted your MFE trailing stop loss to run at 130 points from MFE once the trade had broken even (please see attached code)
This worked in backtesting, but I have tried running it live, and it only uses the initial trailing SL of 200, and ignores the MFE code.
I’m basically looking to have 200 point trail which moves with the trade, which switches to 130 point trail once the trade has broke even.
Thanks in advance
To clarify- it would use the 200tTSL until it reached 130 points in profit at which point it would change to 130TSL with the TSL at break even (£0) at that point.