Фильтр импульса Supertrend
Стратегия Supertrend Momentum Filter основана на индикаторах Supertrend и Momentum.
Сигналы формируются, когда индикаторы подтверждают фильтрованные входы на внутридневных данных (5м). Такой метод подходит активным трейдерам.
Стопы рассчитываются на основе кратных ATR и параметров SupertrendPeriod, SupertrendMultiplier. Настройте эти значения для баланса риска и прибыли.
Подробности
- Критерии входа: см. реализацию условий индикаторов.
- Длинные/короткие: обе стороны.
- Критерии выхода: противоположный сигнал или логика стопов.
- Стопы: да, расчёт на основе индикаторов.
- Значения по умолчанию:
SupertrendPeriod = 10SupertrendMultiplier = 3.0mMomentumPeriod = 14CandleType = TimeSpan.FromMinutes(5).TimeFrame()
- Фильтры:
- Категория: Следование за трендом
- Направление: Оба
- Индикаторы: несколько индикаторов
- Стопы: Да
- Сложность: Средняя
- Таймфрейм: Внутридневной (5м)
- Сезонность: Нет
- Нейронные сети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Trend-following strategy that trades SuperTrend direction only when momentum confirms acceleration.
/// </summary>
public class SupertrendWithMomentumStrategy : Strategy
{
private readonly StrategyParam<int> _supertrendPeriod;
private readonly StrategyParam<decimal> _supertrendMultiplier;
private readonly StrategyParam<int> _momentumPeriod;
private readonly StrategyParam<int> _cooldownBars;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private SuperTrend _supertrend;
private Momentum _momentum;
private decimal _prevMomentum;
private bool _isInitialized;
private int _cooldown;
/// <summary>
/// SuperTrend period.
/// </summary>
public int SupertrendPeriod
{
get => _supertrendPeriod.Value;
set => _supertrendPeriod.Value = value;
}
/// <summary>
/// SuperTrend multiplier.
/// </summary>
public decimal SupertrendMultiplier
{
get => _supertrendMultiplier.Value;
set => _supertrendMultiplier.Value = value;
}
/// <summary>
/// Momentum period.
/// </summary>
public int MomentumPeriod
{
get => _momentumPeriod.Value;
set => _momentumPeriod.Value = value;
}
/// <summary>
/// Bars to wait between orders.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Stop loss percentage.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes strategy parameters.
/// </summary>
public SupertrendWithMomentumStrategy()
{
_supertrendPeriod = Param(nameof(SupertrendPeriod), 10)
.SetRange(2, 50)
.SetDisplay("Supertrend Period", "Period of the SuperTrend indicator", "Indicators");
_supertrendMultiplier = Param(nameof(SupertrendMultiplier), 3m)
.SetRange(0.5m, 10m)
.SetDisplay("Supertrend Multiplier", "Multiplier of the SuperTrend indicator", "Indicators");
_momentumPeriod = Param(nameof(MomentumPeriod), 14)
.SetRange(2, 100)
.SetDisplay("Momentum Period", "Period of the Momentum indicator", "Indicators");
_cooldownBars = Param(nameof(CooldownBars), 84)
.SetRange(1, 500)
.SetDisplay("Cooldown Bars", "Bars to wait between orders", "Risk");
_stopLossPercent = Param(nameof(StopLossPercent), 2m)
.SetRange(0.5m, 10m)
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk");
_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()
{
if (Security != null)
yield return (Security, CandleType);
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_supertrend = null;
_momentum = null;
_prevMomentum = 0m;
_isInitialized = false;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
if (Security == null)
throw new InvalidOperationException("Security is not specified.");
_supertrend = new SuperTrend
{
Length = SupertrendPeriod,
Multiplier = SupertrendMultiplier,
};
_momentum = new Momentum { Length = MomentumPeriod };
_cooldown = 0;
_isInitialized = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_supertrend, _momentum, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _supertrend);
DrawIndicator(area, _momentum);
DrawOwnTrades(area);
}
StartProtection(new Unit(0, UnitTypes.Absolute), new Unit(StopLossPercent, UnitTypes.Percent), false);
}
private void ProcessCandle(ICandleMessage candle, decimal supertrendValue, decimal momentumValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_supertrend.IsFormed || !_momentum.IsFormed)
return;
if (ProcessState != ProcessStates.Started)
return;
if (!_isInitialized)
{
_prevMomentum = momentumValue;
_isInitialized = true;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevMomentum = momentumValue;
return;
}
var price = candle.ClosePrice;
var isAboveSupertrend = price > supertrendValue;
var isBelowSupertrend = price < supertrendValue;
var isMomentumRising = momentumValue > _prevMomentum;
var isMomentumFalling = momentumValue < _prevMomentum;
if (Position == 0)
{
if (isAboveSupertrend && isMomentumRising && momentumValue >= 100m)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (isBelowSupertrend && isMomentumFalling && momentumValue <= 100m)
{
SellMarket();
_cooldown = CooldownBars;
}
}
else if (Position > 0)
{
if (isBelowSupertrend || isMomentumFalling)
{
SellMarket(Math.Abs(Position));
_cooldown = CooldownBars;
}
}
else if (Position < 0)
{
if (isAboveSupertrend || isMomentumRising)
{
BuyMarket(Math.Abs(Position));
_cooldown = CooldownBars;
}
}
_prevMomentum = momentumValue;
}
}
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, Decimal
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import SuperTrend, Momentum
from StockSharp.Algo.Strategies import Strategy
class supertrend_momentum_filter_strategy(Strategy):
"""
Trend-following strategy that trades SuperTrend direction only when momentum confirms acceleration.
"""
def __init__(self):
super(supertrend_momentum_filter_strategy, self).__init__()
self._supertrend_period = self.Param("SupertrendPeriod", 10) \
.SetRange(2, 50) \
.SetDisplay("Supertrend Period", "Period of the SuperTrend indicator", "Indicators")
self._supertrend_multiplier = self.Param("SupertrendMultiplier", 3.0) \
.SetRange(0.5, 10.0) \
.SetDisplay("Supertrend Multiplier", "Multiplier of the SuperTrend indicator", "Indicators")
self._momentum_period = self.Param("MomentumPeriod", 14) \
.SetRange(2, 100) \
.SetDisplay("Momentum Period", "Period of the Momentum indicator", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 84) \
.SetRange(1, 500) \
.SetDisplay("Cooldown Bars", "Bars to wait between orders", "Risk")
self._stop_loss_percent = self.Param("StopLossPercent", 2.0) \
.SetRange(0.5, 10.0) \
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_momentum = 0.0
self._is_initialized = False
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(supertrend_momentum_filter_strategy, self).OnReseted()
self._prev_momentum = 0.0
self._is_initialized = False
self._cooldown = 0
def OnStarted2(self, time):
super(supertrend_momentum_filter_strategy, self).OnStarted2(time)
supertrend = SuperTrend()
supertrend.Length = int(self._supertrend_period.Value)
supertrend.Multiplier = Decimal(self._supertrend_multiplier.Value)
momentum = Momentum()
momentum.Length = int(self._momentum_period.Value)
self._cooldown = 0
self._is_initialized = False
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(supertrend, momentum, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, supertrend)
self.DrawIndicator(area, momentum)
self.DrawOwnTrades(area)
self.StartProtection(
Unit(0, UnitTypes.Absolute),
Unit(self._stop_loss_percent.Value, UnitTypes.Percent),
False
)
def _process_candle(self, candle, supertrend_value, momentum_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
if not self._is_initialized:
self._prev_momentum = float(momentum_value)
self._is_initialized = True
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_momentum = float(momentum_value)
return
price = float(candle.ClosePrice)
st_val = float(supertrend_value)
mom_val = float(momentum_value)
is_above_supertrend = price > st_val
is_below_supertrend = price < st_val
is_momentum_rising = mom_val > self._prev_momentum
is_momentum_falling = mom_val < self._prev_momentum
cd = int(self._cooldown_bars.Value)
if self.Position == 0:
if is_above_supertrend and is_momentum_rising and mom_val >= 100.0:
self.BuyMarket()
self._cooldown = cd
elif is_below_supertrend and is_momentum_falling and mom_val <= 100.0:
self.SellMarket()
self._cooldown = cd
elif self.Position > 0:
if is_below_supertrend or is_momentum_falling:
self.SellMarket(Math.Abs(self.Position))
self._cooldown = cd
elif self.Position < 0:
if is_above_supertrend or is_momentum_rising:
self.BuyMarket(Math.Abs(self.Position))
self._cooldown = cd
self._prev_momentum = mom_val
def CreateClone(self):
return supertrend_momentum_filter_strategy()