Well, I had to call it something, right?
Attached is the first code I’ve put together that ‘seems to work’. Survives all manner of WF tests: 70-30, 50-50, 30-70 – however you want to chop it.
Also does well in Vonasi’s robustness tester, Random 10-10. I tried hitting it with a very big hammer but still performs well.
Uses a combination of HullMA and Supertrend on the 2h TF to define the primary trend, then another HullMA + trailing stop on a 5m TF to control entry and exit.
The 5m TF doesn’t give us much in the backtest but it does well in clear uptrends and downtrends. Just that choppy bit in March 2019 where it couldn’t cope. I hate to see whole month where a strategy doesn’t come good, but one out of 16 is not too shabby.
It runs around the clock so I’ve allowed for a spread of 3.3, calculated for IG as: (6.5 x 2.4 + 6.5 x 1.6 + 2 x 9.8 + 9 x 3.8)/24
All backtesting was done with MM disabled but I ran the final optimization with it turned on just to demonstrate the boost it gives. Starts with position size = 1 and by the end of the run when equity has trebled, it’s placing position size of ~3.4, so more or less in keeping with standard practise. Also reduces position size in bad patches.
Credit where credit is due: Vonasi wrote the Money Management part and coded the HullMA for me. The trailing stop I believe is Nicolas’ work – big thanks to both!
But the really cool thing about this strategy is that the equity graph draws a perfect profile of Daenerys Targaryen! You might have to squint a bit, but if you can’t see Daenerys then you haven’t optimized correctly.
All comments, suggestions, mods etc welcome!
// DJI 5m
DEFPARAM CumulateOrders = False // Cumulating positions deactivated
DEFPARAM preloadbars = 5000
Capital = 10000
MinSize = 1 //The minimum position size allowed for the instrument.
MM1stType = 0 //Starting type of moneymanagement. Set to 0 for level stakes. Set to 1 for increasing stake size as profits increase and decreasing stake size as profits decrease. Set to 2 for increasing stake size as profits increase with stake size never being decreased.
MM2ndType = 1 //Type of money management to switch to after TradesQtyForSwitch number of trades and ProfitNeededForSwitch profit has occurred
TradesQtyForSwitch = 15 //Quantity of trades required before switching to second money management choice.
ProfitNeededForSwitch = 2 //% profit needed before allowing a money management type change to MM2ndType.
DrawdownNeededToSwitch = 8 //% draw down from max equity needed before money management type is changed back to MM1stType.
DrawdownNeededToQuit = 25 //% draw down from max equity needed to stop strategy
Once MoneyManagement = MM1stType
Equity = Capital + StrategyProfit
maxequity = max(equity,maxequity)
if equity < maxequity * (1 - (DrawdownNeededToSwitch/100)) then
enoughtrades = 0
tradecount = 0
moneymanagement = MM1stType
endif
if equity < maxequity * (1 - (DrawdownNeededToQuit/100)) then
quit
endif
if not EnoughTrades then
if abs(countofposition) > abs(countofposition[1]) then
tradecount = tradecount + 1
endif
if tradecount > TradesQtyForSwitch and maxequity >= Capital * (1 + (ProfitNeededForSwitch/100)) then
EnoughTrades = 1
MoneyManagement = MM2ndType
endif
endif
IF MoneyManagement = 1 THEN
PositionSize = Max(MinSize, Equity * (MinSize/Capital))
ENDIF
IF MoneyManagement = 2 THEN
PositionSize = Max(LastSize, Equity * (MinSize/Capital))
LastSize = PositionSize
ENDIF
IF MoneyManagement <> 1 and MoneyManagement <> 2 THEN
PositionSize = MinSize
ENDIF
PositionSize = Round(PositionSize*100)
PositionSize = PositionSize/100
// Size of POSITIONS
PositionSizeLong = 1 * positionsize
PositionSizeShort = 1 * positionsize
TIMEFRAME(120 minutes)
Period= 520
inner = 2*weightedaverage[round( Period/2)](typicalprice)-weightedaverage[Period](typicalprice)
HULLa = weightedaverage[round(sqrt(Period))](inner)
c1 = HULLa > HULLa[1]
c2 = HULLa < HULLa[1]
indicator1 = SuperTrend[5,21]
c3 = (close > indicator1)
c4 = (close < indicator1)
TIMEFRAME(5 minutes)
Periodb= 60
innerb = 2*weightedaverage[round( Periodb/2)](typicalprice)-weightedaverage[Periodb](typicalprice)
HULLb = weightedaverage[round(sqrt(Periodb))](innerb)
c5 = HULLb > HULLb[1]
c6 = HULLb < HULLb[1]
// Conditions to enter long positions
IF c1 AND C3 AND C5 THEN
BUY PositionSizeLong CONTRACT AT MARKET
SET STOP %LOSS 2.1
SET TARGET %PROFIT 1
ENDIF
// Conditions to enter short positions
IF c2 AND C4 AND C6 THEN
SELLSHORT PositionSizeShort CONTRACT AT MARKET
SET STOP %LOSS 1.2
SET TARGET %PROFIT 1
ENDIF
//trailing stop function
trailingstart = 84 //trailing will start @trailinstart points profit
trailingstep = 3 //trailing step to move the "stoploss"
//reset the stoploss value
IF NOT ONMARKET THEN
newSL=0
ENDIF
//manage long positions
IF LONGONMARKET THEN
//first move (breakeven)
IF newSL=0 AND close-tradeprice(1)>=trailingstart*pipsize THEN
newSL = tradeprice(1)+trailingstep*pipsize
ENDIF
//next moves
IF newSL>0 AND close-newSL>=trailingstep*pipsize THEN
newSL = newSL+trailingstep*pipsize
ENDIF
ENDIF
//manage short positions
IF SHORTONMARKET THEN
//first move (breakeven)
IF newSL=0 AND tradeprice(1)-close>=trailingstart*pipsize THEN
newSL = tradeprice(1)-trailingstep*pipsize
ENDIF
//next moves
IF newSL>0 AND newSL-close>=trailingstep*pipsize THEN
newSL = newSL-trailingstep*pipsize
ENDIF
ENDIF
//stop order to exit the positions
IF newSL>0 THEN
SELL AT newSL STOP
EXITSHORT AT newSL STOP
ENDIF
//************************************************************************