ProRealCode - Trading & Coding with ProRealTime™
Yes, you have to.
One more thing: to use high/low instead of close, is this right?
IF LongOnMarket THEN
q1 = PositionPrice + ((high - PositionPrice) * ProfitPerCent) //calculate new SL
SellPriceX = max(max(SellPriceX,SellPrice),q1)
SellPrice = max(max(SellPriceX,SellPrice),PositionPrice + (y1 * pipsize)) //set exit price to whatever grants greater profits, comopared to the previous one
ELSIF ShortOnMarket THEN
r1 = ((PositionPrice - low) * ProfitPerCent) //calculate new SL
Yes, that’s correct, but you’ll have to replace CLOSE also at lines 44 (X1) and 56 (X2).
You have to keep CLOSE, instead, after line 68 when it deals with minimum distance required by the broker, which must ALWAYS be computed from current price (CLOSE).
To make it available to anyone, I am posting the code updated with the choice of using either CLOSE or HIGH/LOW (line 1):
ONCE UseCLOSE = 1 //1=use CLOSE, 0=use High/Low
SrcH = close //defaults to CLOSE
SrcL = close //defaults to CLOSE
IF UseCLOSE = 0 THEN
SrcH = high
SrcL = low
ENDIF
DirectionSwitch = (LongOnMarket AND ShortOnMarket[1]) OR (LongOnMarket[1] AND ShortOnMarket) //True when there's been a change in the direction (likely to be due to a Stop & Reverse)
IF Not OnMarket OR DirectionSwitch THEN
//
// when NOT OnMarket or thare's been a change in direction, reset values to their default settings
//
TrailStart = 30 //30 Start trailing profits from this point
BasePerCent = 0.200 //20.0% Profit percentage to keep when setting BerakEven
StepSize = 10 //10 Pip chunks to increase Percentage
PerCentInc = 0.100 //10.0% PerCent increment after each StepSize chunk
RoundTO = -0.5 //-0.5 rounds always to Lower integer, +0.4 rounds always to Higher integer, 0 defaults PRT behaviour
PriceDistance = 7 * pipsize //7 minimun distance from current price
y1 = 0 //reset to 0
y2 = 0 //reset to 0
ProfitPerCent = BasePerCent //reset to desired default value
PositionCount = 0
SellPrice = 0
ExitPrice = 9999999
ELSE
//------------------------------------------------------
// --- Update Stop Loss after accumulating new positions
//------------------------------------------------------
PositionCount = max(PositionCount,abs(CountOfPosition))
//
// update Stop Loss only when PositionCount has changed (actually when increased, we don't move it if there's been some positions exited)
//
IF PositionCount <> PositionCount[1] AND (ExitPrice + SellPrice) <> 9999999 THEN //go on only if Trailing Stop had already started trailing
IF LongOnMarket THEN
q1 = PositionPrice + ((SrcH - PositionPrice) * ProfitPerCent) //calculate new SL
SellPriceX = max(max(SellPriceX,SellPrice),q1)
SellPrice = max(max(SellPriceX,SellPrice),PositionPrice + (y1 * pipsize)) //set exit price to whatever grants greater profits, comopared to the previous one
ELSIF ShortOnMarket THEN
r1 = ((PositionPrice - SrcL) * ProfitPerCent) //calculate new SL
ExitPriceX = min(min(ExitPriceX,ExitPrice),r1)
ExitPrice = min(min(ExitPriceX,ExitPrice),PositionPrice - (y2 * pipsize)) //set exit price to whatever grants greater profits, comopared to the previous one
ENDIF
ENDIF
// --- Update END
ENDIF
//
IF LongOnMarket AND SrcH > (TradePrice + (y1 * pipsize)) THEN //LONG positions
//
// compute the value of the Percentage of profits, if any, to lock in for LONG trades
//
x1 = (SrcH - tradeprice) / pipsize //convert price to pips
IF x1 >= TrailStart THEN // go ahead only if N+ pips
Diff1 = abs(TrailStart - x1) //difference from current profit and TrailStart
Chunks1 = max(0,round((Diff1 / StepSize) + RoundTO)) //number of STEPSIZE chunks
ProfitPerCent = BasePerCent + (BasePerCent * (Chunks1 * PerCentInc)) //compute new size of ProfitPerCent
ProfitPerCent = max(ProfitPerCent[1],min(100,ProfitPerCent)) //make sure ProfitPerCent doess not exceed 100%
y1 = max(x1 * ProfitPerCent, y1) //y1 = % of max profit
ENDIF
ELSIF ShortOnMarket AND SrcL < (TradePrice - (y2 * pipsize)) THEN //SHORT positions
//
// compute the value of the Percentage of profits, if any, to lock in for SHORT trades
//
x2 = (tradeprice - SrcL) / pipsize //convert price to pips
IF x2 >= TrailStart THEN // go ahead only if N+ pips
Diff2 = abs(TrailStart - x2) //difference from current profit and TrailStart
Chunks2 = max(0,round((Diff2 / StepSize) + RoundTO)) //number of STEPSIZE chunks
ProfitPerCent = BasePerCent + (BasePerCent * (Chunks2 * PerCentInc)) //compute new size of ProfitPerCent
ProfitPerCent = max(ProfitPerCent[1],min(100,ProfitPerCent)) //make sure ProfitPerCent doess not exceed 100%
y2 = max(x2 * ProfitPerCent, y2) //y2 = % of max profit
ENDIF
ENDIF
//------------------------------------------------------------------------------
// manage actual Exit, if needed
//------------------------------------------------------------------------------
IF y1 THEN //Place pending STOP order when y1 > 0 (LONG positions)
SellPrice = max(SellPrice,Tradeprice + (y1 * pipsize)) //convert pips to price
//
// check the minimun distance between ExitPrice and current price
//
IF abs(close - SellPrice) > PriceDistance THEN
//
// place either a LIMIT or STOP pending order according to current price positioning
//
IF close >= SellPrice THEN
SELL AT SellPrice STOP
ELSE
SELL AT SellPrice LIMIT
ENDIF
ELSE
//
//sell AT MARKET when EXITPRICE does not meet the broker's minimun distance from current price
//
SELL AT Market
ENDIF
ENDIF
IF y2 THEN //Place pending STOP order when y2 > 0 (SHORT positions)
ExitPrice = min(ExitPrice,Tradeprice - (y2 * pipsize)) //convert pips to price
//
// check the minimun distance between ExitPrice and current price
//
IF abs(close - ExitPrice) > PriceDistance THEN
//
// place either a LIMIT or STOP pending order according to current price positioning
//
IF close <= ExitPrice THEN
EXITSHORT AT ExitPrice STOP
ELSE
EXITSHORT AT ExitPrice LIMIT
ENDIF
ELSE
//
//ExitShort AT MARKET when EXITPRICE does not meet the broker's minimun distance from current price
//
EXITSHORT AT Market
ENDIF
ENDIF
Sorry guys, I had to change the above code:
I am also attaching the ITF file.
//------------------------------------------------------------------------------------------------------------------------------------------------
ONCE UseCLOSE = 1 //1=use CLOSE, 0=use High/Low
srcH = close //defaults to CLOSE
srcL = close //defaults to CLOSE
IF UseCLOSE = 0 THEN
srcH = high
srcL = low
ENDIF
DirectionSwitch = (LongOnMarket AND ShortOnMarket[1]) OR (LongOnMarket[1] AND ShortOnMarket) //True when there's been a change in the direction (likely to be due to a Stop & Reverse)
IF Not OnMarket OR DirectionSwitch THEN
//
// when NOT OnMarket or thare's been a change in direction, reset values to their default settings
//
TrailStart = 30 //30 Start trailing profits from this point
BasePerCent = 0.200 //20.0% Profit percentage to keep when setting BerakEven
StepSize = 10 //10 Pip chunks to increase Percentage
PerCentInc = 0.100 //10.0% PerCent increment after each StepSize chunk
RoundTO = -0.5 //-0.5 rounds always to Lower integer, +0.4 rounds always to Higher integer, 0 defaults PRT behaviour
PriceDistance = 7 * pipsize //7 minimun distance from current price
y1 = 0 //reset to 0
y2 = 0 //reset to 0
ProfitPerCent = BasePerCent //reset to desired default value
//PositionCount = 0
SellPrice = 0
ExitPrice = 9999999
ELSE
//------------------------------------------------------
// --- Update Stop Loss after accumulating new positions
//------------------------------------------------------
//PositionCount = max(PositionCount,abs(CountOfPosition))
//
// update Stop Loss only when PositionPrice has changed (actually when increased, we don't move it if there's been some positions exited)
//
//IF PositionCount <> PositionCount[1] AND (ExitPrice + SellPrice)<>9999999 THEN //go on only if Trailing Stop had already started trailing
IF PositionPrice <> PositionPrice[1] AND (ExitPrice + SellPrice) <> 9999999 THEN //go on only if Trailing Stop had already started trailing
IF LongOnMarket THEN
q1 = PositionPrice + ((srcH - PositionPrice) * ProfitPerCent) //calculate new SL
SellPriceX = max(max(SellPriceX,SellPrice),q1)
SellPrice = max(max(SellPriceX,SellPrice),PositionPrice + (y1 * pipsize)) //set exit price to whatever grants greater profits, comopared to the previous one
ELSIF ShortOnMarket THEN
r1 = ((PositionPrice - srcL) * ProfitPerCent) //calculate new SL
ExitPriceX = min(min(ExitPriceX,ExitPrice),r1)
ExitPrice = min(min(ExitPriceX,ExitPrice),PositionPrice - (y2 * pipsize)) //set exit price to whatever grants greater profits, comopared to the previous one
ENDIF
ENDIF
// --- Update END
ENDIF
//
IF LongOnMarket AND srcH > (PositionPrice + (y1 * pipsize)) THEN //LONG positions
//
// compute the value of the Percentage of profits, if any, to lock in for LONG trades
//
x1 = (srcH - PositionPrice) / pipsize //convert price to pips
IF x1 >= TrailStart THEN // go ahead only if N+ pips
Diff1 = abs(TrailStart - x1) //difference from current profit and TrailStart
Chunks1 = max(0,round((Diff1 / StepSize) + RoundTO)) //number of STEPSIZE chunks
ProfitPerCent = BasePerCent + (BasePerCent * (Chunks1 * PerCentInc)) //compute new size of ProfitPerCent
ProfitPerCent = max(ProfitPerCent[1],min(100,ProfitPerCent)) //make sure ProfitPerCent doess not exceed 100%
y1 = max(x1 * ProfitPerCent, y1) //y1 = % of max profit
ENDIF
ELSIF ShortOnMarket AND srcL < (PositionPrice - (y2 * pipsize)) THEN //SHORT positions
//
// compute the value of the Percentage of profits, if any, to lock in for SHORT trades
//
x2 = (PositionPrice - srcL) / pipsize //convert price to pips
IF x2 >= TrailStart THEN // go ahead only if N+ pips
Diff2 = abs(TrailStart - x2) //difference from current profit and TrailStart
Chunks2 = max(0,round((Diff2 / StepSize) + RoundTO)) //number of STEPSIZE chunks
ProfitPerCent = BasePerCent + (BasePerCent * (Chunks2 * PerCentInc)) //compute new size of ProfitPerCent
ProfitPerCent = max(ProfitPerCent[1],min(100,ProfitPerCent)) //make sure ProfitPerCent doess not exceed 100%
y2 = max(x2 * ProfitPerCent, y2) //y2 = % of max profit
ENDIF
ENDIF
//------------------------------------------------------------------------------
// manage actual Exit, if needed
//------------------------------------------------------------------------------
IF y1 THEN //Place pending STOP order when y1 > 0 (LONG positions)
SellPrice = max(SellPrice,PositionPrice + (y1 * pipsize)) //convert pips to price
//
// check the minimun distance between ExitPrice and current price
//
IF abs(close - SellPrice) > PriceDistance THEN
//
// place either a LIMIT or STOP pending order according to current price positioning
//
IF close >= SellPrice THEN
SELL AT SellPrice STOP
ELSE
SELL AT SellPrice LIMIT
ENDIF
ELSE
//
//sell AT MARKET when EXITPRICE does not meet the broker's minimun distance from current price
//
SELL AT Market
ENDIF
ENDIF
IF y2 THEN //Place pending STOP order when y2 > 0 (SHORT positions)
ExitPrice = min(ExitPrice,PositionPrice - (y2 * pipsize)) //convert pips to price
//
// check the minimun distance between ExitPrice and current price
//
IF abs(close - ExitPrice) > PriceDistance THEN
//
// place either a LIMIT or STOP pending order according to current price positioning
//
IF close <= ExitPrice THEN
EXITSHORT AT ExitPrice STOP
ELSE
EXITSHORT AT ExitPrice LIMIT
ENDIF
ELSE
//
//ExitShort AT MARKET when EXITPRICE does not meet the broker's minimun distance from current price
//
EXITSHORT AT Market
ENDIF
ENDIF
@Paul
it would be great if you could develop a new modified version of my last posted code, with your interesting additions, if possible, so that it be used with position accumulation.
@Roberto, Thnx for your interest about the additions, a few are covered like sensitivity. The way implemented for me is sufficient. I always prefer % from the latest close instead of a fixed number of points. The Donchian channels I don’t use. Nice to see you included the directionswitch. For now I looking at the % aspects of the code. Looks simple but is it?
If using percentage, it runs into trouble sometimes. You shouldn’t use tradeprice or positionprice but “close” from the moment condtions are true to enter and a new position is opened at the next bar.
But not onmarket or directionswitch does not cover each scenario, because if long & adding long it doesn’t take the correct close.
Anyway i’am suggestion something like this below. What do you think?
Besides this above, while I ‘ve seen working it correctly, also i’ve seen sellprice & exitprice at 0/999999. pffff
Here’s the relevant part.
DirectionSwitch = (LongOnMarket AND ShortOnMarket[1]) OR (LongOnMarket[1] AND ShortOnMarket)
IF Not OnMarket OR DirectionSwitch THEN
ts = 0.2 //% start trailing profits from this point
BasePerCent = 0.200 //20.0% Profit percentage to keep when setting BerakEven
StepSize = 10 //10 Pip chunks to increase Percentage
PerCentInc = 0.100 //10.0% PerCent increment after each StepSize chunk
RoundTO = -0.5 //-0.5 rounds always to Lower integer, +0.4 rounds always to Higher integer,0 defaults PRT
PriceDistance = 7 * pipsize //7 minimun distance from current price
y1 = 0 //reset to 0
y2 = 0 //reset to 0
ProfitPerCent = BasePerCent //reset to desired default value
//PositionCount = 0
SellPrice = 0
ExitPrice = 9999999
trailstart = ((close*ts)/100)*pipsize
ELSE
if abs(countofposition)>abs(countofposition)[1] then // if adding to a long/short position, update trailstart
trailstart = ((close*ts)/100)*pipsize
endif
IF PositionPrice <> PositionPrice[1] AND (ExitPrice + SellPrice) <> 9999999 THEN
IF LongOnMarket THEN
q1 = PositionPrice + ((srcH - PositionPrice) * ProfitPerCent)
SellPriceX = max(max(SellPriceX,SellPrice),q1)
SellPrice = max(max(SellPriceX,SellPrice),PositionPrice + (y1 * pipsize))
ELSIF ShortOnMarket THEN
r1 = ((PositionPrice - srcL) * ProfitPerCent)
ExitPriceX = min(min(ExitPriceX,ExitPrice),r1)
ExitPrice = min(min(ExitPriceX,ExitPrice),PositionPrice - (y2 * pipsize))
ENDIF
ENDIF
ENDIF
Thank you Paul for your useful suggestions.
Having looked at it again I found an other reason for the differences I was experiencing. The format above works with close or positionprice and it can also be placed outside that area to calculate the trailstart and just use position price without additional lines of code. Always more ways then one to achieve the same thing…
It will add 10% to the current percentage every 50 minutes.
So if your base percentage was 10%, PerCentInc may have raised that to, say 11% or 12%, BarPerCent will add a further 10% for a total of 21% or 22%.
If you set up percentages like that:
when PerCentInc INCREASES BasePerCent the first time, BasePerCent will become 11% (itself + 10% of itself), while BarPerCent will ADD 10% so that 11% becomes 21%.
hi Roberto, isn’t stepsize having the same problem as spread if calculated over longer time periods. A stepsize of 10 on the dow might be quite big 5-10 years back?
Second question is that stepsize is depended on which market it is applied to. On the dow it’s different then on forex. On forex (eurusd mini) it was guessing how small it should be. I settled on 0.0001. Does that make sense?
Is there some way to have a method that give it a value automatically?
Maybe the atr is something which will work and covers both questions. If changing over time is usefull or not it’s something to test, but atleast stepsize adjust itself to each market (atr/10)
if (not onmarket[1] and onmarket) or directionswitch then
atr=(AverageTrueRange[200](close))/10
endif
Whenever you launch you strategy in autotrading you know:
so you can change STEP accordingly.
Of course using ATR makes it more portable (but you will still have to change other settings, such as Distance from current price, Start).
Actually there’s no perfect Trailing Stop (and no perfect strategy, indicator, ……), so everyone has to stick to the code he prefers, making custom changes, like you did, to suit best your needs (which may change across different strategies).
“isn’t stepsize having the same problem as spread if calculated over longer time periods. A stepsize of 10 on the dow might be quite big 5-10 years back?” That is 100% true. I also have been focusing on optimizing on 1million bars which means it is a big difference from 2011 and 2021. The backtest shows much better closes if looking at MFE from earlier on the backtest. I like the concept of this code and do you guys have any suggestion how I could work arround this?
BreakEven & Trailing Profit: complete function
This topic contains 137 replies,
has 23 voices, and was last updated by Wim
5 months, 1 week ago.
| Forum: | ProOrder support |
| Language: | English |
| Started: | 03/18/2019 |
| Status: | Active |
| Attachments: | 25 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.