This strategy is an improvement of traditional moving average strategies, using Ichimoku Cloud indicator to help determine bullish and bearish bias. It identifies potential trend reversal points through price breakouts and moving average crossovers, enabling the capture of low-risk trading opportunities.
The Ichimoku Cloud consists of the tenkan line, kijun line, chikou line and senkou lines. Golden cross and dead cross signals are generated when the tenkan line crosses over or under the kijun line. Price breakouts of the Cloud act as entry signals, while the kijun and senkou lines that form the Cloud act as stop loss lines.
Specifically, the long entry signal is triggered when the tenkan line crosses over the kijun line and the price breaks above the top of the Cloud. After entering long, if the price breaks below the bottom of the Cloud, the position will be stopped out. The short entry and stop loss rules are similar.
Compared with traditional moving average strategies, this strategy has the following advantages:
The main risks of this strategy include:
Solutions:
This strategy can be further improved by:
In conclusion, this is an overall reliable, low-risk trend following strategy. By incorporating Ichimoku Cloud on top of moving averages, it helps filter out some false signals. The Cloud stop loss also makes it robust in terms of risk management. Further optimizations may lead to more consistent alpha generation.
/*backtest start: 2024-01-01 00:00:00 end: 2024-01-31 23:59:59 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 // ----------------------------------------------------------------------------- // Copyright © 2024 Skyrex, LLC. All rights reserved. // ----------------------------------------------------------------------------- // Version: v2 // Release: Jan 19, 2024 strategy(title = "Advanced Ichimoku Clouds Strategy Long and Short", shorttitle = "Ichimoku Strategy Long and Short", overlay = true, format = format.inherit, pyramiding = 1, calc_on_order_fills = false, calc_on_every_tick = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, initial_capital = 10000, currency = currency.NONE, commission_type = strategy.commission.percent, commission_value = 0) // Trading Period Settings lookBackPeriodStart = input(title="Trade Start Date/Time", defval = timestamp('2023-01-01T00:00:00'), group = "Trading Period") lookBackPeriodStop = input(title="Trade Stop Date/Time", defval = timestamp('2025-01-01T00:00:00'), group = "Trading Period") // Trading Mode tradingMode = input.string("Long", "Trading Mode", options = ["Long", "Short"], group = "Position side") // Long Mode Signal Options entrySignalOptionsLong = input.string("Bullish All", "Select Entry Signal (Long)", options = ["None", "Bullish Strong", "Bullish Neutral", "Bullish Weak", "Bullish Strong and Neutral", "Bullish Neutral and Weak", "Bullish Strong and Weak", "Bullish All"], group = "Long Mode Signals - set up if Trading Mode: Long") exitSignalOptionsLong = input.string("Bearish Weak", "Select Exit Signal (Long)", options = ["None", "Bearish Strong", "Bearish Neutral", "Bearish Weak", "Bearish Strong and Neutral", "Bearish Neutral and Weak", "Bearish Strong and Weak", "Bearish All"], group = "Long Mode Signals - set up if Trading Mode: Long") // Short Mode Signal Options entrySignalOptionsShort = input.string("None", "Select Entry Signal (Short)", options = ["None", "Bearish Strong", "Bearish Neutral", "Bearish Weak", "Bearish Strong and Neutral", "Bearish Neutral and Weak", "Bearish Strong and Weak", "Bearish All"], group = "Short Mode Signals - set up if Trading Mode: Short") exitSignalOptionsShort = input.string("None", "Select Exit Signal (Short)", options = ["None", "Bullish Strong", "Bullish Neutral", "Bullish Weak", "Bullish Strong and Neutral", "Bullish Neutral and Weak", "Bullish Strong and Weak", "Bullish All"], group = "Short Mode Signals - set up if Trading Mode: Short") // Risk Management Settings takeProfitPct = input.float(7, "Take Profit, % (0 - disabled)", minval = 0, step = 0.1, group = "Risk Management") stopLossPct = input.float(3.5, "Stop Loss, % (0 - disabled)", minval = 0, step = 0.1, group = "Risk Management") // Indicator Settings tenkanPeriods = input.int(9, "Tenkan", minval=1, group="Indicator Settings") kijunPeriods = input.int(26, "Kijun", minval=1, group="Indicator Settings") chikouPeriods = input.int(52, "Chikou", minval=1, group="Indicator Settings") displacement = input.int(26, "Offset", minval=1, group="Indicator Settings") // Display Settings showTenkan = input(false, "Show Tenkan Line", group = "Display Settings") showKijun = input(false, "Show Kijun Line", group = "Display Settings") showSenkouA = input(true, "Show Senkou A Line", group = "Display Settings") showSenkouB = input(true, "Show Senkou B Line", group = "Display Settings") showChikou = input(false, "Show Chikou Line", group = "Display Settings") // Function to convert percentage to price points based on entry price pctToPoints(pct) => strategy.position_avg_price * pct / 100 // Colors and Transparency Level transparencyLevel = 90 colorGreen = color.new(#36a336, 23) colorRed = color.new(#d82727, 47) colorTenkanViolet = color.new(#9400D3, 0) colorKijun = color.new(#fdd8a0, 0) colorLime = color.new(#006400, 0) colorMaroon = color.new(#8b0000, 0) colorGreenTransparent = color.new(colorGreen, transparencyLevel) colorRedTransparent = color.new(colorRed, transparencyLevel) // Ichimoku Calculations donchian(len) => math.avg(ta.lowest(len), ta.highest(len)) tenkan = donchian(tenkanPeriods) kijun = donchian(kijunPeriods) senkouA = math.avg(tenkan, kijun) senkouB = donchian(chikouPeriods) displacedSenkouA = senkouA[displacement - 1] displacedSenkouB = senkouB[displacement - 1] // Plot Ichimoku Lines plot(showTenkan ? tenkan : na, color=colorTenkanViolet, title = "Tenkan", linewidth=2) plot(showKijun ? kijun : na, color=colorKijun, title = "Kijun", linewidth=2) plot(showChikou ? close : na, offset=-displacement, color = colorLime, title = "Chikou", linewidth=1) p1 = plot(showSenkouA ? senkouA : na, offset=displacement - 1, color=colorGreen, title = "Senkou A", linewidth=2) p2 = plot(showSenkouB ? senkouB : na, offset=displacement - 1, color=colorRed, title = "Senkou B", linewidth=2) fill(p1, p2, color=senkouA > senkouB ? colorGreenTransparent : colorRedTransparent) // Signal Calculations bullishSignal = ta.crossover(tenkan, kijun) bearishSignal = ta.crossunder(tenkan, kijun) bullishSignalValues = bullishSignal ? tenkan : na bearishSignalValues = bearishSignal ? tenkan : na strongBullishSignal = bullishSignalValues > displacedSenkouA and bullishSignalValues > displacedSenkouB neutralBullishSignal = ((bullishSignalValues > displacedSenkouA and bullishSignalValues < displacedSenkouB) or (bullishSignalValues < displacedSenkouA and bullishSignalValues > displacedSenkouB)) weakBullishSignal = bullishSignalValues < displacedSenkouA and bullishSignalValues < displacedSenkouB strongBearishSignal = bearishSignalValues < displacedSenkouA and bearishSignalValues < displacedSenkouB neutralBearishSignal = ((bearishSignalValues > displacedSenkouA and bearishSignalValues < displacedSenkouB) or (bearishSignalValues < displacedSenkouA and bearishSignalValues > displacedSenkouB)) weakBearishSignal = bearishSignalValues > displacedSenkouA and bearishSignalValues > displacedSenkouB // Functions to determine entry and exit conditions for Long and Short isEntrySignalLong() => entryCondition = false if entrySignalOptionsLong == "None" entryCondition := false else if entrySignalOptionsLong == "Bullish Strong" entryCondition := strongBullishSignal else if entrySignalOptionsLong == "Bullish Neutral" entryCondition := neutralBullishSignal else if entrySignalOptionsLong == "Bullish Weak" entryCondition := weakBullishSignal else if entrySignalOptionsLong == "Bullish Strong and Neutral" entryCondition := strongBullishSignal or neutralBullishSignal else if entrySignalOptionsLong == "Bullish Neutral and Weak" entryCondition := neutralBullishSignal or weakBullishSignal else if entrySignalOptionsLong == "Bullish Strong and Weak" entryCondition := strongBullishSignal or weakBullishSignal else if entrySignalOptionsLong == "Bullish All" entryCondition := strongBullishSignal or neutralBullishSignal or weakBullishSignal entryCondition isExitSignalLong() => exitCondition = false if exitSignalOptionsLong == "None" exitCondition := false else if exitSignalOptionsLong == "Bearish Strong" exitCondition := strongBearishSignal else if exitSignalOptionsLong == "Bearish Neutral" exitCondition := neutralBearishSignal else if exitSignalOptionsLong == "Bearish Weak" exitCondition := weakBearishSignal else if exitSignalOptionsLong == "Bearish Strong and Neutral" exitCondition := strongBearishSignal or neutralBearishSignal else if exitSignalOptionsLong == "Bearish Neutral and Weak" exitCondition := neutralBearishSignal or weakBearishSignal else if exitSignalOptionsLong == "Bearish Strong and Weak" exitCondition := strongBearishSignal or weakBearishSignal else if exitSignalOptionsLong == "Bearish All" exitCondition := strongBearishSignal or neutralBearishSignal or weakBearishSignal exitCondition isEntrySignalShort() => entryCondition = false if entrySignalOptionsShort == "None" entryCondition := false else if entrySignalOptionsShort == "Bearish Strong" entryCondition := strongBearishSignal else if entrySignalOptionsShort == "Bearish Neutral" entryCondition := neutralBearishSignal else if entrySignalOptionsShort == "Bearish Weak" entryCondition := weakBearishSignal else if entrySignalOptionsShort == "Bearish Strong and Neutral" entryCondition := strongBearishSignal or neutralBearishSignal else if entrySignalOptionsShort == "Bearish Neutral and Weak" entryCondition := neutralBearishSignal or weakBearishSignal else if entrySignalOptionsShort == "Bearish Strong and Weak" entryCondition := strongBearishSignal or weakBearishSignal else if entrySignalOptionsShort == "Bearish All" entryCondition := strongBearishSignal or neutralBearishSignal or weakBearishSignal entryCondition isExitSignalShort() => exitCondition = false if exitSignalOptionsShort == "None" exitCondition := false else if exitSignalOptionsShort == "Bullish Strong" exitCondition := strongBullishSignal else if exitSignalOptionsShort == "Bullish Neutral" exitCondition := neutralBullishSignal else if exitSignalOptionsShort == "Bullish Weak" exitCondition := weakBullishSignal else if exitSignalOptionsShort == "Bullish Strong and Neutral" exitCondition := strongBullishSignal or neutralBullishSignal else if exitSignalOptionsShort == "Bullish Neutral and Weak" exitCondition := neutralBullishSignal or weakBullishSignal else if exitSignalOptionsShort == "Bullish Strong and Weak" exitCondition := strongBullishSignal or weakBullishSignal else if exitSignalOptionsShort == "Bullish All" exitCondition := strongBullishSignal or neutralBullishSignal or weakBullishSignal exitCondition // Strategy logic for entries and exits if true if tradingMode == "Long" takeProfitLevelLong = strategy.position_avg_price * (1 + takeProfitPct / 100) stopLossLevelLong = strategy.position_avg_price * (1 - stopLossPct / 100) if isEntrySignalLong() strategy.entry("Enter Long", strategy.long) if (takeProfitPct > 0 and close >= takeProfitLevelLong) or (stopLossPct > 0 and close <= stopLossLevelLong) or (exitSignalOptionsLong != "None" and isExitSignalLong()) strategy.close("Enter Long", comment="Exit Long") else if tradingMode == "Short" takeProfitLevelShort = strategy.position_avg_price * (1 - takeProfitPct / 100) stopLossLevelShort = strategy.position_avg_price * (1 + stopLossPct / 100) if isEntrySignalShort() strategy.entry("Enter Short", strategy.short) if (takeProfitPct > 0 and close <= takeProfitLevelShort) or (stopLossPct > 0 and close >= stopLossLevelShort) or (exitSignalOptionsShort != "None" and isExitSignalShort()) strategy.close("Enter Short", comment="Exit Short")template: strategy.tpl:40:21: executing "strategy.tpl" at <.api.GetStrategyListByName>: wrong number of args for GetStrategyListByName: want 7 got 6