Estrategia de Tendencia RSI
La Estrategia de Tendencia RSI utiliza el Índice de Fuerza Relativa (RSI) para detectar reversiones de tendencia y gestiona las posiciones con un trailing stop basado en ATR. El sistema abre una posición larga cuando el RSI cruza por encima de un umbral de sobrecompra y entra en una posición corta cuando el RSI cae por debajo de un umbral de sobreventa. El riesgo se controla usando un trailing stop derivado del Rango Verdadero Promedio (ATR), lo que permite que el nivel de stop se adapte a la volatilidad actual.
Esta implementación está diseñada con fines educativos y demuestra cómo construir una estrategia StockSharp de alto nivel usando vinculaciones de indicadores. La estrategia opera solo en velas completadas y no hace referencia a valores anteriores de indicadores directamente, alineándose con las mejores prácticas de StockSharp.
Detalles
- Criterios de entrada:
- Largo:
RSI(t) > BuyLevel y RSI(t-1) <= BuyLevel.
- Corto:
RSI(t) < SellLevel y RSI(t-1) >= SellLevel.
- Largo/Corto: Ambas direcciones.
- Criterios de salida:
- Trailing stop basado en múltiplo de ATR.
- Stops: Sí, trailing stop dinámico.
- Valores predeterminados:
RSI Period = 14.
BuyLevel = 73.
SellLevel = 27.
ATR Period = 100.
ATR Multiple = 3.
- Filtros:
- Categoría: Seguimiento de tendencia.
- Dirección: Ambos.
- Indicadores: RSI, ATR.
- Stops: Sí.
- Complejidad: Intermedio.
- Marco temporal: Cualquiera (velas de 1 minuto por defecto).
- Estacionalidad: No.
- Redes neuronales: No.
- Divergencia: No.
- Nivel de riesgo: Moderado.
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>
/// RSI trend strategy with StdDev trailing stop.
/// </summary>
public class RsiTrendStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiBuyLevel;
private readonly StrategyParam<decimal> _rsiSellLevel;
private readonly StrategyParam<int> _stdevPeriod;
private readonly StrategyParam<decimal> _stdevMultiple;
private readonly StrategyParam<DataType> _candleType;
private decimal _previousRsi;
private bool _isRsiInitialized;
private decimal _stopPrice;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal RsiBuyLevel { get => _rsiBuyLevel.Value; set => _rsiBuyLevel.Value = value; }
public decimal RsiSellLevel { get => _rsiSellLevel.Value; set => _rsiSellLevel.Value = value; }
public int StdevPeriod { get => _stdevPeriod.Value; set => _stdevPeriod.Value = value; }
public decimal StdevMultiple { get => _stdevMultiple.Value; set => _stdevMultiple.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public RsiTrendStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "Period for RSI calculation", "RSI Settings");
_rsiBuyLevel = Param(nameof(RsiBuyLevel), 60m)
.SetDisplay("RSI Buy Level", "Upper RSI barrier for long entries", "RSI Settings");
_rsiSellLevel = Param(nameof(RsiSellLevel), 40m)
.SetDisplay("RSI Sell Level", "Lower RSI barrier for short entries", "RSI Settings");
_stdevPeriod = Param(nameof(StdevPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("StdDev Period", "StdDev period for trailing stop", "Settings");
_stdevMultiple = Param(nameof(StdevMultiple), 2m)
.SetGreaterThanZero()
.SetDisplay("StdDev Multiple", "StdDev multiplier for trailing stop", "Settings");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for processing", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_previousRsi = 0;
_isRsiInitialized = false;
_stopPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var stdev = new StandardDeviation { Length = StdevPeriod };
SubscribeCandles(CandleType)
.Bind(rsi, stdev, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue, decimal stdevValue)
{
if (candle.State != CandleStates.Finished) return;
if (stdevValue <= 0) return;
if (!_isRsiInitialized)
{
_previousRsi = rsiValue;
_isRsiInitialized = true;
return;
}
var bullish = rsiValue > RsiBuyLevel && _previousRsi <= RsiBuyLevel;
var bearish = rsiValue < RsiSellLevel && _previousRsi >= RsiSellLevel;
if (bullish && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_stopPrice = candle.ClosePrice - stdevValue * StdevMultiple;
}
else if (bearish && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_stopPrice = candle.ClosePrice + stdevValue * StdevMultiple;
}
if (Position > 0)
{
var newStop = candle.ClosePrice - stdevValue * StdevMultiple;
if (newStop > _stopPrice) _stopPrice = newStop;
if (candle.ClosePrice <= _stopPrice) SellMarket();
}
else if (Position < 0)
{
var newStop = candle.ClosePrice + stdevValue * StdevMultiple;
if (newStop < _stopPrice) _stopPrice = newStop;
if (candle.ClosePrice >= _stopPrice) BuyMarket();
}
_previousRsi = rsiValue;
}
}
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 RelativeStrengthIndex, StandardDeviation
from StockSharp.Algo.Strategies import Strategy
class rsi_trend_strategy(Strategy):
def __init__(self):
super(rsi_trend_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "Period for RSI calculation", "RSI Settings")
self._rsi_buy_level = self.Param("RsiBuyLevel", 60.0) \
.SetDisplay("RSI Buy Level", "Upper RSI barrier for long entries", "RSI Settings")
self._rsi_sell_level = self.Param("RsiSellLevel", 40.0) \
.SetDisplay("RSI Sell Level", "Lower RSI barrier for short entries", "RSI Settings")
self._stdev_period = self.Param("StdevPeriod", 20) \
.SetDisplay("StdDev Period", "StdDev period for trailing stop", "Settings")
self._stdev_multiple = self.Param("StdevMultiple", 2.0) \
.SetDisplay("StdDev Multiple", "StdDev multiplier for trailing stop", "Settings")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles for processing", "General")
self._previous_rsi = 0.0
self._is_rsi_initialized = False
self._stop_price = 0.0
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def rsi_buy_level(self):
return self._rsi_buy_level.Value
@property
def rsi_sell_level(self):
return self._rsi_sell_level.Value
@property
def stdev_period(self):
return self._stdev_period.Value
@property
def stdev_multiple(self):
return self._stdev_multiple.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(rsi_trend_strategy, self).OnReseted()
self._previous_rsi = 0.0
self._is_rsi_initialized = False
self._stop_price = 0.0
def OnStarted2(self, time):
super(rsi_trend_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
stdev = StandardDeviation()
stdev.Length = self.stdev_period
self.SubscribeCandles(self.candle_type).Bind(rsi, stdev, self.process_candle).Start()
def process_candle(self, candle, rsi_value, stdev_value):
if candle.State != CandleStates.Finished:
return
sv = float(stdev_value)
if sv <= 0:
return
rv = float(rsi_value)
if not self._is_rsi_initialized:
self._previous_rsi = rv
self._is_rsi_initialized = True
return
buy_level = float(self.rsi_buy_level)
sell_level = float(self.rsi_sell_level)
sm = float(self.stdev_multiple)
close = float(candle.ClosePrice)
bullish = rv > buy_level and self._previous_rsi <= buy_level
bearish = rv < sell_level and self._previous_rsi >= sell_level
if bullish and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._stop_price = close - sv * sm
elif bearish and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._stop_price = close + sv * sm
if self.Position > 0:
new_stop = close - sv * sm
if new_stop > self._stop_price:
self._stop_price = new_stop
if close <= self._stop_price:
self.SellMarket()
elif self.Position < 0:
new_stop = close + sv * sm
if new_stop < self._stop_price:
self._stop_price = new_stop
if close >= self._stop_price:
self.BuyMarket()
self._previous_rsi = rv
def CreateClone(self):
return rsi_trend_strategy()