This strategy is named RSI_OTT-TP/SL. It combines RSI indicator and OTT bands to determine trading signals, belonging to trend following strategies. The strategy judges market trend direction through RSI indicator and uses OTT bands to locate specific entry points. It also allows users to set take profit and stop loss ratios to lock in profits or avoid losses automatically.
This strategy uses RSI and OTT indicators to determine trend and entry points.
RSI is used to judge the overall trend direction. RSI can show whether the market is overbought or oversold. RSI crossing above the overbought level is a buy signal, while crossing below the oversold level is a sell signal. The default RSI length is 6, overbought level is 50 and oversold level is also 50 in this strategy.
OTT bands are used to discover entry points. They are bands formed based on the Volatility Rate of Change (VAR) indicator. When price breaks through the lower band upwards, it is a buy signal. When price breaks the upper band downwards, it is a sell signal.
After determining the trend and confirming the entry point, this strategy will open long or short positions when price breaks the OTT bands.
Take profit and stop loss can be set via input boxes for users to customize. The strategy will close positions automatically when take profit or stop loss price is touched.
The strategy also allows long only, short only or both directions trading.
Combining RSI and OTT bands can find high probability entry points under accurate trend judgement.
OTT bands utilize momentum indicator and are very sensitive to price fluctuations, which can discover turning points early.
The take profit and stop loss functions help lock in profits and limit losses before they expand, which benefits risk control.
The code structure is clear with sufficient comments, easy to understand and modify.
Strategy parameters can be flexibly adjusted via the interface to adapt to different market environments.
RSI has lagging issue and may miss trend reversal points, leading to unnecessary losses.
OTT bands can also generate false signals. It’s better to confirm with candlestick patterns.
Improper take profit and stop loss settings will impact strategy performance. Parameters need to be adjusted for different products.
The strategy is only backtested on a single product. Parameters should be separately optimized for different products in live trading.
The backtest time window is short and may not fully validate the strategy effectiveness. It’s recommended to expand the backtest period.
Consider adding other indicators for filtration, such as MACD, KD etc to reduce false entries.
Take profit and stop loss ranges can be dynamically adjusted based on volatility.
Research parameter optimization for different products to establish parameter selection criteria.
Try machine learning methods to dynamically optimize strategy parameters.
Add volume confirmation to avoid false breakouts. Volume indicators can also be used to determine trends.
Consider using MA penetration as stop loss instead of simple percentage stop loss.
In summary, this is a typical trend following strategy. It first judges the trend direction through RSI, then uses OTT bands to assist in determining specific entry points, and finally sets take profit and stop loss to lock in profits and control risks. The advantages of this strategy are simple and effective indicator combinations and good backtest results. But there are also some risks like RSI lag and OTT band false signals. This requires us to optimize parameters carefully in live trading, and add other technical indicators for confirmation to improve strategy stability. With continuous optimization and verification, this strategy can become a very practical trend following strategy template.
/*backtest start: 2023-09-08 00:00:00 end: 2023-10-08 00:00:00 period: 2h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © BigCoinHunter //@version=5 strategy(title="RSI_OTT-TP/SL", overlay=true, pyramiding=0, default_qty_type=strategy.percent_of_equity, default_qty_value=100, initial_capital=1000, currency=currency.USD, commission_value=0.05, commission_type=strategy.commission.percent, process_orders_on_close=true) //----------- get the user inputs -------------- //---------- RSI ------------- price = input(close, title="Source") RSIlength = input.int(defval=6,title="RSI Length") RSIoverSold = input.int(defval=50, title="RSI OverSold", minval=1) RSIoverBought = input.int(defval=50, title="RSI OverBought", minval=1) //------- OTT Bands ---------------- src = close length=input.int(defval=1, title="OTT Period", minval=1) percent=input.float(defval=5, title="OTT Percent", step=0.1, minval=0.001) mav = input.string(title="OTT MA Type", defval="VAR", options=["SMA", "EMA", "WMA", "TMA", "VAR", "WWMA", "ZLEMA", "TSF"]) ottUpperPercent = input.float(title="OTT Upper Line Coeff", defval=0.01, minval = 0.001, step=0.001) ottLowerPercent = input.float(title="OTT Lower Line Coeff", defval=0.01, minval = 0.001, step=0.001) Var_Func(src,length)=> valpha=2/(length+1) vud1=src>src[1] ? src-src[1] : 0 vdd1=src<src[1] ? src[1]-src : 0 vUD=math.sum(vud1,9) vDD=math.sum(vdd1,9) vCMO=nz((vUD-vDD)/(vUD+vDD)) VAR=0.0 VAR:=nz(valpha*math.abs(vCMO)*src)+(1-valpha*math.abs(vCMO))*nz(VAR[1]) VAR=Var_Func(src,length) Wwma_Func(src,length)=> wwalpha = 1/ length WWMA = 0.0 WWMA := wwalpha*src + (1-wwalpha)*nz(WWMA[1]) WWMA=Wwma_Func(src,length) Zlema_Func(src,length)=> zxLag = length/2==math.round(length/2) ? length/2 : (length - 1) / 2 zxEMAData = (src + (src - src[zxLag])) ZLEMA = ta.ema(zxEMAData, length) ZLEMA=Zlema_Func(src,length) Tsf_Func(src,length)=> lrc = ta.linreg(src, length, 0) lrc1 = ta.linreg(src,length,1) lrs = (lrc-lrc1) TSF = ta.linreg(src, length, 0)+lrs TSF=Tsf_Func(src,length) getMA(src, length) => ma = 0.0 if mav == "SMA" ma := ta.sma(src, length) ma if mav == "EMA" ma := ta.ema(src, length) ma if mav == "WMA" ma := ta.wma(src, length) ma if mav == "TMA" ma := ta.sma(ta.sma(src, math.ceil(length / 2)), math.floor(length / 2) + 1) ma if mav == "VAR" ma := VAR ma if mav == "WWMA" ma := WWMA ma if mav == "ZLEMA" ma := ZLEMA ma if mav == "TSF" ma := TSF ma ma MAvg=getMA(src, length) fark=MAvg*percent*0.01 longStop = MAvg - fark longStopPrev = nz(longStop[1], longStop) longStop := MAvg > longStopPrev ? math.max(longStop, longStopPrev) : longStop shortStop = MAvg + fark shortStopPrev = nz(shortStop[1], shortStop) shortStop := MAvg < shortStopPrev ? math.min(shortStop, shortStopPrev) : shortStop dir = 1 dir := nz(dir[1], dir) dir := dir == -1 and MAvg > shortStopPrev ? 1 : dir == 1 and MAvg < longStopPrev ? -1 : dir MT = dir==1 ? longStop: shortStop OTT=MAvg>MT ? MT*(200+percent)/200 : MT*(200-percent)/200 light_green=#08ff12 light_red=#fe0808 OTTupper = nz(OTT[2])*(1+ottUpperPercent) OTTlower = nz(OTT[2])*(1-ottLowerPercent) p1 = plot(OTTupper, color=light_green, linewidth=1, title="OTT UPPER") p2 = plot(nz(OTT[2]), color=color.new(color.yellow,0), linewidth=1, title="OTT MIDDLE") p3 = plot(OTTlower, color=light_red, linewidth=1, title="OTT LOWER") fill(plot1=p1, plot2=p3, title="OTT Background", color=color.new(color.aqua,90), fillgaps=false, editable=true) buyEntry = ta.crossover(src, OTTlower) sellEntry = ta.crossunder(src, OTTupper) //---------- input TP/SL --------------- tp = input.float(title="Take Profit:", defval=0.0, minval=0.0, maxval=100.0, step=0.1) * 0.01 sl = input.float(title="Stop Loss: ", defval=0.0, minval=0.0, maxval=100.0, step=0.1) * 0.01 isEntryLong = input.bool(defval=true, title= 'Long Entry', inline="11") isEntryShort = input.bool(defval=true, title='Short Entry', inline="11") //---------- backtest range setup ------------ fromDay = input.int(defval = 1, title = "From Day", minval = 1, maxval = 31) fromMonth = input.int(defval = 1, title = "From Month", minval = 1, maxval = 12) fromYear = input.int(defval = 2021, title = "From Year", minval = 2010) toDay = input.int(defval = 30, title = "To Day", minval = 1, maxval = 31) toMonth = input.int(defval = 12, title = "To Month", minval = 1, maxval = 12) toYear = input.int(defval = 2022, title = "To Year", minval = 2010) //------------ time interval setup ----------- start = timestamp(fromYear, fromMonth, fromDay, 00, 00) // backtest start window finish = timestamp(toYear, toMonth, toDay, 23, 59) // backtest finish window window() => true // create function "within window of time" //------- define the global variables ------ var bool long = true var bool stoppedOutLong = false var bool stoppedOutShort = false //--------- Colors --------------- //TrendColor = RSIoverBought and (price[1] > BBupper and price < BBupper) and BBbasis < BBbasis[1] ? color.red : RSIoverSold and (price[1] < BBlower and price > BBlower) and BBbasis > BBbasis[1] ? color.green : na //bgcolor(switch2?(color.new(TrendColor,50)):na) //--------- calculate the input/output points ----------- longProfitPrice = strategy.position_avg_price * (1 + tp) // tp -> take profit percentage longStopPrice = strategy.position_avg_price * (1 - sl) // sl -> stop loss percentage shortProfitPrice = strategy.position_avg_price * (1 - tp) shortStopPrice = strategy.position_avg_price * (1 + sl) //---------- RSI + Bollinger Bands Strategy ------------- vrsi = ta.rsi(price, RSIlength) rsiCrossOver = ta.crossover(vrsi, RSIoverSold) rsiCrossUnder = ta.crossunder(vrsi, RSIoverBought) OTTCrossOver = ta.crossover(src, OTTlower) OTTCrossUnder = ta.crossunder(src, OTTupper) if (not na(vrsi)) if rsiCrossOver and OTTCrossOver long := true if rsiCrossUnder and OTTCrossUnder long := false //------- define the global variables ------ buySignall = false sellSignall = false //------------------- determine buy and sell points --------------------- buySignall := window() and long and (not stoppedOutLong) sellSignall := window() and (not long) and (not stoppedOutShort) //---------- execute the strategy ----------------- if(isEntryLong and isEntryShort) if long strategy.entry("LONG", strategy.long, when = buySignall, comment = "ENTER LONG") stoppedOutLong := true stoppedOutShort := false else strategy.entry("SHORT", strategy.short, when = sellSignall, comment = "ENTER SHORT") stoppedOutLong := false stoppedOutShort := true else if(isEntryLong) strategy.entry("LONG", strategy.long, when = buySignall) strategy.close("LONG", when = sellSignall) if long stoppedOutLong := true else stoppedOutLong := false else if(isEntryShort) strategy.entry("SHORT", strategy.short, when = sellSignall) strategy.close("SHORT", when = buySignall) if not long stoppedOutShort := true else stoppedOutShort := false //----------------- take profit and stop loss ----------------- if(tp>0.0 and sl>0.0) if ( strategy.position_size > 0 ) strategy.exit(id="LONG", limit=longProfitPrice, stop=longStopPrice, comment="Long TP/SL Trigger") else if ( strategy.position_size < 0 ) strategy.exit(id="SHORT", limit=shortProfitPrice, stop=shortStopPrice, comment="Short TP/SL Trigger") else if(tp>0.0) if ( strategy.position_size > 0 ) strategy.exit(id="LONG", limit=longProfitPrice, comment="Long TP Trigger") else if ( strategy.position_size < 0 ) strategy.exit(id="SHORT", limit=shortProfitPrice, comment="Short TP Trigger") else if(sl>0.0) if ( strategy.position_size > 0 ) strategy.exit(id="LONG", stop=longStopPrice, comment="Long SL Trigger") else if ( strategy.position_size < 0 ) strategy.exit(id="SHORT", stop=shortStopPrice, comment="Short SL Trigger")