Supertrend Adx Strategy
Strategy based on Supertrend indicator and ADX for trend strength confirmation. Entry criteria: Long: Price > Supertrend && ADX > 25 (uptrend with strong movement) Short: Price < Supertrend && ADX > 25 (downtrend with strong movement) Exit criteria: Long: Price < Supertrend (price falls below Supertrend) Short: Price > Supertrend (price rises above Supertrend)
Testing indicates an average annual return of about 166%. It performs best in the stocks market.
Supertrend provides a volatility-adjusted path while ADX confirms the power of the move. Trades take place when both indicators line up.
For those aiming to ride strong trends with trailing stops. ATR determines stop placement.
Details
- Entry Criteria:
- Long:
Close > Supertrend && ADX > AdxThreshold - Short:
Close < Supertrend && ADX > AdxThreshold
- Long:
- Long/Short: Both
- Exit Criteria: Supertrend reversal
- Stops: Uses Supertrend as trailing stop
- Default Values:
SupertrendPeriod= 10SupertrendMultiplier= 3.0mAdxPeriod= 14AdxThreshold= 25mCandleType= TimeSpan.FromMinutes(15).TimeFrame()
- Filters:
- Category: Trend
- Direction: Both
- Indicators: Supertrend, ADX
- Stops: Yes
- Complexity: Intermediate
- Timeframe: Mid-term
- Seasonality: No
- Neural Networks: No
- Divergence: No
- Risk Level: Medium
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on Supertrend indicator and ADX for trend strength confirmation.
///
/// Entry criteria:
/// Long: Price > Supertrend && ADX > 25 (uptrend with strong movement)
/// Short: Price < Supertrend && ADX > 25 (downtrend with strong movement)
///
/// Exit criteria:
/// Long: Price < Supertrend (price falls below Supertrend)
/// Short: Price > Supertrend (price rises above Supertrend)
/// </summary>
public class SupertrendAdxStrategy : Strategy
{
private readonly StrategyParam<int> _supertrendPeriod;
private readonly StrategyParam<decimal> _supertrendMultiplier;
private readonly StrategyParam<int> _adxPeriod;
private readonly StrategyParam<decimal> _adxThreshold;
private readonly StrategyParam<int> _cooldownBars;
private readonly StrategyParam<DataType> _candleType;
private decimal _lastSupertrend;
private bool _isAboveSupertrend;
private int _cooldown;
/// <summary>
/// Period for Supertrend calculation.
/// </summary>
public int SupertrendPeriod
{
get => _supertrendPeriod.Value;
set => _supertrendPeriod.Value = value;
}
/// <summary>
/// Multiplier for Supertrend calculation.
/// </summary>
public decimal SupertrendMultiplier
{
get => _supertrendMultiplier.Value;
set => _supertrendMultiplier.Value = value;
}
/// <summary>
/// Period for ADX calculation.
/// </summary>
public int AdxPeriod
{
get => _adxPeriod.Value;
set => _adxPeriod.Value = value;
}
/// <summary>
/// Threshold for ADX to confirm trend strength.
/// </summary>
public decimal AdxThreshold
{
get => _adxThreshold.Value;
set => _adxThreshold.Value = value;
}
/// <summary>
/// Bars to wait between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Type of candles to use.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public SupertrendAdxStrategy()
{
_supertrendPeriod = Param(nameof(SupertrendPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Supertrend Period", "Period for ATR calculation in Supertrend", "Indicators")
.SetOptimize(5, 20, 5);
_supertrendMultiplier = Param(nameof(SupertrendMultiplier), 3.0m)
.SetGreaterThanZero()
.SetDisplay("Supertrend Multiplier", "Multiplier for ATR in Supertrend", "Indicators")
.SetOptimize(1.0m, 5.0m, 1.0m);
_adxPeriod = Param(nameof(AdxPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ADX Period", "Period for ADX calculation", "Indicators")
.SetOptimize(7, 21, 7);
_adxThreshold = Param(nameof(AdxThreshold), 30m)
.SetGreaterThanZero()
.SetDisplay("ADX Threshold", "Minimum ADX value to confirm trend strength", "Indicators")
.SetOptimize(20m, 30m, 5m);
_cooldownBars = Param(nameof(CooldownBars), 50)
.SetRange(1, 100)
.SetDisplay("Cooldown Bars", "Bars between trades", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).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 OnReseted()
{
base.OnReseted();
_lastSupertrend = 0;
_isAboveSupertrend = false;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var supertrend = new SuperTrend { Length = SupertrendPeriod, Multiplier = SupertrendMultiplier };
var dummyEma = new ExponentialMovingAverage { Length = 10 };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(supertrend, dummyEma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, supertrend);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stVal, IIndicatorValue dummyVal)
{
if (candle.State != CandleStates.Finished)
return;
if (stVal is not SuperTrendIndicatorValue st)
return;
var isUpTrend = st.IsUpTrend;
var trendChanged = isUpTrend != _isAboveSupertrend && _lastSupertrend > 0;
if (_cooldown > 0)
_cooldown--;
if (_cooldown == 0 && trendChanged)
{
if (isUpTrend && Position <= 0)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (!isUpTrend && Position >= 0)
{
SellMarket();
_cooldown = CooldownBars;
}
}
_lastSupertrend = 1;
_isAboveSupertrend = isUpTrend;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SuperTrend, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class supertrend_adx_strategy(Strategy):
"""
Strategy based on Supertrend indicator trend direction changes.
Trades on supertrend trend flips with cooldown.
"""
def __init__(self):
super(supertrend_adx_strategy, self).__init__()
self._supertrend_period = self.Param("SupertrendPeriod", 10) \
.SetGreaterThanZero() \
.SetDisplay("Supertrend Period", "Period for ATR calculation in Supertrend", "Indicators")
self._supertrend_multiplier = self.Param("SupertrendMultiplier", 3.0) \
.SetGreaterThanZero() \
.SetDisplay("Supertrend Multiplier", "Multiplier for ATR in Supertrend", "Indicators")
self._adx_period = self.Param("AdxPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("ADX Period", "Period for ADX calculation", "Indicators")
self._adx_threshold = self.Param("AdxThreshold", 30.0) \
.SetGreaterThanZero() \
.SetDisplay("ADX Threshold", "Minimum ADX value to confirm trend strength", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 50) \
.SetRange(1, 100) \
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._candle_type = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._last_supertrend = 0
self._is_above_supertrend = False
self._cooldown = 0
@property
def CandleType(self):
return self._candle_type.Value
def OnReseted(self):
super(supertrend_adx_strategy, self).OnReseted()
self._last_supertrend = 0
self._is_above_supertrend = False
self._cooldown = 0
def OnStarted2(self, time):
super(supertrend_adx_strategy, self).OnStarted2(time)
self._last_supertrend = 0
self._is_above_supertrend = False
self._cooldown = 0
supertrend = SuperTrend()
supertrend.Length = self._supertrend_period.Value
supertrend.Multiplier = self._supertrend_multiplier.Value
dummyEma = ExponentialMovingAverage()
dummyEma.Length = 10
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(supertrend, dummyEma, self.ProcessCandle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, supertrend)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle, st_val, dummy_val):
if candle.State != CandleStates.Finished:
return
is_up_trend = st_val.IsUpTrend
trend_changed = is_up_trend != self._is_above_supertrend and self._last_supertrend > 0
if self._cooldown > 0:
self._cooldown -= 1
cooldown_val = int(self._cooldown_bars.Value)
if self._cooldown == 0 and trend_changed:
if is_up_trend and self.Position <= 0:
self.BuyMarket()
self._cooldown = cooldown_val
elif not is_up_trend and self.Position >= 0:
self.SellMarket()
self._cooldown = cooldown_val
self._last_supertrend = 1
self._is_above_supertrend = is_up_trend
def CreateClone(self):
return supertrend_adx_strategy()