ProRealCode - Trading & Coding with ProRealTime™
PositionPrice should be used instead of TradePrice, but the % modification suggested by nonetheless doesn’t work actually, because you should also change the lines where TrailStart is used to compare with the current price.
I coded it with pips in my mind, so the code would need some in-depth modifications to work with percentages.
I would have thought that
ts = (positionprice*pc)/100 // % trailing start
TrailStart = ts // Start trailing profits from this point
would simply create a value for TrailStart, and then any further reference to TrailStart will relate to that value, no?
Line 56, for example, compares pips. It should be changed to compare percentages.
I think it woukd be better to convert a percentage into pips, in line 14:
TrailStart = (close / PipSize) * pc / 100
this will compute a percentage of the current price, before entering a trade, and convert it into pips.
You may also use your Equity instead of close, and change the expression:
TrailStart = (MyEquity / PipValue) * pc / 100
You can also use such expression for StepSize.
PriceDistance should be left as is, since it has no relation with risk and percentages.
With such minor modifications you will accommodate for percentages without modifying the logic of the code.
Sorry Roberto, I still don’t get it. 🤔
If pc = 0.25 and positionprice = 32000, then TrailStart will be 80
How is this different from simply entering TrailStart = 80 without the % calculation ?
Where Line 56 refers to TrailStart it would just read 80 and work with that … wouldn’t it?
Your assumption is correct because you are using SP500 o Nasdaq, or any other index with a price/pip ratio of 1. Try applying that percentage to, say, Aud/Chf which is 0.7167 with a price/pip ratio of 1/10000th!
If you want to use some code for your personal use you can do whatever you want because that suits your needs and you know what it does, but to make a code portable it must be coded so that it can be used on every instrument.
Ok, now I see what you’re getting at – and of course it makes total sense if you want to cross over into forex.
TBH, I mostly use the original version (from page 1), still gets great results when not using cumulative orders.
This is the new code with the addition of (optional) percentages as above (as suggested by nonetheless). I added a MINSTART to prevent TrailStart from dropping below ZERO when Equity (if you plan to use it) turns negative.
Define MyEquity somewhere in your code (even to ZERO if you don’t plan to use it):
//------------------------------------------------------------------------------------------------------------------------------------------------
// Trailing Start
//------------------------------------------------------------------------------------------------------------------------------------------------
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
ONCE UsePerCentage = 0 //0=use Pips (default), 1=use Percentages
ONCE UseEquity = 0 //0=use price (default), 1=use current Equity (initial Capital + StrategyProfit, as defined by variable MyEquity)
//
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
//
StartPerCent = 0.25 //0.25% to start triggering Trailing Stop (when UsePerCentage=1)
StepPerCent = 50 //50% (of the 0.25% above) as a Trqiling Step (when UsePerCentage=1) (set to 100 to make StepSize=TrailStart, set to 200 to make it twice TrailStart)
//
TrailStart = 30 //30 Start trailing profits from this point (when UsePerCentage=0)
MinStart = 10 //10 Minimum value for TrailStart (when UseEquity=1, to prevent TrailStart from dropping below ZERO when Equity turns negative)
IF UsePerCentage THEN
TrailStart = (close / PipSize) * StartPerCent / 100 //use current price (CLOSE) for calculations
IF UseEquity THEN //alternative calculations using EQUITY
TrailStart = Max(MinStart,(MyEquity / PipValue) * StartPerCent / 100) //MyEquity is the variable (feel free to use a different name) retaining your current equity
ENDIF
ENDIF
//
BasePerCent = 0.200 //20.0% Profit percentage to keep when setting BerakEven
//
StepSize = 10 //10 Pip chunks to increase Percentage
IF UsePerCentage THEN
StepSize = TrailStart * StepPerCent / 100
ENDIF
//
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
SellPriceX = 0
ExitPrice = 9999999
ExitPriceX = 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 - ((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
That’s a great addition. With forward testing it won’t matter that much whether you use % or points, but with backtesting up to 10 years ago, when index levels were a third or a quarter of what they are now, I think % is essential to get an accurate impression of past performance.
This one is seriously amazing. Great work!
My brain is getting fried. I was trying theoretically to come up with the solution before I tried to change the code, but I’m stuck.
What I want to achieve is to add a target at let’s say 2%. The trailing starts at 0.2%. The closer it gets to the 2%, the tighter the trailing stop is. So theoretically, when you hit 2%, it’s basically a TP.
Any ideas?
I decided to code a new one, instead of changing the above code (tested on DAX, Daily TF):
Avg = average[100,0](close)
IF not OnMarket THEN
IF close CROSSES OVER Avg THEN
BUY AT MARKET
ELSIF close CROSSES UNDER Avg THEN
SELLSHORT AT MARKET
ENDIF
SL = close / 100 * 2 //2% SL
SET STOP LOSS SL
ENDIF
//
// incremental Trailing Stop (based on Percentages)
//
NewTrade = (OnMarket AND Not OnMarket[1]) OR (LongOnMarket AND ShortOnMarket[1]) OR (LongOnMarket[1] AND ShortOnMarket)
//
IF Not OnMarket OR NewTrade THEN //reset to default values when a new trade has been opened
PerCentTP = 2.0 //2.0% is TP
PerCentStart = 0.2 //0.2% is the Trailing Stop trigger level
PerCentStep = 0.2 //0.2% is each subsequent step
PerCentSaved = 0.1 //0.1% is how much profit has to be saved when trailing starts and every step
Multiplier = 1.5 //1.5 is how much PerCentSaved is incremented each trailing step
// 1.5 is a 50% increment, so that:
// 0.1% becomes 0.15%, then
// 0.15% becomes 0.225%, then
// 0.225% becomes 0.3375%, etc...
Distance = 6 //6 pip distance from current price (if required by the broker)
MySL = 0
ProfitPerCent = 0
ENDIF
IF OnMarket THEN
IF MySL = 0 THEN
PCent = PositionPrice * PerCentTP / 100
PStart = PositionPrice * PerCentStart / 100
PStep = PositionPrice * PerCentStep / 100
PSaved = PositionPrice * PerCentSaved / 100
ENDIF
//
// check if Trailing Stop has to be triggered
//
IF MySL = 0 THEN
IF LongOnMarket THEN
IF (close - PositionPrice) >= PStart THEN
MySL = min(close,PositionPrice + PSaved)
PSaved = PSaved * Multiplier
ENDIF
ELSIF ShortOnMarket THEN
IF (PositionPrice - close) >= PStart THEN
MySL = max(close,PositionPrice - PSaved)
PSaved = PSaved * Multiplier
ENDIF
ENDIF
ELSE
//
// check if another Step has been triggered
//
IF LongOnMarket THEN
IF (close - MySL) >= PStep THEN
MySL = min(close,MySL + PSaved)
PSaved = PSaved * Multiplier
ENDIF
ELSIF ShortOnMarket THEN
IF (MySL - close) >= PStep THEN
MySL = max(close,MySL - PSaved)
PSaved = PSaved * Multiplier
ENDIF
ENDIF
ENDIF
//
// place Pending STOP orders
//
IF MySL > 0 THEN
IF (MySL = close) OR (abs(MySL - close) < Distance) THEN //exit immediately in case MySL has reached
// the current price or there's not enough DISTANCE
SELL AT MARKET
EXITSHORT AT MARKET
ELSE
SELL AT MySL STOP
EXITSHORT AT MySL STOP
ENDIF
ENDIF
ENDIF
//
graphonprice PositionPrice coloured(0,0,0,255) AS "Entry"
graphonprice MySL coloured(0,128,0,155) AS "Trailing Stop"
IF LongOnMarket THEN
graphonprice PositionPrice - SL coloured(255,0,0,255) AS "Stop Loss"
ELSE
graphonprice PositionPrice + SL coloured(255,0,0,255) AS "Stop Loss"
ENDIF
graph PCent coloured(0,0,0,255)
graph PStart coloured(0,0,255,255)
graph PStep coloured(0,128,0,155)
graph PSaved coloured(255,0,0,255)
graph positionperf * positionprice / pipsize AS "Gain"
Holy smokes! You are amazing!
Will give it a try today. I think it will work great for some of the strategies that hold for longer and are in quite high profits. With the old one, the gap between the SL and current price was getting bigger and bigger, so it gave back quite a lot of the profit.
Thank you!
robertogozzi u are an amazing coder. But for us others it would be very intresting to get an explantion in text for how ur trailingcode works. Whats hapens when and why. What is and how to use minstart MyEquity and so on.
This is the same code as above (test code not included), with more comments:
// NewTrade is true whenever a new trade is opened, be it:
//
// - a trade when there was none previously
// - a trade that has changed direction due to a Stop & Reverse (it's Long and previously was Short and viceversa)
//
// This will be useful to reset variables to their initial values after a trade has been opened.
//
NewTrade = (OnMarket AND Not OnMarket[1]) OR (LongOnMarket AND ShortOnMarket[1]) OR (LongOnMarket[1] AND ShortOnMarket)
//
// Reset variables to their initial value when a new trade shows
//
IF Not OnMarket OR NewTrade THEN //reset to default values when a new trade has been opened (or none is OnMarket)
PerCentTP = 2.0 //2.0% is TP
PerCentStart = 0.2 //0.2% is the Trailing Stop trigger level
PerCentStep = 0.2 //0.2% is each subsequent step
PerCentSaved = 0.1 //0.1% is how much profit has to be saved when trailing starts and every step
Multiplier = 1.5 //1.5 is how much PerCentSaved is incremented each trailing step
// 1.5 is a 50% increment, so that:
// 0.1% becomes 0.15%, then
// 0.15% becomes 0.225%, then
// 0.225% becomes 0.3375%, etc...
Distance = 6 //6 pip distance from current price (if required by the broker)
MySL = 0
ProfitPerCent = 0
ENDIF
//
// The trailing stop can operate only when OnMarket
//
IF OnMarket THEN
//
// before the trailing stop is triggered some calculations need to be done, accordin to settings
//
IF MySL = 0 THEN
PCent = PositionPrice * PerCentTP / 100
PStart = PositionPrice * PerCentStart / 100
PStep = PositionPrice * PerCentStep / 100
PSaved = PositionPrice * PerCentSaved / 100
ENDIF
//
// check if Trailing Stop has to be triggered
//
IF MySL = 0 THEN
IF LongOnMarket THEN
IF (close - PositionPrice) >= PStart THEN
MySL = min(close,PositionPrice + PSaved)
PSaved = PSaved * Multiplier
ENDIF
ELSIF ShortOnMarket THEN
IF (PositionPrice - close) >= PStart THEN
MySL = max(close,PositionPrice - PSaved)
PSaved = PSaved * Multiplier
ENDIF
ENDIF
ELSE
//
// check if another Step has been triggered
//
IF LongOnMarket THEN
IF (close - MySL) >= PStep THEN
MySL = min(close,MySL + PSaved)
PSaved = PSaved * Multiplier
ENDIF
ELSIF ShortOnMarket THEN
IF (MySL - close) >= PStep THEN
MySL = max(close,MySL - PSaved)
PSaved = PSaved * Multiplier
ENDIF
ENDIF
ENDIF
//
// place Pending STOP orders
//
IF MySL > 0 THEN
IF (MySL = close) OR (abs(MySL - close) < Distance) THEN //exit immediately in case MySL has reached
// the current price or there's not enough DISTANCE
SELL AT MARKET
EXITSHORT AT MARKET
ELSE
SELL AT MySL STOP
EXITSHORT AT MySL STOP
ENDIF
ENDIF
ENDIF
if you have more questions don’t hesitate to ask.
Thanks roberto.
Is their a function abow that does:
When x% profit sl jumps to x% profit.
Exemple: When 1% profit sl jumps to 0.1% profit.
Lets call it “breakeven jump-code” 😊
Would u like to explan MyEquity and how it works and how to use it.
Sorry for asking so much ☺
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.