Ichimoku Adx Strategy
Strategy based on Ichimoku Cloud and ADX indicators. Entry criteria:
Long: Price > Kumo (cloud) && Tenkan > Kijun && ADX > 25 (uptrend with strong movement) Short: Price < Kumo (cloud) && Tenkan < Kijun && ADX > 25 (downtrend with strong movement) Exit criteria: Long: Price < Kumo (price falls below cloud) Short: Price > Kumo (price rises above cloud)
Testing indicates an average annual return of about 187%. It performs best in the stocks market.
This strategy blends Ichimoku Cloud signals with ADX to filter for powerful trends. Trades occur when price breaks above or below the cloud with ADX confirming.
It favors traders who prefer structured trend setups. The cloud itself acts as the stop against adverse swings.
Details
- Entry Criteria:
- Long:
Price > Cloud && Tenkan > Kijun && ADX > AdxThreshold
- Short:
Price < Cloud && Tenkan < Kijun && ADX > AdxThreshold
- Long/Short: Both
- Exit Criteria:
- Price crosses the cloud opposite
- Stops: Uses Ichimoku cloud for trailing stop
- Default Values:
TenkanPeriod = 9
KijunPeriod = 26
SenkouSpanBPeriod = 52
AdxPeriod = 14
AdxThreshold = 25m
CandleType = TimeSpan.FromMinutes(15).TimeFrame()
A long closes when price closes below the cloud and a short when it closes above it. An entry signal against an open position reverses it.
- Filters:
- Category: Trend
- Direction: Both
- Indicators: Ichimoku Cloud, ADX
- Stops: Yes
- Complexity: Intermediate
- Timeframe: Mid-term
- Seasonality: No
- Neural Networks: No
- Divergence: No
- Risk Level: Medium
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Ichimoku ADX strategy.
/// A close above the cloud with Tenkan-sen above Kijun-sen while ADX is above AdxThreshold goes long, a close below the cloud with Tenkan-sen
/// below Kijun-sen under the same ADX condition goes short, reversing an opposite position. The cloud is the trailing stop: a long closes
/// when price closes below the cloud and a short when it closes above it.
/// </summary>
public class IchimokuAdxStrategy : Strategy
{
private readonly StrategyParam<int> _tenkanPeriod;
private readonly StrategyParam<int> _kijunPeriod;
private readonly StrategyParam<int> _senkouSpanBPeriod;
private readonly StrategyParam<int> _adxPeriod;
private readonly StrategyParam<decimal> _adxThreshold;
private readonly StrategyParam<DataType> _candleType;
/// <summary>
/// Period of Tenkan-sen.
/// </summary>
public int TenkanPeriod
{
get => _tenkanPeriod.Value;
set => _tenkanPeriod.Value = value;
}
/// <summary>
/// Period of Kijun-sen.
/// </summary>
public int KijunPeriod
{
get => _kijunPeriod.Value;
set => _kijunPeriod.Value = value;
}
/// <summary>
/// Period of Senkou Span B.
/// </summary>
public int SenkouSpanBPeriod
{
get => _senkouSpanBPeriod.Value;
set => _senkouSpanBPeriod.Value = value;
}
/// <summary>
/// Period of ADX.
/// </summary>
public int AdxPeriod
{
get => _adxPeriod.Value;
set => _adxPeriod.Value = value;
}
/// <summary>
/// ADX level of a strong trend.
/// </summary>
public decimal AdxThreshold
{
get => _adxThreshold.Value;
set => _adxThreshold.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public IchimokuAdxStrategy()
{
_tenkanPeriod = Param(nameof(TenkanPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Tenkan Period", "Period of Tenkan-sen", "Ichimoku");
_kijunPeriod = Param(nameof(KijunPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Kijun Period", "Period of Kijun-sen", "Ichimoku");
_senkouSpanBPeriod = Param(nameof(SenkouSpanBPeriod), 52)
.SetGreaterThanZero()
.SetDisplay("Senkou Span B Period", "Period of Senkou Span B", "Ichimoku");
_adxPeriod = Param(nameof(AdxPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ADX Period", "Period of ADX", "ADX");
_adxThreshold = Param(nameof(AdxThreshold), 25m)
.SetDisplay("ADX Threshold", "ADX level of a strong trend", "ADX");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ichimoku = new Ichimoku
{
Tenkan = { Length = TenkanPeriod },
Kijun = { Length = KijunPeriod },
SenkouB = { Length = SenkouSpanBPeriod }
};
var adx = new AverageDirectionalIndex { Length = AdxPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(ichimoku, adx, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ichimoku);
DrawOwnTrades(area);
var oscillators = CreateChartArea();
if (oscillators != null)
{
DrawIndicator(oscillators, adx);
}
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue ichimokuValue, IIndicatorValue adxValue)
{
if (candle.State != CandleStates.Finished)
return;
if (ichimokuValue is not IIchimokuValue { Tenkan: decimal tenkan, Kijun: decimal kijun, SenkouA: decimal senkouA, SenkouB: decimal senkouB })
return;
if (!adxValue.IsFormed || adxValue is not AverageDirectionalIndexValue { MovingAverage: decimal strength })
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
var cloudTop = Math.Max(senkouA, senkouB);
var cloudBottom = Math.Min(senkouA, senkouB);
var strong = strength > AdxThreshold;
if (close > cloudTop && tenkan > kijun && strong && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (close < cloudBottom && tenkan < kijun && strong && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
else if (Position > 0 && close < cloudBottom)
SellMarket(Position);
else if (Position < 0 && close > cloudTop)
BuyMarket(-Position);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Ichimoku, AverageDirectionalIndex
from StockSharp.Algo.Strategies import Strategy
class ichimoku_adx_strategy(Strategy):
"""
Ichimoku ADX strategy.
A close above the cloud with Tenkan-sen above Kijun-sen while ADX is above AdxThreshold goes long, a close below the cloud with Tenkan-sen
below Kijun-sen under the same ADX condition goes short, reversing an opposite position. The cloud is the trailing stop: a long closes
when price closes below the cloud and a short when it closes above it.
"""
def __init__(self):
super(ichimoku_adx_strategy, self).__init__()
self._tenkan_period = self.Param("TenkanPeriod", 9).SetGreaterThanZero().SetDisplay("Tenkan Period", "Period of Tenkan-sen", "Ichimoku")
self._kijun_period = self.Param("KijunPeriod", 26).SetGreaterThanZero().SetDisplay("Kijun Period", "Period of Kijun-sen", "Ichimoku")
self._senkou_span_b_period = self.Param("SenkouSpanBPeriod", 52).SetGreaterThanZero().SetDisplay("Senkou Span B Period", "Period of Senkou Span B", "Ichimoku")
self._adx_period = self.Param("AdxPeriod", 14).SetGreaterThanZero().SetDisplay("ADX Period", "Period of ADX", "ADX")
self._adx_threshold = self.Param("AdxThreshold", 25.0).SetDisplay("ADX Threshold", "ADX level of a strong trend", "ADX")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))).SetDisplay("Candle Type", "Type of candles to use", "General")
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(ichimoku_adx_strategy, self).OnStarted2(time)
ichimoku = Ichimoku()
ichimoku.Tenkan.Length = self._tenkan_period.Value
ichimoku.Kijun.Length = self._kijun_period.Value
ichimoku.SenkouB.Length = self._senkou_span_b_period.Value
adx = AverageDirectionalIndex()
adx.Length = self._adx_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(ichimoku, adx, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ichimoku)
self.DrawOwnTrades(area)
oscillators = self.CreateChartArea()
if oscillators is not None:
self.DrawIndicator(oscillators, adx)
def _process_candle(self, candle, ichimoku_value, adx_value):
if candle.State != CandleStates.Finished:
return
tenkan = ichimoku_value.Tenkan
kijun = ichimoku_value.Kijun
senkou_a = ichimoku_value.SenkouA
senkou_b = ichimoku_value.SenkouB
if tenkan is None or kijun is None or senkou_a is None or senkou_b is None:
return
if not adx_value.IsFormed or adx_value.MovingAverage is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
close = candle.ClosePrice
cloud_top = senkou_a if senkou_a > senkou_b else senkou_b
cloud_bottom = senkou_b if senkou_a > senkou_b else senkou_a
strong = adx_value.MovingAverage > Decimal(self._adx_threshold.Value)
if close > cloud_top and tenkan > kijun and strong and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif close < cloud_bottom and tenkan < kijun and strong and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
elif self.Position > 0 and close < cloud_bottom:
self.SellMarket(self.Position)
elif self.Position < 0 and close > cloud_top:
self.BuyMarket(-self.Position)
def CreateClone(self):
return ichimoku_adx_strategy()