RSI Sobrecompra/Sobreventa (RSI Overbought/Oversold)
Este sistema opera reversiones utilizando el Índice de Fuerza Relativa (RSI). Cuando el RSI cae por debajo del nivel de sobreventa, compra después de cerrar los cortos. Cuando el RSI sube por encima del nivel de sobrecompra, vende después de cerrar los largos.
Las pruebas indican un rendimiento anual promedio de aproximadamente el 61%. Funciona mejor en el mercado de criptomonedas.
Las posiciones se cierran cuando el RSI regresa a una zona neutral o se alcanza el stop-loss.
Detalles
- Criterios de entrada: RSI por debajo de
OversoldLevelo por encima deOverboughtLevel. - Largo/Corto: Ambos.
- Criterios de salida: RSI cruza
NeutralLevelo stop. - Stops: Sí.
- Valores predeterminados:
RsiPeriod= 14OverboughtLevel= 70OversoldLevel= 30NeutralLevel= 50CandleType= TimeSpan.FromMinutes(5)StopLossPercent= 2.0m
- Filtros:
- Categoría: Oscilador
- Dirección: Ambos
- Indicadores: RSI
- Stops: Sí
- Complejidad: Básico
- Marco temporal: Intradía
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: Sí
- 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>
/// RSI Overbought/Oversold strategy.
/// Buys when RSI is oversold, sells when RSI is overbought.
/// </summary>
public class RsiOverboughtOversoldStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _overboughtLevel;
private readonly StrategyParam<int> _oversoldLevel;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private int _cooldown;
/// <summary>
/// RSI calculation period.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// RSI level considered overbought.
/// </summary>
public int OverboughtLevel
{
get => _overboughtLevel.Value;
set => _overboughtLevel.Value = value;
}
/// <summary>
/// RSI level considered oversold.
/// </summary>
public int OversoldLevel
{
get => _oversoldLevel.Value;
set => _oversoldLevel.Value = value;
}
/// <summary>
/// Type of candles to use.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown bars between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="RsiOverboughtOversoldStrategy"/>.
/// </summary>
public RsiOverboughtOversoldStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetRange(5, 30)
.SetDisplay("RSI Period", "Period for RSI calculation", "Indicators");
_overboughtLevel = Param(nameof(OverboughtLevel), 70)
.SetRange(60, 80)
.SetDisplay("Overbought Level", "RSI overbought threshold", "Indicators");
_oversoldLevel = Param(nameof(OversoldLevel), 30)
.SetRange(20, 40)
.SetDisplay("Oversold Level", "RSI oversold threshold", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_cooldownBars = Param(nameof(CooldownBars), 500)
.SetRange(1, 1000)
.SetDisplay("Cooldown Bars", "Bars to wait between trades", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_cooldown = 0;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, rsi);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_cooldown > 0)
{
_cooldown--;
return;
}
if (Position == 0 && rsiValue <= OversoldLevel)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (Position == 0 && rsiValue >= OverboughtLevel)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position > 0 && rsiValue >= OverboughtLevel)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && rsiValue <= OversoldLevel)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
}
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_overbought_oversold_strategy(Strategy):
"""
RSI Overbought/Oversold strategy.
Buys when RSI is oversold, sells when RSI is overbought.
"""
def __init__(self):
super(rsi_overbought_oversold_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14).SetDisplay("RSI Period", "Period for RSI calculation", "Indicators")
self._overbought_level = self.Param("OverboughtLevel", 70).SetDisplay("Overbought Level", "RSI overbought threshold", "Indicators")
self._oversold_level = self.Param("OversoldLevel", 30).SetDisplay("Oversold Level", "RSI oversold threshold", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._cooldown_bars = self.Param("CooldownBars", 500).SetDisplay("Cooldown Bars", "Bars to wait between trades", "General")
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(rsi_overbought_oversold_strategy, self).OnReseted()
self._cooldown = 0
def OnStarted2(self, time):
super(rsi_overbought_oversold_strategy, self).OnStarted2(time)
self._cooldown = 0
rsi = RelativeStrengthIndex()
rsi.Length = self._rsi_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, rsi)
self.DrawOwnTrades(area)
def _process_candle(self, candle, rsi_val):
if candle.State != CandleStates.Finished:
return
if self._cooldown > 0:
self._cooldown -= 1
return
rv = float(rsi_val)
ob = self._overbought_level.Value
os_level = self._oversold_level.Value
cd = self._cooldown_bars.Value
if self.Position == 0 and rv <= os_level:
self.BuyMarket()
self._cooldown = cd
elif self.Position == 0 and rv >= ob:
self.SellMarket()
self._cooldown = cd
elif self.Position > 0 and rv >= ob:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and rv <= os_level:
self.BuyMarket()
self._cooldown = cd
def CreateClone(self):
return rsi_overbought_oversold_strategy()