Индикатор Supertrend сочетает ATR и цену, формируя линию поддержки или сопротивления. Когда линия Supertrend переключается с одной стороны цены на другую, это указывает на возможное изменение тренда. Стратегия торгует такие переключения.
Тестирование показывает среднегодичную доходность около 151%. Стратегию лучше запускать на фондовом рынке.
На каждой свече ATR‑расчёт обновляет уровень Supertrend. Переход линии сверху цены вниз создаёт сигнал на покупку, а движение снизу вверх — на продажу. В образце кода стопы не прописаны, поэтому выход осуществляется вручную или отдельным модулем управления рисками.
Индикатор может быстро реагировать на волатильность, поэтому трейдеры часто используют дополнительные фильтры, чтобы избежать ложных сигналов.
Детали
Условия входа: Supertrend меняет сторону относительно цены.
Длинные/короткие: обе стороны.
Условия выхода: вручную или внешний стоп.
Стопы: не определены.
Значения по умолчанию:
Period = 10
Multiplier = 3.0
CandleType = 15 минут
Фильтры:
Категория: следование за трендом
Направление: оба
Индикаторы: Supertrend
Стопы: опционально
Сложность: базовая
Таймфрейм: внутридневной
Сезонность: нет
Нейросети: нет
Дивергенция: нет
Уровень риска: средний
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>
/// Supertrend Reversal strategy.
/// Uses the built-in SuperTrend indicator.
/// Enters long when SuperTrend flips to uptrend (below price).
/// Enters short when SuperTrend flips to downtrend (above price).
/// Uses cooldown to control trade frequency.
/// </summary>
public class SupertrendReversalStrategy : Strategy
{
private readonly StrategyParam<int> _period;
private readonly StrategyParam<decimal> _multiplier;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private bool? _prevIsUpTrend;
private int _cooldown;
/// <summary>
/// ATR period for SuperTrend.
/// </summary>
public int Period
{
get => _period.Value;
set => _period.Value = value;
}
/// <summary>
/// ATR multiplier for SuperTrend.
/// </summary>
public decimal Multiplier
{
get => _multiplier.Value;
set => _multiplier.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown bars.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public SupertrendReversalStrategy()
{
_period = Param(nameof(Period), 10)
.SetRange(7, 20)
.SetDisplay("Period", "ATR period for SuperTrend", "SuperTrend");
_multiplier = Param(nameof(Multiplier), 3.0m)
.SetRange(2.0m, 4.0m)
.SetDisplay("Multiplier", "ATR multiplier for SuperTrend", "SuperTrend");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_cooldownBars = Param(nameof(CooldownBars), 500)
.SetRange(1, 1000)
.SetDisplay("Cooldown Bars", "Bars to wait between trades", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevIsUpTrend = null;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevIsUpTrend = null;
_cooldown = 0;
var superTrend = new SuperTrend
{
Length = Period,
Multiplier = Multiplier
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(superTrend, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, superTrend);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!stValue.IsFormed)
return;
var stTyped = (SuperTrendIndicatorValue)stValue;
var isUpTrend = stTyped.IsUpTrend;
if (_prevIsUpTrend == null)
{
_prevIsUpTrend = isUpTrend;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevIsUpTrend = isUpTrend;
return;
}
// SuperTrend flipped to uptrend = bullish
var flippedUp = _prevIsUpTrend == false && isUpTrend;
// SuperTrend flipped to downtrend = bearish
var flippedDown = _prevIsUpTrend == true && !isUpTrend;
if (Position == 0 && flippedUp)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (Position == 0 && flippedDown)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position > 0 && flippedDown)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && flippedUp)
{
BuyMarket();
_cooldown = CooldownBars;
}
_prevIsUpTrend = 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
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SuperTrend
from StockSharp.Algo.Strategies import Strategy
class supertrend_reversal_strategy(Strategy):
"""
Supertrend Reversal strategy.
Enters long when SuperTrend flips to uptrend (below price).
Enters short when SuperTrend flips to downtrend (above price).
Uses cooldown to control trade frequency.
"""
def __init__(self):
super(supertrend_reversal_strategy, self).__init__()
self._period = self.Param("Period", 10).SetDisplay("Period", "ATR period for SuperTrend", "SuperTrend")
self._multiplier = self.Param("Multiplier", 3.0).SetDisplay("Multiplier", "ATR multiplier for SuperTrend", "SuperTrend")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._cooldown_bars = self.Param("CooldownBars", 500).SetDisplay("Cooldown Bars", "Bars to wait between trades", "General")
self._prev_is_up_trend = None
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(supertrend_reversal_strategy, self).OnReseted()
self._prev_is_up_trend = None
self._cooldown = 0
def OnStarted2(self, time):
super(supertrend_reversal_strategy, self).OnStarted2(time)
self._prev_is_up_trend = None
self._cooldown = 0
st = SuperTrend()
st.Length = self._period.Value
st.Multiplier = self._multiplier.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(st, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, st)
self.DrawOwnTrades(area)
def _process_candle(self, candle, st_iv):
if candle.State != CandleStates.Finished:
return
if not st_iv.IsFormed:
return
is_up_trend = st_iv.IsUpTrend
if self._prev_is_up_trend is None:
self._prev_is_up_trend = is_up_trend
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_is_up_trend = is_up_trend
return
cd = self._cooldown_bars.Value
# SuperTrend flipped to uptrend = bullish
flipped_up = self._prev_is_up_trend == False and is_up_trend
# SuperTrend flipped to downtrend = bearish
flipped_down = self._prev_is_up_trend == True and not is_up_trend
if self.Position == 0 and flipped_up:
self.BuyMarket()
self._cooldown = cd
elif self.Position == 0 and flipped_down:
self.SellMarket()
self._cooldown = cd
elif self.Position > 0 and flipped_down:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and flipped_up:
self.BuyMarket()
self._cooldown = cd
self._prev_is_up_trend = is_up_trend
def CreateClone(self):
return supertrend_reversal_strategy()