Esta estrategia utiliza el Índice de Fuerza Relativa (RSI) para identificar reversiones tras extremos a corto plazo. Una señal de compra ocurre cuando el RSI cruza por encima del umbral de sobreventa después de permanecer por debajo durante dos velas consecutivas. Una señal de venta ocurre cuando el RSI cruza por debajo del umbral de sobrecompra después de permanecer por encima durante dos velas. La estrategia opcionalmente cierra una posición opuesta existente y opera solo dentro de una ventana de tiempo configurable.
Detalles
Criterios de entrada:
Largo: RSI > BuyPoint y el RSI de las dos velas anteriores < BuyPoint.
Corto: RSI < SellPoint y el RSI de las dos velas anteriores > SellPoint.
Criterios de salida: Señal opuesta o stop/take-profit de protección.
Filtro de tiempo: Opera solo cuando la hora de apertura de la vela está entre StartHour y EndHour.
Stops: Take profit y stop loss fijos expresados en unidades de precio.
Parámetros:
RsiPeriod – período de cálculo del RSI.
BuyPoint – nivel de sobreventa para entradas largas.
SellPoint – nivel de sobrecompra para entradas cortas.
CloseOnOpposite – cerrar la posición actual cuando aparece una señal opuesta.
StartHour / EndHour – horas de trading.
TakeProfit / StopLoss – niveles de protección en precio.
Este ejemplo demuestra un sistema minimalista de cruce RSI construido con la API de alto nivel de StockSharp. Puede utilizarse como plantilla para mayor experimentación.
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-based trading strategy.
/// Buys when RSI crosses above BuyPoint, sells when RSI crosses below SellPoint.
/// </summary>
public class RsiTraderV1Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _buyPoint;
private readonly StrategyParam<decimal> _sellPoint;
private decimal _prevRsi;
private decimal _prevPrevRsi;
private bool _hasPrev;
private bool _hasPrevPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal BuyPoint { get => _buyPoint.Value; set => _buyPoint.Value = value; }
public decimal SellPoint { get => _sellPoint.Value; set => _sellPoint.Value = value; }
public RsiTraderV1Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "Calculation period", "RSI");
_buyPoint = Param(nameof(BuyPoint), 30m)
.SetDisplay("Buy Threshold", "RSI level for long entry", "RSI");
_sellPoint = Param(nameof(SellPoint), 70m)
.SetDisplay("Sell Threshold", "RSI level for short entry", "RSI");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0;
_prevPrevRsi = 0;
_hasPrev = false;
_hasPrevPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
SubscribeCandles(CandleType)
.Bind(rsi, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevRsi = rsiValue;
_hasPrev = true;
return;
}
if (!_hasPrevPrev)
{
_prevPrevRsi = _prevRsi;
_prevRsi = rsiValue;
_hasPrevPrev = true;
return;
}
var longSignal = rsiValue > BuyPoint && _prevRsi < BuyPoint && _prevPrevRsi < BuyPoint;
var shortSignal = rsiValue < SellPoint && _prevRsi > SellPoint && _prevPrevRsi > SellPoint;
if (longSignal && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (shortSignal && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevPrevRsi = _prevRsi;
_prevRsi = 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
from StockSharp.Algo.Strategies import Strategy
class rsi_trader_v1_strategy(Strategy):
def __init__(self):
super(rsi_trader_v1_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "Calculation period", "RSI")
self._buy_point = self.Param("BuyPoint", 30.0) \
.SetDisplay("Buy Threshold", "RSI level for long entry", "RSI")
self._sell_point = self.Param("SellPoint", 70.0) \
.SetDisplay("Sell Threshold", "RSI level for short entry", "RSI")
self._prev_rsi = 0.0
self._prev_prev_rsi = 0.0
self._has_prev = False
self._has_prev_prev = False
@property
def candle_type(self):
return self._candle_type.Value
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def buy_point(self):
return self._buy_point.Value
@property
def sell_point(self):
return self._sell_point.Value
def OnReseted(self):
super(rsi_trader_v1_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._prev_prev_rsi = 0.0
self._has_prev = False
self._has_prev_prev = False
def OnStarted2(self, time):
super(rsi_trader_v1_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
self.SubscribeCandles(self.candle_type).Bind(rsi, self.process_candle).Start()
def process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_value)
if not self._has_prev:
self._prev_rsi = rv
self._has_prev = True
return
if not self._has_prev_prev:
self._prev_prev_rsi = self._prev_rsi
self._prev_rsi = rv
self._has_prev_prev = True
return
bp = float(self.buy_point)
sp = float(self.sell_point)
long_signal = rv > bp and self._prev_rsi < bp and self._prev_prev_rsi < bp
short_signal = rv < sp and self._prev_rsi > sp and self._prev_prev_rsi > sp
if long_signal and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif short_signal and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_prev_rsi = self._prev_rsi
self._prev_rsi = rv
def CreateClone(self):
return rsi_trader_v1_strategy()