Estrategia RSI Bollinger Bands
Estrategia que combina el Índice de Fuerza Relativa (RSI) con las Bollinger Bands. Se abre una posición larga cuando el RSI está por debajo del umbral de sobreventa y el precio de cierre está por debajo de la banda inferior de Bollinger. Se abre una posición corta cuando el RSI está por encima del umbral de sobrecompra y el precio de cierre está por encima de la banda superior de Bollinger. Las posiciones se revierten ante señales opuestas.
Detalles
- Criterios de entrada: RSI por debajo de
RsiOversoldy precio de cierre por debajo de la banda inferior para comprar; RSI por encima deRsiOverboughty precio de cierre por encima de la banda superior para vender. - Largo/Corto: Ambas direcciones.
- Criterios de salida: Señal inversa.
- Stops: Ninguno.
- Valores predeterminados:
CandleType= TimeSpan.FromMinutes(15)RsiPeriod= 20BollingerPeriod= 20BollingerWidth= 2RsiOversold= 30RsiOverbought= 70
- Filtros:
- Categoría: Oscilador
- Dirección: Ambos
- Indicadores: RSI, Bollinger Bands
- Stops: No
- Complejidad: Básico
- Marco temporal: 15 minutos
- 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 combined with Bollinger Bands strategy.
/// Buys when RSI is oversold and price is below the lower band.
/// Sells when RSI is overbought and price is above the upper band.
/// </summary>
public class RsiBollingerBandsStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _bollingerPeriod;
private readonly StrategyParam<decimal> _bollingerWidth;
private readonly StrategyParam<decimal> _rsiOversold;
private readonly StrategyParam<decimal> _rsiOverbought;
public RsiBollingerBandsStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Primary timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI calculation length", "Indicators");
_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
.SetDisplay("Bollinger Period", "Bollinger bands length", "Indicators");
_bollingerWidth = Param(nameof(BollingerWidth), 2m)
.SetDisplay("Bollinger Width", "Band width multiplier", "Indicators");
_rsiOversold = Param(nameof(RsiOversold), 35m)
.SetDisplay("RSI Oversold", "Buy threshold", "Indicators");
_rsiOverbought = Param(nameof(RsiOverbought), 65m)
.SetDisplay("RSI Overbought", "Sell threshold", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
public decimal BollingerWidth { get => _bollingerWidth.Value; set => _bollingerWidth.Value = value; }
public decimal RsiOversold { get => _rsiOversold.Value; set => _rsiOversold.Value = value; }
public decimal RsiOverbought { get => _rsiOverbought.Value; set => _rsiOverbought.Value = value; }
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var bollinger = new BollingerBands { Length = BollingerPeriod, Width = BollingerWidth };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(rsi, bollinger, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, bollinger);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue rsiValue, IIndicatorValue bbValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var rsi = rsiValue.IsFormed ? rsiValue.GetValue<decimal>() : (decimal?)null;
var bb = bbValue as BollingerBandsValue;
if (rsi is null || bb?.UpBand is not decimal upper || bb?.LowBand is not decimal lower)
return;
var buySignal = rsi < RsiOversold && candle.ClosePrice < lower;
var sellSignal = rsi > RsiOverbought && candle.ClosePrice > upper;
if (buySignal && Position <= 0)
BuyMarket();
else if (sellSignal && Position >= 0)
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
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import RelativeStrengthIndex, BollingerBands
from StockSharp.Algo.Strategies import Strategy
class rsi_bollinger_bands_strategy(Strategy):
def __init__(self):
super(rsi_bollinger_bands_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Primary timeframe", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI calculation length", "Indicators")
self._bollinger_period = self.Param("BollingerPeriod", 20) \
.SetDisplay("Bollinger Period", "Bollinger bands length", "Indicators")
self._bollinger_width = self.Param("BollingerWidth", 2.0) \
.SetDisplay("Bollinger Width", "Band width multiplier", "Indicators")
self._rsi_oversold = self.Param("RsiOversold", 35.0) \
.SetDisplay("RSI Oversold", "Buy threshold", "Indicators")
self._rsi_overbought = self.Param("RsiOverbought", 65.0) \
.SetDisplay("RSI Overbought", "Sell threshold", "Indicators")
@property
def candle_type(self):
return self._candle_type.Value
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def bollinger_period(self):
return self._bollinger_period.Value
@property
def bollinger_width(self):
return self._bollinger_width.Value
@property
def rsi_oversold(self):
return self._rsi_oversold.Value
@property
def rsi_overbought(self):
return self._rsi_overbought.Value
def OnReseted(self):
super(rsi_bollinger_bands_strategy, self).OnReseted()
def OnStarted2(self, time):
super(rsi_bollinger_bands_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
bollinger = BollingerBands()
bollinger.Length = self.bollinger_period
bollinger.Width = self.bollinger_width
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(rsi, bollinger, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, bollinger)
self.DrawOwnTrades(area)
def process_candle(self, candle, rsi_value, bb_value):
if candle.State != CandleStates.Finished:
return
if not rsi_value.IsFormed:
return
rsi = float(rsi_value)
upper = bb_value.UpBand
lower = bb_value.LowBand
if upper is None or lower is None:
return
upper = float(upper)
lower = float(lower)
close = float(candle.ClosePrice)
buy_signal = rsi < float(self.rsi_oversold) and close < lower
sell_signal = rsi > float(self.rsi_overbought) and close > upper
if buy_signal and self.Position <= 0:
self.BuyMarket()
elif sell_signal and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return rsi_bollinger_bands_strategy()