Estrategia AI SuperTrend
La estrategia AI SuperTrend combina el indicador SuperTrend con medias móviles ponderadas del precio y de la línea SuperTrend. Se abre una operación larga cuando el SuperTrend gira hacia arriba y la WMA del precio se mueve por encima de la WMA del SuperTrend. Se abre una operación corta en las condiciones opuestas. Las posiciones están protegidas con un trailing stop dinámico basado en ATR.
Detalles
- Criterios de entrada:
- Largo: La dirección de SuperTrend cambia hacia arriba y la WMA del precio está por encima de la WMA del SuperTrend.
- Corto: La dirección de SuperTrend cambia hacia abajo y la WMA del precio está por debajo de la WMA del SuperTrend.
- Criterios de salida:
- Reversión de tendencia o trailing stop ATR.
- Stops: Trailing stop ATR dinámico.
- Valores predeterminados:
AtrPeriod= 10AtrFactor= 3PriceWmaLength= 20SuperWmaLength= 100EnableLong= trueEnableShort= true
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Ambos
- Indicadores: SuperTrend, WMA, ATR
- Stops: Sí
- Complejidad: Moderado
- Marco temporal: Cualquiera
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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>
/// AI SuperTrend Strategy - trades SuperTrend signals combined with WMA trend filter.
/// </summary>
public class AiSuperTrendStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<decimal> _atrFactor;
private readonly StrategyParam<int> _wmaLength;
private readonly StrategyParam<int> _cooldownBars;
private bool _prevIsUpTrend;
private bool _isInitialized;
private int _cooldownRemaining;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public decimal AtrFactor { get => _atrFactor.Value; set => _atrFactor.Value = value; }
public int WmaLength { get => _wmaLength.Value; set => _wmaLength.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public AiSuperTrendStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_atrPeriod = Param(nameof(AtrPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("ATR Period", "ATR period for SuperTrend", "SuperTrend");
_atrFactor = Param(nameof(AtrFactor), 3m)
.SetDisplay("ATR Factor", "ATR factor for SuperTrend", "SuperTrend");
_wmaLength = Param(nameof(WmaLength), 20)
.SetGreaterThanZero()
.SetDisplay("WMA Length", "WMA length for trend filter", "AI");
_cooldownBars = Param(nameof(CooldownBars), 10)
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevIsUpTrend = false;
_isInitialized = false;
_cooldownRemaining = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var superTrend = new SuperTrend { Length = AtrPeriod, Multiplier = AtrFactor };
var wma = new WeightedMovingAverage { Length = WmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(superTrend, wma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, superTrend);
DrawIndicator(area, wma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stValue, IIndicatorValue wmaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var stTyped = (SuperTrendIndicatorValue)stValue;
var isUpTrend = stTyped.IsUpTrend;
var wma = wmaValue.ToDecimal();
if (!_isInitialized)
{
_prevIsUpTrend = isUpTrend;
_isInitialized = true;
return;
}
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevIsUpTrend = isUpTrend;
return;
}
// Long: SuperTrend flips to uptrend + price above WMA
if (!_prevIsUpTrend && isUpTrend && candle.ClosePrice > wma && Position <= 0)
{
if (Position < 0)
BuyMarket(Math.Abs(Position));
BuyMarket(Volume);
_cooldownRemaining = CooldownBars;
}
// Short: SuperTrend flips to downtrend + price below WMA
else if (_prevIsUpTrend && !isUpTrend && candle.ClosePrice < wma && Position >= 0)
{
if (Position > 0)
SellMarket(Math.Abs(Position));
SellMarket(Volume);
_cooldownRemaining = 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, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SuperTrend, WeightedMovingAverage, IndicatorHelper
from StockSharp.Algo.Strategies import Strategy
class ai_super_trend_strategy(Strategy):
def __init__(self):
super(ai_super_trend_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._atr_period = self.Param("AtrPeriod", 10) \
.SetGreaterThanZero() \
.SetDisplay("ATR Period", "ATR period for SuperTrend", "SuperTrend")
self._atr_factor = self.Param("AtrFactor", 3.0) \
.SetDisplay("ATR Factor", "ATR factor for SuperTrend", "SuperTrend")
self._wma_length = self.Param("WmaLength", 20) \
.SetGreaterThanZero() \
.SetDisplay("WMA Length", "WMA length for trend filter", "AI")
self._cooldown_bars = self.Param("CooldownBars", 10) \
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk")
self._prev_is_up_trend = False
self._is_initialized = False
self._cooldown_remaining = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ai_super_trend_strategy, self).OnReseted()
self._prev_is_up_trend = False
self._is_initialized = False
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(ai_super_trend_strategy, self).OnStarted2(time)
st = SuperTrend()
st.Length = int(self._atr_period.Value)
st.Multiplier = self._atr_factor.Value
wma = WeightedMovingAverage()
wma.Length = int(self._wma_length.Value)
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(st, wma, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, st)
self.DrawIndicator(area, wma)
self.DrawOwnTrades(area)
def _on_process(self, candle, st_value, wma_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
is_up_trend = st_value.IsUpTrend
wma_v = float(IndicatorHelper.ToDecimal(wma_value))
close = float(candle.ClosePrice)
if not self._is_initialized:
self._prev_is_up_trend = is_up_trend
self._is_initialized = True
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_is_up_trend = is_up_trend
return
cooldown = int(self._cooldown_bars.Value)
if not self._prev_is_up_trend and is_up_trend and close > wma_v and self.Position <= 0:
if self.Position < 0:
self.BuyMarket(Math.Abs(self.Position))
self.BuyMarket(self.Volume)
self._cooldown_remaining = cooldown
elif self._prev_is_up_trend and not is_up_trend and close < wma_v and self.Position >= 0:
if self.Position > 0:
self.SellMarket(Math.Abs(self.Position))
self.SellMarket(self.Volume)
self._cooldown_remaining = cooldown
self._prev_is_up_trend = is_up_trend
def CreateClone(self):
return ai_super_trend_strategy()