Estrategia de Ruptura RSI
La Estrategia de Ruptura RSI busca ráfagas de momentum cuando el Índice de Fuerza Relativa (RSI) supera su rango típico. Al medir las desviaciones del RSI respecto a su media móvil, el sistema pretende captar nuevas tendencias en su inicio.
Las pruebas indican un rendimiento anual promedio de aproximadamente 88%. Funciona mejor en el mercado de acciones.
Se abre una posición larga cuando el RSI cierra por encima de la media más Multiplier veces la desviación estándar. Se toma una posición corta cuando el RSI cae por debajo de la media menos ese multiplicador. Las posiciones se cierran una vez que el RSI cruza de vuelta por su valor medio.
Los traders de momentum pueden encontrar este enfoque útil para identificar rupturas tempranas mientras mantienen niveles de salida definidos. Un porcentaje de stop-loss protege contra reversiones repentinas.
Detalles
- Criterios de entrada:
- Largo: RSI > Avg + Multiplier * StdDev
- Corto: RSI < Avg - Multiplier * StdDev
- Largo/Corto: Ambos lados.
- Criterios de salida:
- Largo: Salir cuando RSI < Avg
- Corto: Salir cuando RSI > Avg
- Stops: Sí, stop-loss porcentual.
- Valores predeterminados:
RsiPeriod= 14AveragePeriod= 20Multiplier= 2.0mCandleType= TimeSpan.FromMinutes(5)
- Filtros:
- Categoría: Ruptura
- Dirección: Ambos
- Indicadores: RSI
- Stops: Sí
- Complejidad: Intermedio
- Marco temporal: Intradía
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// RSI Breakout Strategy (247).
/// Enter when RSI breaks out above/below its average by a certain multiple of standard deviation.
/// Exit when RSI returns to its average.
/// </summary>
public class RsiBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _averagePeriod;
private readonly StrategyParam<decimal> _multiplier;
private readonly StrategyParam<DataType> _candleType;
private RelativeStrengthIndex _rsi;
private SimpleMovingAverage _rsiAverage;
private StandardDeviation _rsiStdDev;
private decimal _prevRsiValue;
private decimal _currentRsiValue;
private decimal _currentRsiAvg;
private decimal _currentRsiStdDev;
/// <summary>
/// RSI period.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// Period for RSI average calculation.
/// </summary>
public int AveragePeriod
{
get => _averagePeriod.Value;
set => _averagePeriod.Value = value;
}
/// <summary>
/// Standard deviation multiplier for entry.
/// </summary>
public decimal Multiplier
{
get => _multiplier.Value;
set => _multiplier.Value = value;
}
/// <summary>
/// Type of candles to use.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="RsiBreakoutStrategy"/>.
/// </summary>
public RsiBreakoutStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "Period for RSI calculation", "Strategy Parameters")
.SetOptimize(10, 20, 2);
_averagePeriod = Param(nameof(AveragePeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Average Period", "Period for RSI average calculation", "Strategy Parameters")
.SetOptimize(10, 30, 5);
_multiplier = Param(nameof(Multiplier), 2.0m)
.SetGreaterThanZero()
.SetDisplay("StdDev Multiplier", "Standard deviation multiplier for entry", "Strategy Parameters")
.SetOptimize(1.0m, 3.0m, 0.5m);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "Strategy Parameters");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsiValue = default;
_currentRsiValue = default;
_currentRsiAvg = default;
_currentRsiStdDev = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Create indicators
_rsi = new RelativeStrengthIndex { Length = RsiPeriod };
_rsiAverage = new SMA { Length = AveragePeriod };
_rsiStdDev = new StandardDeviation { Length = AveragePeriod };
// Create candle subscription
var subscription = SubscribeCandles(CandleType);
// Bind RSI to candles
subscription
.Bind(_rsi, ProcessRsi)
.Start();
// Setup chart visualization if available
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _rsi);
DrawIndicator(area, _rsiAverage);
DrawOwnTrades(area);
}
// Enable position protection
StartProtection(
takeProfit: new Unit(5, UnitTypes.Percent),
stopLoss: new Unit(2, UnitTypes.Percent)
);
}
private void ProcessRsi(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
// Store previous and current RSI value
_prevRsiValue = _currentRsiValue;
_currentRsiValue = rsiValue;
// Process RSI through average and standard deviation indicators
var avgValue = _rsiAverage.Process(new DecimalIndicatorValue(_rsiAverage, rsiValue, candle.ServerTime) { IsFinal = true });
var stdDevValue = _rsiStdDev.Process(new DecimalIndicatorValue(_rsiStdDev, rsiValue, candle.ServerTime) { IsFinal = true });
_currentRsiAvg = avgValue.ToDecimal();
_currentRsiStdDev = stdDevValue.ToDecimal();
if (!_rsiAverage.IsFormed || !_rsiStdDev.IsFormed)
return;
// Calculate bands
var upperBand = _currentRsiAvg + Multiplier * _currentRsiStdDev;
var lowerBand = _currentRsiAvg - Multiplier * _currentRsiStdDev;
LogInfo($"RSI: {_currentRsiValue}, RSI Avg: {_currentRsiAvg}, Upper: {upperBand}, Lower: {lowerBand}");
// Entry logic - BREAKOUT
if (Position == 0)
{
if (_currentRsiValue > upperBand)
{
BuyMarket();
}
else if (_currentRsiValue < lowerBand)
{
SellMarket();
}
}
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import RelativeStrengthIndex, SimpleMovingAverage, StandardDeviation
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class rsi_breakout_strategy(Strategy):
"""
RSI Breakout Strategy (247).
Enter when RSI breaks out above/below its average by a certain multiple of standard deviation.
Exit when RSI returns to its average.
"""
def __init__(self):
super(rsi_breakout_strategy, self).__init__()
# Initialize strategy parameters
self._rsiPeriod = self.Param("RsiPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("RSI Period", "Period for RSI calculation", "Strategy Parameters") \
.SetCanOptimize(True) \
.SetOptimize(10, 20, 2)
self._averagePeriod = self.Param("AveragePeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("Average Period", "Period for RSI average calculation", "Strategy Parameters") \
.SetCanOptimize(True) \
.SetOptimize(10, 30, 5)
self._multiplier = self.Param("Multiplier", 2.0) \
.SetGreaterThanZero() \
.SetDisplay("StdDev Multiplier", "Standard deviation multiplier for entry", "Strategy Parameters") \
.SetCanOptimize(True) \
.SetOptimize(1.0, 3.0, 0.5)
self._candleType = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Type of candles to use", "Strategy Parameters")
# Internal indicators
self._rsi = None
self._rsiAverage = None
self._rsiStdDev = None
# State variables
self._prevRsiValue = 0.0
self._currentRsiValue = 0.0
self._currentRsiAvg = 0.0
self._currentRsiStdDev = 0.0
@property
def RsiPeriod(self):
"""RSI period."""
return self._rsiPeriod.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsiPeriod.Value = value
@property
def AveragePeriod(self):
"""Period for RSI average calculation."""
return self._averagePeriod.Value
@AveragePeriod.setter
def AveragePeriod(self, value):
self._averagePeriod.Value = value
@property
def Multiplier(self):
"""Standard deviation multiplier for entry."""
return self._multiplier.Value
@Multiplier.setter
def Multiplier(self, value):
self._multiplier.Value = value
@property
def CandleType(self):
"""Type of candles to use."""
return self._candleType.Value
@CandleType.setter
def CandleType(self, value):
self._candleType.Value = value
def GetWorkingSecurities(self):
"""!! REQUIRED!! Return securities and candle types used."""
return [(self.Security, self.CandleType)]
def OnReseted(self):
"""Resets internal state when strategy is reset."""
super(rsi_breakout_strategy, self).OnReseted()
self._prevRsiValue = 0.0
self._currentRsiValue = 0.0
self._currentRsiAvg = 0.0
self._currentRsiStdDev = 0.0
def OnStarted2(self, time):
"""Called when the strategy starts."""
super(rsi_breakout_strategy, self).OnStarted2(time)
# Create indicators
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiPeriod
self._rsiAverage = SimpleMovingAverage()
self._rsiAverage.Length = self.AveragePeriod
self._rsiStdDev = StandardDeviation()
self._rsiStdDev.Length = self.AveragePeriod
# Create candle subscription
subscription = self.SubscribeCandles(self.CandleType)
# Bind RSI to candles
subscription.Bind(self._rsi, self.ProcessRsi).Start()
# Setup chart visualization if available
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._rsi)
self.DrawIndicator(area, self._rsiAverage)
self.DrawOwnTrades(area)
# Enable position protection
self.StartProtection(
takeProfit=Unit(5, UnitTypes.Percent),
stopLoss=Unit(2, UnitTypes.Percent)
)
def ProcessRsi(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
# Store previous and current RSI value
self._prevRsiValue = self._currentRsiValue
self._currentRsiValue = rsi_value
# Process RSI through average and standard deviation indicators
avg_value = process_float(self._rsiAverage, rsi_value, candle.ServerTime, candle.State == CandleStates.Finished)
std_dev_value = process_float(self._rsiStdDev, rsi_value, candle.ServerTime, candle.State == CandleStates.Finished)
self._currentRsiAvg = float(avg_value)
self._currentRsiStdDev = float(std_dev_value)
if not self._rsiAverage.IsFormed or not self._rsiStdDev.IsFormed:
return
# Calculate bands
upper_band = self._currentRsiAvg + self.Multiplier * self._currentRsiStdDev
lower_band = self._currentRsiAvg - self.Multiplier * self._currentRsiStdDev
self.LogInfo(
"RSI: {0}, RSI Avg: {1}, Upper: {2}, Lower: {3}".format(
self._currentRsiValue, self._currentRsiAvg, upper_band, lower_band))
# Entry logic - BREAKOUT only when flat (no exit logic in CS)
if self.Position == 0:
if self._currentRsiValue > upper_band:
self.BuyMarket()
elif self._currentRsiValue < lower_band:
self.SellMarket()
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return rsi_breakout_strategy()