Estrategia Kolier SuperTrend
Estrategia basada en el indicador Kolier SuperTrend que aplica bandas ATR para detectar reversiones de tendencia.
El indicador dibuja niveles dinámicos de soporte y resistencia derivados del ATR. Una reversión alcista ocurre cuando el precio cierra por encima de la banda inferior y la línea gira por debajo del precio. Una reversión bajista ocurre cuando el precio cierra por debajo de la banda superior.
Siguiendo este rastro adaptativo, la estrategia intenta capturar tendencias fuertes mientras se mantiene protegida cuando el impulso disminuye.
Detalles
- Criterios de entrada: El precio cruza la línea SuperTrend.
- Largo/Corto: Ambas direcciones.
- Criterios de salida: Cruce opuesto.
- Stops: No.
- Valores predeterminados:
Period= 10Multiplier= 3.0mCandleType= TimeSpan.FromHours(4)
- Filtros:
- Categoría: Tendencia
- Dirección: Ambos
- Indicadores: ATR, SuperTrend
- Stops: No
- Complejidad: Básico
- Marco temporal: Swing (4h)
- 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>
/// Kolier SuperTrend strategy based on ATR bands.
/// Enters long when price crosses above the SuperTrend line and short when crossing below.
/// </summary>
public class KolierSuperTrendStrategy : Strategy
{
private readonly StrategyParam<int> _period;
private readonly StrategyParam<decimal> _multiplier;
private readonly StrategyParam<DataType> _candleType;
private AverageTrueRange _atr;
private bool _prevPriceAbove;
private decimal _prevSupertrend;
private bool _isInitialized;
public int Period { get => _period.Value; set => _period.Value = value; }
public decimal Multiplier { get => _multiplier.Value; set => _multiplier.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public KolierSuperTrendStrategy()
{
_period = Param(nameof(Period), 10)
.SetDisplay("ATR Period", "ATR period for SuperTrend", "Indicators")
.SetOptimize(5, 20, 1);
_multiplier = Param(nameof(Multiplier), 3.0m)
.SetDisplay("ATR Multiplier", "ATR multiplier for SuperTrend", "Indicators")
.SetOptimize(2.0m, 4.0m, 0.5m);
_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();
_prevPriceAbove = false;
_prevSupertrend = 0m;
_isInitialized = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_atr = new AverageTrueRange { Length = Period };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var atrResult = _atr.Process(candle);
if (!atrResult.IsFormed)
return;
var atrValue = atrResult.ToDecimal();
var median = (candle.HighPrice + candle.LowPrice) / 2m;
var upper = median + Multiplier * atrValue;
var lower = median - Multiplier * atrValue;
decimal supertrend;
if (!_isInitialized)
{
supertrend = candle.ClosePrice > median ? lower : upper;
_prevSupertrend = supertrend;
_prevPriceAbove = candle.ClosePrice > supertrend;
_isInitialized = true;
return;
}
if (_prevSupertrend <= candle.HighPrice)
supertrend = Math.Max(lower, _prevSupertrend);
else if (_prevSupertrend >= candle.LowPrice)
supertrend = Math.Min(upper, _prevSupertrend);
else
supertrend = candle.ClosePrice > _prevSupertrend ? lower : upper;
var priceAbove = candle.ClosePrice > supertrend;
var crossUp = priceAbove && !_prevPriceAbove;
var crossDown = !priceAbove && _prevPriceAbove;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevSupertrend = supertrend;
_prevPriceAbove = priceAbove;
}
}
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 AverageTrueRange, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
class kolier_super_trend_strategy(Strategy):
"""
Kolier SuperTrend: ATR-based trend following.
Enters long when price crosses above SuperTrend, short when below.
"""
def __init__(self):
super(kolier_super_trend_strategy, self).__init__()
self._period = self.Param("Period", 10) \
.SetDisplay("ATR Period", "ATR period for SuperTrend", "Indicators")
self._multiplier = self.Param("Multiplier", 3.0) \
.SetDisplay("ATR Multiplier", "ATR multiplier for SuperTrend", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._atr = None
self._prev_price_above = False
self._prev_supertrend = 0.0
self._is_initialized = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(kolier_super_trend_strategy, self).OnReseted()
self._prev_price_above = False
self._prev_supertrend = 0.0
self._is_initialized = False
def OnStarted2(self, time):
super(kolier_super_trend_strategy, self).OnStarted2(time)
self._atr = AverageTrueRange()
self._atr.Length = self._period.Value
self.Indicators.Add(self._atr)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
atr_inp = CandleIndicatorValue(self._atr, candle)
atr_result = self._atr.Process(atr_inp)
if not atr_result.IsFormed:
return
atr_val = float(atr_result)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
close = float(candle.ClosePrice)
median = (high + low) / 2.0
mult = self._multiplier.Value
upper = median + mult * atr_val
lower = median - mult * atr_val
if not self._is_initialized:
supertrend = lower if close > median else upper
self._prev_supertrend = supertrend
self._prev_price_above = close > supertrend
self._is_initialized = True
return
if self._prev_supertrend <= high:
supertrend = max(lower, self._prev_supertrend)
elif self._prev_supertrend >= low:
supertrend = min(upper, self._prev_supertrend)
else:
supertrend = lower if close > self._prev_supertrend else upper
price_above = close > supertrend
cross_up = price_above and not self._prev_price_above
cross_down = not price_above and self._prev_price_above
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_supertrend = supertrend
self._prev_price_above = price_above
def CreateClone(self):
return kolier_super_trend_strategy()