ProRealCode - Trading & Coding with ProRealTime™
If a strategy uses a long and short criteria and a breakeven- or trailing stop there’s a problem.
The case is that they both need a scenario where there’s no market position, and that “not on market” is used to enter a new position.
If there’s no market position, the breakeven and trailing stop are correctly calculated when a position is entered.
If there’s i.e. a long position and there’s short signal, the position should go the opposite.
Problem is that the breakevenstop and trailingstop are not correctly calculated for the short position, there was never a “not on market” moment.
As a result to have good strategy calculations, you need to enter “not on market” when the position enters the market, but then it ignores the short (opposite) signal and stays long.
Not an obvious flaw, but one which can impact a strategy in a good or bad way.
So my goal is:
use correct values for breakeven and trailing stop, regardless if the position goes the opposite direction, so replace the “not on market” check for the breakeven- and trailingstop with something else.
That “not on market” is not used as criteria to enter a new position, since it skips an valid opposite signal
Any solutions?
// mfe trailing stop
if mfewtrailingstop then
trailingstop = (tradeprice/100)*mwts
if not onmarket then
maxprice = 0
minprice = close
priceexit = 0
endif
if longonmarket then
maxprice = max(maxprice,close)
if maxprice-tradeprice(1)>=trailingstop*pipsize then
priceexit = maxprice-trailingstop*pipsize
endif
endif
if shortonmarket then
minprice = min(minprice,close)
if tradeprice(1)-minprice>=trailingstop*pipsize then
priceexit = minprice+trailingstop*pipsize
endif
endif
endif
if breakevenstop then
if not onmarket then
newsl=0
endif
if longonmarket and close-tradeprice(1)>=((tradeprice/100)*besg)*pipsize then
newsl = tradeprice(1)+((tradeprice/100)*besl)*pipsize
endif
if shortonmarket and tradeprice(1)-close>=((tradeprice/100)*besg)*pipsize then
newsl = tradeprice(1)-((tradeprice/100)*besl)*pipsize
endif
if newsl>0 then
sell at newsl stop
exitshort at newsl stop
endif
endif
if tradetime and not onmarket then
if pclong and mclong and eclong and iclong and trendup then
buy positionsize contract at market
longtradecounter=longtradecounter + 1
tradecounter=tradecounter+1
endif
if pcshort and mcshort and ecshort and icshort and trenddown then
sellshort positionsize contract at market
shorttradecounter=shorttradecounter + 1
tradecounter=tradecounter+1
endif
endif
When On Market is true you should save your TRADEPRICE in a variable each bar, so that as soon as you detect that the current value is different from that of the previous bar and On Market is still true it’s because there’s been a change and you can reset your Trailing Stop/Breakeven settings to the default ones for the new trade.
Not tested but sounds logically correct.
Or something like: (not tested).
changed = onmarket[1] and ( (longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket) )
Thank you both. The easiest try was Nicolas suggestion so I tried that to start with.
Focussed on the trailing stop.
// mfe trailing stop
if mfewtrailingstop then
trailingstop = (tradeprice/100)*mwts
if not onmarket then
maxprice = 0
minprice = close
priceexit = 0
elsif onmarket[1] and ( (longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket) ) then
maxprice = 0
minprice = close
priceexit = 0
endif
if longonmarket then
maxprice = max(maxprice,close)
if maxprice-tradeprice(1)>=trailingstop*pipsize then
priceexit = maxprice-trailingstop*pipsize
endif
endif
if shortonmarket then
minprice = min(minprice,close)
if tradeprice(1)-minprice>=trailingstop*pipsize then
priceexit = minprice+trailingstop*pipsize
endif
endif
endif
In de added suggestion, I tried with onmarket[1] or onmarket[0], or without onmarket but that made no difference
tried with elsif, and with new if command no difference
I will try to replicate the problem with a clean test code and post later.
Here’s a clean code.
To test the differences optimize tss and bes with 0 and 1 and see the differences with the added suggestion from Nicolas.
It has no effect on breakeven.
DEFPARAM CumulateOrders = false
ONCE enabletrailingstop=1
ONCE enablebreakevenstop=1
ONCE TSsuggestion=tss
ONCE BEsuggestion=bes
SL = 1.50 //stoploss
TS = 0.75 //trailing stop
besg = 0.50 //breakeven minimum gain
besl = 0 //breakeven stoploss
// reset at start
if intradaybarindex = 0 then
longtradecounter = 0
shorttradecounter = 0
endif
pclong = longtradecounter < 1
pcshort = shorttradecounter < 1
SMA5 = Average[5](close)
SMA10 = Average[10](close)
STOCH = Stochastic[14,3](close)
indicator4 = Average[5](STOCH)
RSIind = RSI[14](close)
// Conditions to enter long positions
l1 = (SMA5 CROSSES OVER SMA10)
l2 = (STOCH - indicator4 >10)//Stochastic upward momentum
l3 = (RSIind > 45)//RSI upward momentum
l5 = (average[10](STOCH)<45)// Stochastic not yet overbought
//Conditions to enter short
s1 = (SMA5 CROSSES UNDER SMA10)
s2 = (STOCH - indicator4 <-10)//Stochastic downward momentum
s3 = (RSIind < 55)//RSI downward momentum
s5 = (average[10](STOCH)>55)//Stochastic not yet oversold
IF pclong and l1 AND l2 AND l3 AND l5 tHEN
buy 1 CONTRACT AT MARKET
longtradecounter=longtradecounter + 1
ENDIF
IF pcshort and s1 AND s2 AND s3 AND s5 THEN
sellshort 1 CONTRACT AT MARKET
shorttradecounter=shorttradecounter + 1
ENDIF
// break even stop
if enablebreakevenstop then
if not onmarket then
newsl=0
endif
if BEsuggestion then
if ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
newsl=0
endif
endif
if longonmarket and close-tradeprice(1)>=((tradeprice/100)*besg)*pipsize then
newsl = tradeprice(1)+((tradeprice/100)*besl)*pipsize
endif
if shortonmarket and tradeprice(1)-close>=((tradeprice/100)*besg)*pipsize then
newsl = tradeprice(1)-((tradeprice/100)*besl)*pipsize
endif
if newsl>0 then
sell at newsl stop
exitshort at newsl stop
endif
endif
//trailing stop
if enabletrailingstop then
ts=0.35
trailingstop = (tradeprice/100)*ts
//resetting variables when no trades are on market
if not onmarket then
MAXPRICE = 0
MINPRICE = close
priceexit = 0
endif
if TSsuggestion=1 then
if ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
MAXPRICE = 0
MINPRICE = close
priceexit = 0
endif
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
endif
SET STOP %LOSS SL
graphonprice priceexit
graph 0 coloured(300,0,0) as "zeroline"
graph (positionperf*100)coloured(0,0,0,255) as "positionperformance"
Since you use market orders, you already know that you are on market, so why not flagging a variable when you enter an order. In this case, if new conditions are met to put a contrarian order on market, you can reset the breakeven variables at that point of the code.
Bear in mind that code is read from top to bottom, conditions testing in the right order is crucial to solve your problem.
I made everything visual. Didn’t work on the flag yet. Maybe I’am missing something obvious.
//tested on dax
// The goal is use notonmarket=0 with correct TS and BE values
// If useNOTonmarket=1 then everything is correct
//i.e. dax 10 min
//everything 1, exept ONCE useNOTonmarket = 0
//problem example 23 january 2019 16:20
DEFPARAM CumulateOrders = false
ONCE enableSL = 1 // stop loss
ONCE enablePT = 1 // profit target
ONCE enableBE = 1 // breakeven stop
ONCE enableTS = 1 // trailing stop
ONCE displaySL = 1 // stop loss
ONCE displayPT = 1 // profit target
ONCE displayBE = 1 // breakeven stop
ONCE displayTS = 1 // trailing stop
ONCE TSsuggestion=1 //optimize 0 and 1 to see difference
ONCE BEsuggestion=1 //optimize 0 and 1 to see difference
//test what's it is all about.
ONCE useNOTonmarket = 0 //with entry criteria
sl = 2.00 // % stop loss
pt = 1.50 // % profit target
ts = 0.50 // % trailing stop
besg = 0.25 // % break even stop gain
besl = 0.00 // % break even stop level
// reset at start
if intradaybarindex = 0 then
longtradecounter = 0
shorttradecounter = 0
endif
pclong = longtradecounter < 1
pcshort = shorttradecounter < 1
SMA5 = Average[5](close)
SMA10 = Average[10](close)
STOCH = Stochastic[14,3](close)
indicator4 = Average[5](STOCH)
RSIind = RSI[14](close)
// Conditions to enter long positions
l1 = (SMA5 CROSSES OVER SMA10)
l2 = (STOCH - indicator4 >10)//Stochastic upward momentum
l3 = (RSIind > 45)//RSI upward momentum
l5 = (average[10](STOCH)<45)// Stochastic not yet overbought
//Conditions to enter short
s1 = (SMA5 CROSSES UNDER SMA10)
s2 = (STOCH - indicator4 <-10)//Stochastic downward momentum
s3 = (RSIind < 55)//RSI downward momentum
s5 = (average[10](STOCH)>55)//Stochastic not yet oversold
if useNOTonmarket=1 then
if not onmarket then
IF pclong and l1 AND l2 AND l3 AND l5 tHEN
buy 1 CONTRACT AT MARKET
longtradecounter=longtradecounter + 1
ENDIF
IF pcshort and s1 AND s2 AND s3 AND s5 THEN
sellshort 1 CONTRACT AT MARKET
shorttradecounter=shorttradecounter + 1
ENDIF
endif
endif
if useNOTonmarket=0 then
IF pclong and l1 AND l2 AND l3 AND l5 tHEN
buy 1 CONTRACT AT MARKET
longtradecounter=longtradecounter + 1
ENDIF
IF pcshort and s1 AND s2 AND s3 AND s5 THEN
sellshort 1 CONTRACT AT MARKET
shorttradecounter=shorttradecounter + 1
ENDIF
endif
// trailing stop
if enableTS then
trailingstop = (tradeprice/100)*ts
if not onmarket then
MAXPRICE = 0
MINPRICE = close
priceexit = 0
endif
if TSsuggestion then
if onmarket[1] and ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
MAXPRICE = 0
MINPRICE = close
priceexit = 0
endif
endif
if shortonmarket then
MINPRICE = MIN(MINPRICE,close)
if tradeprice(1)-MINPRICE>=trailingstop*pointsize then
priceexit = MINPRICE+trailingstop*pointsize
endif
endif
if longonmarket then
MAXPRICE = MAX(MAXPRICE,close)
if MAXPRICE-tradeprice(1)>=trailingstop*pointsize then
priceexit = MAXPRICE-trailingstop*pointsize
endif
endif
if onmarket and priceexit>0 then
EXITSHORT AT priceexit STOP
SELL AT priceexit STOP
endif
if displayTS then
graphonprice priceexit COLOURED(0,0,255,255) as "trailingstop"
endif
endif
// break even stop
if enableBE then
if not onmarket then
newsl=0
endif
if BEsuggestion then
if onmarket[1] and ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
newsl=0
endif
endif
if longonmarket and close-tradeprice(1)>=((tradeprice/100)*besg)*pipsize then
newsl = tradeprice(1)+((tradeprice/100)*besl)*pipsize
endif
if shortonmarket and tradeprice(1)-close>=((tradeprice/100)*besg)*pipsize then
newsl = tradeprice(1)-((tradeprice/100)*besl)*pipsize
endif
if newsl>0 then
sell at newsl stop
exitshort at newsl stop
endif
if displayBE then
graphonprice newsl COLOURED(244,102,27,255) as "breakevenstop"
endif
endif
// to set & display stop loss
if enableSL then
set stop %loss sl
if displaySL then
if not onmarket then
sloss=0
elsif onmarket[1] and ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
sloss=0
endif
if onmarket then
if longonmarket then
sloss=tradeprice(1)-((tradeprice(1)*sl)/100)*pointsize
endif
if shortonmarket then
sloss=tradeprice(1)+((tradeprice(1)*sl)/100)*pointsize
endif
endif
graphonprice sloss COLOURED(255,0,0,255) as "stoploss"
endif
endif
// to set & display profittarget
if enablePT then
set target %profit pt
if displayPT then
if not onmarket then
ptarget=0
elsif onmarket[1] and ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
ptarget=0
endif
if onmarket then
if longonmarket then
ptarget=tradeprice(1)+((tradeprice(1)*pt)/100)*pointsize
endif
if shortonmarket then
ptarget=tradeprice(1)-((tradeprice(1)*pt)/100)*pointsize
endif
endif
graphonprice ptarget COLOURED(121,141,35,255) as "profittarget"
endif
endif
//graph 0 coloured(300,0,0) as "zeroline"
graph (positionperf*100)coloured(0,0,0,255) as "positionperformance"
It seems that adding the code from Nicolas and also splitsing the newsl and priceexit exits for long and short criteria worked.
Thanks for the tips.
Thank you Paul, do you have the complete code to share here, in order to have it for future reference please?
Here’s my final test code on the dax with working breakeven- and trailing stops in every scenario.
It does matter that a trailing stop code is above the breakeven code.
// test trailingstop and breakeven on the dax
defparam cumulateorders = false
once enableSL = 1 // stop loss
once enablePT = 1 // profit target
once enableTS = 1 // trailing stop
once enableBE = 1 // breakeven stop
once displaySL = 1 // stop loss
once displayPT = 1 // profit target
once displayTS = 1 // trailing stop
once displayBE = 1 // breakeven stop
SL = 0.75 // % stop loss
PT = 1.00 // % profit target
TS = 0.35 // % trailing stop
BESG = 0.25 // % break even stop gain
BESL = 0.00 // % break even stop level
// reset at start
if intradaybarindex=0 then
longtradecounter=0
shorttradecounter=0
endif
pclong= longtradecounter<1
pcshort = shorttradecounter<1
shortma = average[25](close)
longma = average[50](close)
// conditions to enter long positions
l1 = (shortma crosses over longma)
// conditions to enter short
s1 = (shortma crosses under longma)
if pclong and l1 then
buy 1 contract at market
longtradecounter=longtradecounter+1
endif
if pcshort and s1 then
sellshort 1 contract at market
shorttradecounter=shorttradecounter+1
endif
// trailing stop
if enableTS then
trailingstop = (tradeprice/100)*TS
if not onmarket then
maxprice=0
minprice=close
priceexit=0
endif
if ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
maxprice=0
minprice=close
priceexit=0
endif
if longonmarket then
maxprice=max(maxprice,close)
if maxprice-tradeprice(1)>=trailingstop*pointsize then
priceexit=maxprice-trailingstop*pointsize
endif
endif
if shortonmarket then
minprice=min(minprice,close)
if tradeprice(1)-minprice>=trailingstop*pointsize then
priceexit=minprice+trailingstop*pointsize
endif
endif
if longonmarket and priceexit>0 then
sell at priceexit stop
endif
if shortonmarket and priceexit>0 then
exitshort at priceexit stop
endif
if displayTS then
graphonprice priceexit coloured(0,0,255,255) as "trailingstop"
endif
endif
// break even stop
if enableBE then
if not onmarket then
newsl=0
endif
if ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
newsl=0
endif
if longonmarket then
if close-tradeprice(1)>=((tradeprice/100)*BESG)*pipsize then
newsl=tradeprice(1)+((tradeprice/100)*BESL)*pipsize
endif
endif
if shortonmarket then
if tradeprice(1)-close>=((tradeprice/100)*BESG)*pipsize then
newsl=tradeprice(1)-((tradeprice/100)*BESL)*pipsize
endif
endif
if longonmarket and newsl>0 then
sell at newsl stop
endif
if shortonmarket and newsl>0 then
exitshort at newsl stop
endif
if displayBE then
graphonprice newsl coloured(244,102,27,255) as "breakevenstop"
endif
endif
// to set & display profittarget
if enablePT then
set target %profit PT
if displaypt then
if not onmarket then
ptarget=0
elsif ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
ptarget=0
endif
if onmarket then
if longonmarket then
ptarget=tradeprice(1)+((tradeprice(1)*PT)/100)*pointsize
endif
if shortonmarket then
ptarget=tradeprice(1)-((tradeprice(1)*PT)/100)*pointsize
endif
endif
graphonprice ptarget coloured(121,141,35,255) as "profittarget"
endif
endif
// to set & display stoploss
if enableSL then
set stop %loss SL
if displaysl then
if not onmarket then
sloss=0
elsif ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
sloss=0
endif
if onmarket then
if longonmarket then
sloss=tradeprice(1)-((tradeprice(1)*SL)/100)*pointsize
endif
if shortonmarket then
sloss=tradeprice(1)+((tradeprice(1)*SL)/100)*pointsize
endif
endif
graphonprice sloss coloured(255,0,0,255) as "stoploss"
endif
endif
graph (positionperf*100)coloured(0,0,0,255) as "positionperformance"
Try this:
// test trailingstop and breakeven on the dax
defparam cumulateorders = false
once enableSL = 1 // stop loss
once enablePT = 1 // profit target
once enableTS = 1 // trailing stop
once enableBE = 1 // breakeven stop
//once displaySL = 1 // stop loss
//once displayPT = 1 // profit target
//once displayTS = 1 // trailing stop
//once displayBE = 1 // breakeven stop
SL = 0.75 // % stop loss
PT = 1.00 // % profit target
TS = 0.35 // % trailing stop
BESG = 0.25 // % break even stop gain
BESL = 0.00 // % break even stop level
// reset at start
if intradaybarindex=0 then
longtradecounter=0
shorttradecounter=0
endif
pclong= longtradecounter<1
pcshort = shorttradecounter<1
shortma = average[25](close)
longma = average[50](close)
// conditions to enter long positions
l1 = (shortma crosses over longma)
// conditions to enter short
s1 = (shortma crosses under longma)
if pclong and l1 then
buy 1 contract at market
longtradecounter=longtradecounter+1
endif
if pcshort and s1 then
sellshort 1 contract at market
shorttradecounter=shorttradecounter+1
endif
// trailing stop
if enableTS then
trailingstop = (tradeprice/100)*TS
if not onmarket then
maxprice=0
minprice=close
priceexit=0
endif
if ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
maxprice=0
minprice=close
priceexit=0
endif
if longonmarket then
maxprice=max(maxprice,close)
if maxprice-tradeprice(1)>=trailingstop*pointsize then
priceexit=maxprice-trailingstop*pointsize
endif
endif
if shortonmarket then
minprice=min(minprice,close)
if tradeprice(1)-minprice>=trailingstop*pointsize then
priceexit=minprice+trailingstop*pointsize
endif
endif
if longonmarket and priceexit>0 then
sell at priceexit stop
endif
if shortonmarket and priceexit>0 then
exitshort at priceexit stop
endif
//if displayTS then
//graphonprice priceexit coloured(0,0,255,255) as "trailingstop"
//endif
endif
// break even stop
if enableBE then
if not onmarket then
newsl=0
endif
if ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
newsl=0
endif
if longonmarket then
if close-tradeprice(1)>=((tradeprice/100)*BESG)*pipsize then
newsl=tradeprice(1)+((tradeprice/100)*BESL)*pipsize
endif
endif
if shortonmarket then
if tradeprice(1)-close>=((tradeprice/100)*BESG)*pipsize then
newsl=tradeprice(1)-((tradeprice/100)*BESL)*pipsize
endif
endif
if longonmarket and newsl>0 then
sell at newsl stop
endif
if shortonmarket and newsl>0 then
exitshort at newsl stop
endif
//if displayBE then
//graphonprice newsl coloured(244,102,27,255) as "breakevenstop"
//endif
endif
// to set & display profittarget
if enablePT then
set target %profit PT
//if displaypt then
//if not onmarket then
//ptarget=0
//elsif ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
//ptarget=0
//endif
//if onmarket then
//if longonmarket then
//ptarget=tradeprice(1)+((tradeprice(1)*PT)/100)*pointsize
//endif
//if shortonmarket then
//ptarget=tradeprice(1)-((tradeprice(1)*PT)/100)*pointsize
//endif
//endif
//graphonprice ptarget coloured(121,141,35,255) as "profittarget"
//endif
endif
// to set & display stoploss
if enableSL then
set stop %loss SL
//if displaysl then
//if not onmarket then
//sloss=0
//elsif ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
//sloss=0
//endif
//if onmarket then
//if longonmarket then
//sloss=tradeprice(1)-((tradeprice(1)*SL)/100)*pointsize
//endif
//if shortonmarket then
//sloss=tradeprice(1)+((tradeprice(1)*SL)/100)*pointsize
//endif
//endif
//graphonprice sloss coloured(255,0,0,255) as "stoploss"
//endif
endif
//graph (positionperf*100)coloured(0,0,0,255) as "positionperformance"
You can’t exclude graph by //. But you can set display to 0 for each one to disable lines or try Vonasi suggestion.
The lines are a bit annoying since they start at the bottom as vertical lines. As alternative you can set them to points.
haha spot on Vonasi, works now, thank you!
I had tried same / similar. but I can see now I was // out 3 lines too many in each code section with a GRAPH function.
Also I’ve now noticed that I was optimising over 10k bars only!
I was watching a good film at same time, but maybe I need to get my glasses from Australia! 🙂
Actually below are what I wear on the computer when my eyes are tired! Pinhole glasses (£4 or £1 from china!) ,,, think physics in school and pinhole cameras and that’s how they work! Well worth checking out for anybody who’s eyesight is not what it used to be!
Breakeven- and trailing stop problem
This topic contains 16 replies,
has 5 voices, and was last updated by Vonasi
7 years ago.
| Forum: | ProOrder: Automated Strategies & Backtesting |
| Language: | English |
| Started: | 01/30/2019 |
| Status: | Active |
| Attachments: | 7 files |
The information collected on this form is stored in a computer file by ProRealCode to create and access your ProRealCode profile. This data is kept in a secure database for the duration of the member's membership. They will be kept as long as you use our services and will be automatically deleted after 3 years of inactivity. Your personal data is used to create your private profile on ProRealCode. This data is maintained by SAS ProRealCode, 407 rue Freycinet, 59151 Arleux, France. If you subscribe to our newsletters, your email address is provided to our service provider "MailChimp" located in the United States, with whom we have signed a confidentiality agreement. This company is also compliant with the EU/Swiss Privacy Shield, and the GDPR. For any request for correction or deletion concerning your data, you can directly contact the ProRealCode team by email at privacy@prorealcode.com If you would like to lodge a complaint regarding the use of your personal data, you can contact your data protection supervisory authority.