Estrategia de Filtro de Momentum Supertrend
La estrategia Supertrend Momentum Filter está construida en torno a los indicadores Supertrend y Momentum.
Las señales se activan cuando sus indicadores confirman entradas filtradas en datos intradía (5m). Esto hace que el método sea adecuado para traders activos.
Los stops dependen de múltiplos de ATR y factores como SupertrendPeriod, SupertrendMultiplier. Ajuste estos valores predeterminados para equilibrar el riesgo y la recompensa.
Detalles
- Criterios de entrada: ver implementación para condiciones de indicadores.
- Largo/Corto: Ambos.
- Criterios de salida: señal opuesta o lógica de stops.
- Stops: Sí, usando cálculos basados en indicadores.
- Valores predeterminados:
SupertrendPeriod = 10SupertrendMultiplier = 3.0mMomentumPeriod = 14CandleType = TimeSpan.FromMinutes(5).TimeFrame()
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Ambos
- Indicadores: Múltiples
- Stops: Sí
- Complejidad: Intermedio
- Marco temporal: Intradía (5m)
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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()