ProRealCode - Trading & Coding with ProRealTime™
Price distance can be set at 2 points with SP500 with a clear conscience.
There are different versions of Roberto’s Trp. I used the version on page 4 (rif: 165976): https://www.prorealcode.com/topic/breakeeven-trailing-profit/page/4/
Roberto, is there a better one for this TS?
Is there a reason why you define TP and SL outside of the if block? Is this better from the encoding or just a coding style?
looks interesting, thanks for sharing.
I tried reworking it on 1m bars but it’s fairly dead before 2018, so here’s a quick treatment on a 5 year backtest. Attached are results for yours and Mauro’s for that same period and you can see that they’re curve-fit to 200k
SP 5m T4 Multi v4.1 is with Roberto’s trail, but I didn’t change any of the values from Mauro’s version, so that could be worth playing with.
More room for improvement, I’m sure
It’s just a coding style, I think the code remains cleaner.
here’s the code for mine, so you can see the changes
//30.03.2022 200000k
//US500 M5 Spread 0.6
//UK Time
defparam preloadbars = 10000
defparam CUMULATEORDERS = false
possize = 5
//Tradetime
//UK time
h1 = 143000
h2 = 220000
//Euro time
//h1 = 153000
//h2 = 230000
//adjustment for American Daylight Savings time
ADLS =1
if ADLS then
DLS =(Date >= 20100314 and date <=20100328) or (Date >= 20101031 and date <=20101107) or (Date >= 20110313 and date <=20110327) or (Date >= 20111030 and date <=20111106) or (Date >= 20120311 and date <=20120325) or (Date >= 20121028 and date <=20121104) or (Date >= 20130310 and date <=20130331) or (Date >= 20131027 and date <=20131103) or (Date >= 20140309 and date <=20140330) or (Date >= 20141026 and date <=20141102) or (Date >= 20150308 and date <=20150329) or (Date >= 20151025 and date <=20151101) or (Date >= 20160313 and date <=20160327) or (Date >= 20161030 and date <=20161106) or (Date >= 20170312 and date <=20170326) or (Date >= 20171030 and date <=20171105) or (Date >= 20180311 and date <=20180325) or (Date >= 20181028 and date <=20181104) or (Date >= 20190310 and date <=20190331) or (Date >= 20191027 and date <=20191103) or (Date >= 20200308 and date <=20200329) or (Date >= 20201025 and date <=20201101) or (Date >= 20210314 and date <=20210328) or (Date >= 20211031 and date <=20211107) or (Date >= 20220313 and date <=20220327) or (Date >= 20221030 and date <=20221106) or (Date >= 20230312 and date <=20230326) or (Date >= 20231029 and date <=20231105) or (Date >= 20240310 and date <=20240331) or (Date >= 20241027 and date <=20241103)
If DLS then
Tradetime = time >=h1-10000 and time <h2-10000
elsif not DLS then
Tradetime = time >=h1 and time <h2
endif
endif
if not ADLS then
Tradetime = time >=h1 and time <h2
endif
timeframe(8 hour)
ma = average[a1,t1](typicalprice)
cb1 = ma > ma[1]
mb = average[a2,t2](typicalprice)
cs1 = mb < mb[1]
timeframe(15 minutes)
MA1 = average[x1,t3](typicalprice)
MA2 = average[x2,t3](typicalprice)
MA4 = average[x5,t5](typicalprice)
MA5 = average[x6,t5](typicalprice)
cb2 = MA1 > MA2 //and MA2 > MA3 //and MA2 > MA2[1]
cs2 = MA4 < MA5 //and MA5 < MA5[1]
timeframe(default)//M5
MAL1 = average[a7,t7](typicalprice)
MAL2 = average[a8,t7](typicalprice) //15
cb3 = MAL1 crosses over MAL2
cs3 = MAL1 crosses under MAL2
long = cb1 and cb2 and cb3 //and RangelongD20
short = cs1 and cs2 and cs3 //and RangeshortD20
// position management
IF Tradetime THEN
If long then //not onmarket and
BUY possize CONTRACT AT market
SET STOP %LOSS hl
SET TARGET %PROFIT gl
EndIf
If short then
sellshort possize CONTRACT AT market
SET STOP %LOSS hs
SET TARGET %PROFIT gs
EndIf
endif
If longonmarket and cs1 then
sell at market
endif
If shortonmarket and cb1 then
exitshort at market
endif
////////////////////////////////////////
Thank you for your work. I’ll compare in peace. But it is interesting to see that a suitable system is created with simple indicators without much magic. I think the “problem” with the Roberto Trail is that it uses points instead of percent. I suspect. And that before 2018 the S&P500 was worth half what it is today. Of course, the fluctuations were much smaller than today.
the Roberto Trail is that it uses points instead of percent
this version has a % option:
//RGTS2
ONCE RGTS2 = 1
if RGTS2 then
ONCE UseCLOSE = 0 //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 = 1 //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)
MyEquity = 0
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 = pc //0.25 = 0.25% to start triggering Trailing Stop (when UsePerCentage=1)
StartPerCentShort = pcs
StepPerCent = spc //50 = 50% (of the 0.25% above) as a Trailing 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
TrailStartShort = (close / PipSize) * StartPerCentShort / 100
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 = bpc //0.08 - 0.2 Profit percentage to keep when setting BerakEven
//
StepSize = ss //5 - 15 Pip chunks to increase Percentage
IF UsePerCentage THEN
StepSize = TrailStart * StepPerCent / 100
ENDIF
//
PerCentInc = pci //0.06 - 0.14 PerCent increment after each StepSize chunk
RoundTO = rnd //-0.5 rounds always to Lower integer, +0.4 rounds always to Higher integer, 0 defaults PRT behaviour
PriceDistance = IG * pipsize //IG minimum 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 >= TrailStartShort THEN // go ahead only if N+ pips
Diff2 = abs(TrailStartShort - 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
ENDIF
Which do you prefer? This one (Robertos) or your own, which I also use? Both of which are by Roberto in terms of construction.
I mostly use this one (above) – has a few more options and usually gives better results. I added a separate TrailStartShort as it often helps to have different values there.
I have found that separate trailing for long and short is important. But the steps must also be separate. Short trades usually have to be secured faster than long trades.
Thanks for sharing nonetheless
Agree with you that % is better than fixed. Given the change in index value over the last 2 years I tend to optimise over a more recent data set to have something more relevant going forwards.
I once again looked at my original version and installed lightweight filter …
In the H4 time frame I installed a new noTrade-filter that should prevent the strategy enters a covered or oversold market. In addition, I added an entrance timer who should find out if there is a better price after the Ma-Cross.
All small changes, but … more Profit, Smaller Drawdown.
//31.03.2022 200000k
//US500 M5 Spread 0.6
//German Time
defparam preloadbars = 10000
defparam CUMULATEORDERS = false
possize = 5
timeframe(4hour, updateonclose)
myRSI = RSI[rs](close)
noTradeL = myRSI > rso
noTradeS = myRSI < rsu
timeframe(15minute, updateonclose)
RangeMAD5 = average[480,0](close) //Wochentrend Daily MA5
RangelongD5 = close > RangeMAD5
RangeshortD5 = close < RangeMAD5
RangeMAD20 = average[1920,0](close) //"Monatstrend" Daily MA20
RangelongD20 = RangeMAD5 > RangeMAD20
RangeshortD20 = RangeMAD5 < RangeMAD20
MA1 = average[x1,0](close)
MA2 = average[x2,0](close)
//MA3 = average[x3,0](close)
MA4 = average[x5,1](close)
MA5 = average[x6,1](close)
longA = MA1 > MA2 //and MA2 > MA3 //and MA2 > MA2[1]
shortA = MA4 < MA5 //and MA5 < MA5[1]
MAL1 = average[5,0](close)
MAL2 = average[15,0](close) //15
longB = MAL1 crosses over MAL2
shortB = MAL1 crosses under MAL2
timeframe(default)//M5
long = RangelongD5 and longB[t1] and longA and not noTradeL //and RangelongD20
short = RangeshortD5 and shortB[t2] and shortA and not noTradeS //and RangeshortD20
Exit1 = RangeshortD5
Exit2 = RangelongD5
// trading window
ONCE BuyTime = 110000
ONCE SellTime = 213000
ONCE BuyTime2 = 150000
ONCE SellTime2 = 213000
// position management
IF Time >= buyTime AND Time <= SellTime THEN
If long then //not onmarket and
BUY possize CONTRACT AT market
SET STOP %LOSS hl
SET TARGET %PROFIT gl
EndIf
endif
IF Time >= buyTime2 AND Time <= SellTime2 THEN
If short then
sellshort possize CONTRACT AT market
SET STOP %LOSS hs
SET TARGET %PROFIT gs
EndIf
endif
If longonmarket and Exit1 then
sell at market
endif
If shortonmarket and Exit2 then
exitshort at market
endif
if time = 223000 then //223000
//sell at market
exitshort at market
endif
if time = 225500 and dayofweek=5 then //225500
sell at market
exitshort at market
endif
////////////////////////////////////////
// %trailing stop function incl. cumulative positions
once trailingstoptype = 1
if trailingstoptype then
//====================
trailingpercentlong = startl // %
trailingpercentshort = start // %
once acceleratorlong = stepl // typically tst*0.1
once acceleratorshort= step // typically tss*0.1
ts2sensitivity = 2 // [1] close [2] high/low [3] low/high [4] typicalprice
//====================
once steppercentlong = (trailingpercentlong/10)*acceleratorlong
once steppercentshort = (trailingpercentshort/10)*acceleratorshort
if onmarket then
trailingstartlong = positionprice*(trailingpercentlong/100)
trailingstartshort = positionprice*(trailingpercentshort/100)
trailingsteplong = positionprice*(steppercentlong/100)
trailingstepshort = positionprice*(steppercentshort/100)
endif
if not onmarket or ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
newsl = 0
mypositionprice = 0
endif
positioncount = abs(countofposition)
if newsl > 0 then
if positioncount > positioncount[1] then
if longonmarket then
newsl = max(newsl,positionprice * newsl / mypositionprice)
else
newsl = min(newsl,positionprice * newsl / mypositionprice)
endif
endif
endif
if ts2sensitivity=1 then
ts2sensitivitylong=close
ts2sensitivityshort=close
elsif ts2sensitivity=2 then
ts2sensitivitylong=high
ts2sensitivityshort=low
elsif ts2sensitivity=3 then
ts2sensitivitylong=low
ts2sensitivityshort=high
elsif ts2sensitivity=4 then
ts2sensitivitylong=(typicalprice)
ts2sensitivityshort=(typicalprice)
endif
if longonmarket then
if newsl=0 and ts2sensitivitylong-positionprice>=trailingstartlong then
newsl = positionprice+trailingsteplong + 0.2
endif
if newsl>0 and ts2sensitivitylong-newsl>=trailingsteplong then
newsl = newsl+trailingsteplong
endif
endif
if shortonmarket then
if newsl=0 and positionprice-ts2sensitivityshort>=trailingstartshort then
newsl = positionprice-trailingstepshort
endif
if newsl>0 and newsl-ts2sensitivityshort>=trailingstepshort then
newsl = newsl-trailingstepshort
endif
endif
if barindex-tradeindex>1 then
if longonmarket then
if newsl>0 then
sell at newsl stop
endif
if newsl>0 then
if low crosses under newsl then
sell at market
endif
endif
endif
if shortonmarket then
if newsl>0 then
exitshort at newsl stop
endif
if newsl>0 then
if high crosses over newsl then
exitshort at market
endif
endif
endif
endif
mypositionprice = positionprice
endif
if (shortonmarket and newsl > 0) or (longonmarket and newsl>0) then
if positioncount > positioncount[1] then
if longonmarket then
newsl = max(newsl,positionprice * newsl / mypositionprice)
endif
if shortonmarket then
newsl = min(newsl,positionprice * newsl / mypositionprice)
endif
endif
endif
//////////////////////////////////////////////////////////////
I expect you’ve decided that you don’t really care what happened before your test period, but just in case you’re curious:
Simple Moving Average Crossover Strategy
This topic contains 95 replies,
has 12 voices, and was last updated by CRISRJ
3 years, 1 month ago.
| Forum: | ProOrder: Automated Strategies & Backtesting |
| Language: | English |
| Started: | 01/26/2022 |
| Status: | Active |
| Attachments: | 39 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.