ProRealCode - Trading & Coding with ProRealTime™
Here’s a new algo I’ve had on forward testing for a while (US Tech 100), so far consistent with the BT results. It’s all on moving averages and more or less approximates what I do in manual trading, except where I normally work on a 1min chart, this drops down to 30sec to make up for the 1 candle delay at the entry.
FOR:
Very nice histogram, as good as it gets.
High number of trades in the BT (4 0r 5 per day)
Low drawdown
Spectacular ‘potential returns’ when MM is active (2nd pic – haha, dream on…🤣)
Against:
Very short BT, 17 months – assume it’s curve-fit to that period and would need regular reworking
Possibly over-optimized (???)
Stoploss is > Target profit, meaning that loss of worst trade is also > Gain of best trade – not good but unavoidable.
Very low gain per trade, easily eroded with slippage or at times of higher spread.
No WF, as I prefer to do out-of-sample testing in demo (closer to real trading conditions)
***Requires lengthy forward testing before going live***
As with most things in life – could be a winner, could crash and burn … who knows? Be sure to adjust the Tradetime for your time zone.
// Definition of code parameters
DEFPARAM CumulateOrders = false // Cumulating positions deactivated
DEFPARAM preloadbars = 10000
//MONEY MANAGEMENT II
MM = 0 // = 0 for optimization
if MM = 0 then
positionsize = 0.5
ENDIF
if MM then
MinSize = 0.5 // IG minimum position size allowed
MaxSize = 2000 // IG tier 2 margin limit
ProfitAccrued = 0 // when restarting strategy, enter profit or loss to date in instrument currency
DD = 370 //MinSize drawdown in instrument currency
Multiplier = 3 //drawdown multiplier
if ProfitAccrued + StrategyProfit >= DD*2 then
Multiplier = 2
endif
Capital = DD * Multiplier
Equity = Capital + ProfitAccrued + StrategyProfit
PositionSize = Max(MinSize, Equity * (MinSize/Capital))
if positionsize > MaxSize then
positionsize = MaxSize
endif
PositionSize = Round(PositionSize*100)
PositionSize = PositionSize/100
ENDIF
once tradetype = 1 // [1] long/short [2]long [3]short
once closeonreversal = 0
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 >=133000 and time <200000//UK time
elsif not DLS then
Tradetime = time >=143000 and time <210000//UK time
endif
TIMEFRAME(15 minutes)
ma = average[a,t](typicalprice)
cb1 = ma > ma[1]
mb = average[p2,t2](typicalprice)
cs1 = mb < mb[1]
TIMEFRAME(5 minutes)
mc = average[a3,t3](typicalprice)
cb2 = (mc > ma)
cb3 = mc > mc[1]
md = average[a4,t4](typicalprice)
cs2 = (md < mb)
cs3 = md < md[1]
TIMEFRAME(default)
me = average[a5,t5](typicalprice)
cb4 = me > me[1] and me[1] < me[2]
mf = average[a6,t6](typicalprice)
cs4 = mf < mf[1] and mf[1] > mf[2]
CB = Tradetime and (cb1 or cb2) and cb3 and cb4
CS = Tradetime and (cs1 or cs2) and cs3 and cs4
// Conditions to enter long positions
if tradetype=1 or tradetype=2 then
IF not longonmarket and CB THEN
BUY positionsize CONTRACT AT MARKET
SET STOP %LOSS sl
SET TARGET %PROFIT tp
ENDIF
ENDIF
if tradetype=2 and longonmarket and closeonreversal and CS then
sell at market
endif
// Conditions to enter short positions
if tradetype=1 or tradetype=3 then
IF not shortonmarket and CS THEN
sellshort positionsize CONTRACT AT MARKET
SET STOP %LOSS sls
SET TARGET %PROFIT tps
ENDIF
ENDIF
if tradetype=3 and shortonmarket and closeonreversal and CB then
exitshort at market
endif
//% Break even (high/low)
once breakeven =1
if breakeven then
breakevenPC = be // long
breakevenPCS = bes // short
PointsToKeep = pk
startBreakeven = tradeprice(1)*(breakevenPC/100)
startBreakevenS = tradeprice(1)*(breakevenPCS/100)
//reset the breakevenLevel when no trade are on market
if breakeven>0 then
IF NOT ONMARKET THEN
breakevenLevel=0
ENDIF
// --- BUY SIDE ---
//test if the price have moved favourably of "startBreakeven" points already
IF LONGONMARKET AND high-tradeprice(1)>=startBreakeven*pipsize THEN
//calculate the breakevenLevel
breakevenLevel = tradeprice(1)+PointsToKeep*pipsize
ENDIF
//place the new stop orders on market at breakevenLevel
IF breakevenLevel>0 THEN
SELL AT breakevenLevel STOP
ENDIF
// --- end of BUY SIDE ---
IF SHORTONMARKET AND tradeprice(1)-low>=startBreakevenS*pipsize THEN
//calculate the breakevenLevel
breakevenLevel = tradeprice(1)-PointsToKeep*pipsize
ENDIF
//place the new stop orders on market at breakevenLevel
IF breakevenLevel>0 THEN
EXITSHORT AT breakevenLevel STOP
ENDIF
endif
endif
// trailing atr stop
once trailingstopATR = 1
if trailingstopATR then
//====================
once tsincrements = tsi // set to 0 to ignore tsincrements
once tsminatrdist = tsm
once tsatrperiod = tsa // ts atr parameter
once tsminstop = 4 // ts minimum stop distance
tssensitivity = 2 // 1 = close 2 = High/Low 3 = Low/High 4 = typicalprice (not use once)
//====================
if barindex=tradeindex then
trailingstoplong = tsl // ts atr distance
trailingstopshort = tss // ts atr distance
else
if longonmarket then
if tsnewsl>0 then
if trailingstoplong>tsminatrdist then
if tsnewsl>tsnewsl[1] then
trailingstoplong=trailingstoplong
else
trailingstoplong=trailingstoplong-tsincrements
endif
else
trailingstoplong=tsminatrdist
endif
endif
endif
if shortonmarket then
if tsnewsl>0 then
if trailingstopshort>tsminatrdist then
if tsnewsl<tsnewsl[1] then
trailingstopshort=trailingstopshort
else
trailingstopshort=trailingstopshort-tsincrements
endif
else
trailingstopshort=tsminatrdist
endif
endif
endif
endif
tsatr=averagetruerange[tsatrperiod]((close/10))/1000
//tsatr=averagetruerange[tsatrperiod]((close/1)) // (forex)
tgl=round(tsatr*trailingstoplong)
tgs=round(tsatr*trailingstopshort)
if not onmarket or ((longonmarket and shortonmarket[1]) or (longonmarket[1] and shortonmarket)) then
tsmaxprice=0
tsminprice=close
tsnewsl=0
mypositionpriceatr = 0
endif
positioncountatr = abs(countofposition)
if tsnewsl > 0 then
if positioncountatr > positioncountatr[1] then
if longonmarket then
tsnewsl = max(tsnewsl,positionprice * tsnewsl / mypositionpriceatr)
else
tsnewsl = min(tsnewsl,positionprice * tsnewsl / mypositionpriceatr)
endif
endif
endif
if tssensitivity=1 then
tssensitivitylong=close
tssensitivityshort=close
elsif tssensitivity=2 then
tssensitivitylong=high
tssensitivityshort=low
elsif tssensitivity=3 then
tssensitivitylong=low
tssensitivityshort=high
elsif tssensitivity=4 then
tssensitivitylong=typicalprice
tssensitivityshort=typicalprice
endif
if longonmarket then
tsmaxprice=max(tsmaxprice,tssensitivitylong)
if tsmaxprice-positionprice>=tgl then
if tsmaxprice-positionprice>=tsminstop then
tsnewsl=tsmaxprice-tgl
else
tsnewsl=tsmaxprice-tsminstop
endif
endif
endif
if shortonmarket then
tsminprice=min(tsminprice,tssensitivityshort)
if positionprice-tsminprice>=tgs then
if positionprice-tsminprice>=tsminstop then
tsnewsl=tsminprice+tgs
else
tsnewsl=tsminprice+tsminstop
endif
endif
endif
if longonmarket then
if tsnewsl>0 then
sell at tsnewsl stop
endif
if tsnewsl>0 then
if low crosses under tsnewsl then
sell at market // when stop is rejected
endif
endif
endif
if shortonmarket then
if tsnewsl>0 then
exitshort at tsnewsl stop
endif
if tsnewsl>0 then
if high crosses over tsnewsl then
exitshort at market // when stop is rejected
endif
endif
endif
mypositionpriceatr = positionprice
endif
//===================================
RSIexit = 1 // in profit
if RSIexit then
myrsi=rsi[r](close)
if myrsi<rl and barindex-tradeindex>1 and longonmarket and close>positionprice then
sell at market
endif
if myrsi>rs and barindex-tradeindex>1 and shortonmarket and close<positionprice then
exitshort at market
endif
endif
Impressive work!
Impressive. Can that also be recoded to M1? My 200000bars are only a few days in a 30 second timeframe.
Hi @nonetheless
Thanks for sharing this with us!
Do you have PRT version that is sponsored via prorealtime directly rather than the version IG provides? I need to move over to that version. I’m also curious about how it performs in 1minute compared to 30s.
I
Can that also be recoded to M1?
I haven’t tried. My guess is that it relies on getting an early entry as the MA changes direction. The margins are quite small (€2.55 per trade means an average gain of just 5 points) and could be wiped out by waiting another 30sec before opening the trade.
I’m going to be away for a couple of weeks but I’ll try it on 1 min when i get back.
Do you have PRT version that is sponsored via prorealtime
I have a PRT sponsored Premium account with IG. You have to open it through the PRT website. There’s no fee and you can do it even if you already have an IG account so it’s a no-brainer IMHO.
Thank you very much for sharing! A clean approach to trade entry. Very impressive 🙂
“Very short BT, 17 months”
Did you optimized it beginning at the first day and ended on last day?
The problem with the optimizations up to the present day is, that we don´t see how the algo is working in realtime. The problem with the optimizations up to the present day is, that we don’t see how the algo is working in realtime. I have so many algo´s working fine in backtest, and after starting it in realtime demo, it fails. The realtime results are much more better, if i finish the BT´s a few moths befor present day and let them run after end of BT.
So, can you pls stop optimizing of this algo as of 4/1/2021 and then backtest it from 5/1 to today?
If you do it like that you still don’t see how it works in realtime because BT conditions, whether in-sample or out-of-sample, are nothing like real trading (for reasons that have been discussed countless times). Better is to optimise on max data (esp if you’ve only got 17 months), then forward test in demo.
In my opinion, a backtest only tells you if something is worth putting on demo for a few months. Only then will you get an idea of how it works out of sample.
I did already say this in my original post.
So, can you pls stop optimizing of this algo as of 4/1/2021 and then backtest it from 5/1 to today?
If you do it like that you still don’t see how it works in realtime because BT conditions, whether in-sample or out-of-sample, are nothing like real trading
Trying to learn something …
When I read about the idea of VinzentVega, I actually thought it would be a good idea. Not that I would apply it for real, but I think it should work. Thus :
Backtest (literally) until a few months ago (e.g. April vs today’s September) and no bar further. 🙂
When done and optimized to your ideas, run a final backtest (not literally – it is just a final check) from the bar you stopped optimizing (April) until today (September). Let it further run in real time from there if you want. I personally see no difference in this final check done from April till today on one hand, and back in April starting a Paper run till today on the other. If there *is* a difference, then something is wrong with the approach in the backtest program vs what would be reality.
Of course one golden rule is in order : It is totally forbidden to optimize further after you saw the results of that final check (the run from April till today). And, if the final check tells you “FAIL” then just stop with that strategy. It would also be forbidden to optimize the first part (until April) so-called not looking at the final check, because inherently you will be doing this latter (optimize the first part so the last part looks better – DON’T).
Is this wrong somewhere ?
Thanks !
Peter
Is this wrong somewhere ?
Yes … we miss out on optimising for the market cycles / price action existing today, last week , last month etc.
Far better to leave an unoptimised period at the beginning of backtest (10k bars, 50k bars, whatever) and then run the optimised Algo over that OOS period. If Algo stays above zero / not go into deep loss (during the OOS period) then proceed to Forwrd Test / Paper Trade on Demo Account.
Thanks for sharing ! I understand you have optimized it over the whole backtest period …How did you manage to optimize more than 20 variables over 1M candles ??
I personally see no difference in this final check done from April till today on one hand, and back in April starting a Paper run till today on the other. If there *is* a difference, then something is wrong with the approach in the backtest program vs what would be reality.
It’s easy to prove it. Take one algo, duplicate it, optimize it, based on the two backtest scenarios, and finally backtest it and compare the results. I ensure you, that there will be diffrences.
Far better to leave an unoptimised period at the beginning of backtest (10k bars, 50k bars, whatever) and then run the optimised Algo over that OOS period.
This is also a possibility. If you have enough backtest time (in higher timeframe) , then you can disregard one period BEFORE and one period AFTER in optimization. And than ckeck the results.
NAS scalping strategy
This topic contains 30 replies,
has 12 voices, and was last updated by nonetheless
4 years, 2 months ago.
| Forum: | ProOrder: Automated Strategies & Backtesting |
| Language: | English |
| Started: | 09/02/2021 |
| Status: | Active |
| Attachments: | 4 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.