This strategy combines the TSI, CCI indicators and Hull Moving Average to determine and trade trends. TSI and CCI identify price waves while Hull MA confirms trend direction. Profit targets are set when long/short signals occur for profitable exits.
The TSI curve and signal line are calculated. Long signal when curve crosses above line, short on downward crossover. CCI indicates overbought/oversold levels. Price crossing above Hull MA suggests bull market, and below for bear market. Long/short trades are taken when TSI, CCI and Hull MA breakout conditions align. Profit targets are set to exit positions when reached.
Risks can be reduced by tuning indicators, optimizing profit algorithms etc.
This multiple indicator strategy with profit targeting shows good backtest results. Further refinements like parameter optimization can make it a stable quant trading system.
/*backtest start: 2023-08-18 00:00:00 end: 2023-09-17 00:00:00 period: 3h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=4 strategy(title="TSI CCI Hull", shorttitle="TSICCIHULL", default_qty_type=strategy.percent_of_equity, default_qty_value=100, calc_on_order_fills= false, calc_on_every_tick=true, pyramiding=0, commission_type=strategy.commission.percent, commission_value=0.018) long = input(title="Long Length", type=input.integer, defval=50) short = input(title="Short Length", type=input.integer, defval=50) signal = input(title="Signal Length", type=input.integer, defval=25) price=input(title="Source",type=input.source,defval=close) Period=input(26, minval=1) lineupper = input(title="Upper Line", type=input.integer, defval=100) linelower = input(title="Lower Line", type=input.integer, defval=-100) p=price length= Period double_smooth(src, long, short) => fist_smooth = ema(src, long) ema(fist_smooth, short) pc = change(price) double_smoothed_pc = double_smooth(pc, long, short) double_smoothed_abs_pc = double_smooth(abs(pc), long, short) tsi_value = 100 * (double_smoothed_pc / double_smoothed_abs_pc) keh = tsi_value*5 > linelower ? color.red : color.lime teh = ema(tsi_value*5, signal*5) > lineupper ? color.red : color.lime meh = ema(tsi_value*5, signal*5) > tsi_value*5 ? color.red : color.lime i1=plot(tsi_value*5, title="TSI Value", color=color.black, linewidth=1,transp=100) i2=plot(ema(tsi_value*5, signal*5), title="TSI Signal", color=color.black, linewidth=1,transp=100) fill(i1,i2,color=meh,transp=85) plot(cross(tsi_value*5, ema(tsi_value*5, signal*5)) ? tsi_value*5 : na, style=plot.style_circles, color=color.black, linewidth=10) plot(cross(tsi_value*5, ema(tsi_value*5, signal*5)) ? tsi_value*5 : na, style=plot.style_circles, color=color.white, linewidth=8,transp=0) plot(cross(tsi_value*5, ema(tsi_value*5, signal*5)) ? tsi_value*5 : na, style=plot.style_circles, color=meh, linewidth=5) n2ma = 2 * wma(p, round(length / 2)) nma = wma(p, length) diff = n2ma - nma sqn = round(sqrt(length)) n1 = wma(diff, sqn) cci = (p - n1) / (0.015 * dev(p, length)) c = cci > 0 ? color.lime : color.red c1 = cci > 20 ? color.lime : color.silver c2 = cci < -20 ? color.red : color.silver cc=plot(cci, color=c, title="CCI Line", linewidth=2) cc2=plot(cci[1], color=color.gray, linewidth=1,transp=100) fill(cc,cc2,color=c,transp=85) plot(cross(20, cci) ? 20 : na, style=plot.style_cross,title="CCI cross UP", color=c1, linewidth=2,transp=100,offset=-2) plot(cross(-20, cci) ? -20 : na, style=plot.style_cross,title="CCI cross down", color=c2, linewidth=2,transp=100,offset=-2) TSI1=ema(tsi_value*5, signal*5) TSI2=ema(tsi_value*5, signal*5)[2] hullma_smoothed = wma(2*wma(n1, Period/2)-wma(n1, Period), round(sqrt(Period))) //plot(hullma_smoothed*200) // Make input options that configure backtest date range startDate = input(title="Start Date", type=input.integer, defval=1, minval=1, maxval=31) startMonth = input(title="Start Month", type=input.integer, defval=1, minval=1, maxval=12) startYear = input(title="Start Year", type=input.integer, defval=2018, minval=1800, maxval=2100) endDate = input(title="End Date", type=input.integer, defval=1, minval=1, maxval=31) endMonth = input(title="End Month", type=input.integer, defval=7, minval=1, maxval=12) endYear = input(title="End Year", type=input.integer, defval=9999, minval=1800, maxval=2100) // Look if the close time of the current bar // falls inside the date range inDateRange = (time >= timestamp(syminfo.timezone, startYear, startMonth, startDate, 0, 0)) and (time < timestamp(syminfo.timezone, endYear, endMonth, endDate, 0, 0)) LongProfitPercent=input(0.5) ShortProfitPercent=input(0.5) LP=(LongProfitPercent/100)+1 SP=(ShortProfitPercent/100)+1 LongProfitSource=input(title="profit long source",type=input.source,defval=close) ShortProfitSource=input(title="profit short source",type=input.source,defval=close) longCondition = TSI1>TSI2 and hullma_smoothed<price and cci>0 shortCondition = TSI1<TSI2 and hullma_smoothed>price and cci<0 if (longCondition and cci>cci[1] and cci > 0 and n1>n1[1] and inDateRange) strategy.entry("buy", strategy.long) strategy.close("buy", when = shortCondition and cci<cci[1] and cci < 0 and n1<n1[1] or LongProfitSource>strategy.position_avg_price*LP and inDateRange) if (shortCondition and cci<cci[1] and cci < 0 and n1<n1[1] and inDateRange) strategy.entry("sell", strategy.short) strategy.close("sell", when = longCondition and cci>cci[1] and cci > 0 and n1>n1[1] or ShortProfitSource<strategy.position_avg_price/SP and inDateRange)