This strategy is based on the famous turtle trading system and tries to follow the original rules as much as possible. It is a trend following system that generates entry and exit signals using double moving averages.
The advantages of this strategy:
There are also some risks:
Risks can be reduced by:
The strategy can be improved in the following ways:
The strategy profits by following the trend and has good backtest results. But real performance needs to be validated. Further optimization on parameter robustness, stop loss and position sizing is needed before applying it in live trading. Overall it has sound logic and much potential for improvement.
/*backtest start: 2022-10-30 00:00:00 end: 2023-11-05 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=4 strategy(title="Turtle", overlay=true, initial_capital=100000, default_qty_type=strategy.percent_of_equity, default_qty_value=10, commission_type=strategy.commission.percent, commission_value=0.1, pyramiding=5) stopInput = input(2.0, "Stop N", step=.5) pyramidInput = input(1, "Pyramid N", step=.5) l1LongInput = input(20, "L1 Long", minval=5) l2LongInput = input(55, "L2 Long", minval=5) l1LongExitInput = input (10, "L1 Long Exit", minval=5) l2LongExitInput = input (20, "L2 Long Exit", minval=5) FromYear = input(2000, "From Year", minval=1900), FromMonth = input(1, "From Month", minval=1, maxval=12), FromDay = input(1, "From Day", minval=1, maxval=31) ToYear = input(9999, "To Year", minval=1900), ToMonth = input(1, "To Month", minval=1, maxval=12), ToDay = input(1, "To Day", minval=1, maxval=31) FromDate = timestamp(FromYear, FromMonth, FromDay, 00, 00), ToDate = timestamp(ToYear, ToMonth, ToDay, 23, 59) TradeDateIsAllowed() => time >= FromDate and time <= ToDate l1Long = highest(l1LongInput) l1LongExit = lowest(l1LongExitInput) l2Long = highest(l2LongInput) l2LongExit = lowest(l2LongExitInput) // // ADX, +-DI // https://www.tradingview.com/script/rlMJ05yl-ADX-and-DI-pine-script-3-0/ // len = 14 th = 20 TrueRange = max(max(high-low, abs(high-nz(close[1]))), abs(low-nz(close[1]))) DirectionalMovementPlus = high-nz(high[1]) > nz(low[1])-low ? max(high-nz(high[1]), 0): 0 DirectionalMovementMinus = nz(low[1])-low > high-nz(high[1]) ? max(nz(low[1])-low, 0): 0 SmoothedTrueRange = 0.0 SmoothedTrueRange := nz(SmoothedTrueRange[1]) - (nz(SmoothedTrueRange[1])/len) + TrueRange SmoothedDirectionalMovementPlus = 0.0 SmoothedDirectionalMovementPlus := nz(SmoothedDirectionalMovementPlus[1]) - (nz(SmoothedDirectionalMovementPlus[1])/len) + DirectionalMovementPlus SmoothedDirectionalMovementMinus = 0.0 SmoothedDirectionalMovementMinus := nz(SmoothedDirectionalMovementMinus[1]) - (nz(SmoothedDirectionalMovementMinus[1])/len) + DirectionalMovementMinus DIPlus = SmoothedDirectionalMovementPlus / SmoothedTrueRange * 100 DIMinus = SmoothedDirectionalMovementMinus / SmoothedTrueRange * 100 DX = abs(DIPlus-DIMinus) / (DIPlus+DIMinus)*100 ADX = sma(DX, len) // Back to Turtle filter = true // not (DIPlus < ADX and DIMinus < ADX) and DIPlus > DIMinus var win = false var totalPrice = 0.0 var buyPrice = 0.0 var avgPrice = 0.0 var nextBuyPrice = 0.0 var stopPrice = 0.0 var totalBuys = 0 var bool inBuy = false var float l1LongPlot = highest(l1LongInput) var float l2LongPlot = highest(l2LongInput) n = atr(14) var mode = 'L1' string longLevel = na if not inBuy l1LongPlot := highest(l1LongInput)[1] l2LongPlot := highest(l2LongInput)[1] if (close > l2Long[1] and filter) mode := 'L2' if TradeDateIsAllowed() strategy.close_all() strategy.entry("long", strategy.long, comment="L2") longLevel := 'L2' win := false buyPrice := close totalBuys := 1 totalPrice := buyPrice avgPrice := buyPrice stopPrice := close-(stopInput*n) nextBuyPrice := high+(pyramidInput*n) inBuy := true else if (close > l1Long[1] and filter) mode := 'L1' if not win if TradeDateIsAllowed() strategy.close_all() strategy.entry("long", strategy.long, comment="L1") longLevel := 'L1' win := false buyPrice := close totalBuys := 1 totalPrice := buyPrice avgPrice := buyPrice stopPrice := close-(stopInput*n) nextBuyPrice := high+(pyramidInput*n) inBuy := true else inBuy := false else l1LongPlot := l1LongPlot[1] l2LongPlot := l2LongPlot[1] if close > nextBuyPrice and TradeDateIsAllowed() and totalBuys < 6 strategy.entry("long", strategy.long, comment="LP") longLevel := 'P' stopPrice := close-(stopInput*n) nextBuyPrice := high+(pyramidInput*n) totalBuys := totalBuys + 1 totalPrice := totalPrice + buyPrice avgPrice := totalPrice / totalBuys if (close < stopPrice) inBuy := false if TradeDateIsAllowed() if (close >= avgPrice) longLevel := 'SG' else longLevel := 'SR' strategy.close("long", strategy.long) win := false buyPrice := 0 avgPrice := 0 else if (mode == 'L1' and close > l2Long[1] and filter) if win inBuy := true win := false mode := 'L2' if TradeDateIsAllowed() strategy.close_all() longLevel := 'L2' strategy.entry("long", strategy.long, comment="L2") buyPrice := close totalBuys := 1 totalPrice := buyPrice avgPrice := buyPrice stopPrice := close-(stopInput*n) nextBuyPrice := close+(pyramidInput*n) else if (close < l1LongExit[1] or close < l2LongExit[1]) inBuy := false if TradeDateIsAllowed() strategy.close("long", strategy.long) if close < avgPrice longLevel := 'SR' win := false else longLevel := 'SG' win := true buyPrice := 0 plot(l1LongPlot, title="l1 long", linewidth=3, style=plot.style_stepline, color=color.green) plot(l1LongExit[1], title="l1 exit", linewidth=3, style=plot.style_stepline, color=color.red) plot(l2LongPlot, title="l2 long", linewidth=2, style=plot.style_stepline, color=color.green) plot(l2LongExit[1], title="l2 exit", linewidth=2, style=plot.style_stepline, color=color.red) plot(stopPrice, title="stop", linewidth=2, style=plot.style_stepline, color=color.purple) plotarrow(longLevel == 'L1' ? 1 : 0, colordown=color.black, colorup=color.green, transp=40) plotarrow(longLevel == 'L2' ? 1 : 0, colordown=color.black, colorup=color.purple, transp=40) plotarrow(longLevel == 'SR' ? -1 : 0, colordown=color.red, colorup=color.purple, transp=40) plotarrow(longLevel == 'SG' ? -1 : 0, colordown=color.green, colorup=color.purple, transp=40)