Estrategia de Compra/Venta RSI Multi-Temporalidad
Esta estrategia utiliza valores RSI de tres marcos temporales diferentes. Se abre una posición larga cuando todos los RSI habilitados están por debajo del umbral de compra. Se abre una posición corta cuando todos los RSI habilitados están por encima del umbral de venta. Un período de enfriamiento evita señales consecutivas.
Detalles
- Criterios de entrada: Todos los RSI activos por debajo/encima de los umbrales.
- Largo/Corto: Ambos.
- Criterios de salida: Señal opuesta.
- Stops: No.
- Valores predeterminados:
Rsi1Length= 14Rsi2Length= 14Rsi3Length= 14Rsi1CandleType= TimeSpan.FromMinutes(5)Rsi2CandleType= TimeSpan.FromMinutes(15)Rsi3CandleType= TimeSpan.FromMinutes(30)BuyThreshold= 30mSellThreshold= 70mCooldownPeriod= 5
- Filtros:
- Categoría: Momentum
- Dirección: Ambos
- Indicadores: RSI
- Stops: No
- Complejidad: Básico
- Marco temporal: Multi-temporalidad
- 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;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Multi timeframe RSI strategy. Generates buy signal when all enabled RSI values are below BuyThreshold.
/// Generates sell signal when all enabled RSI values are above SellThreshold.
/// </summary>
public class MultiTimeframeRsiBuySellStrategy : Strategy
{
private readonly StrategyParam<bool> _rsi1Enabled;
private readonly StrategyParam<bool> _rsi2Enabled;
private readonly StrategyParam<bool> _rsi3Enabled;
private readonly StrategyParam<int> _rsi1Length;
private readonly StrategyParam<int> _rsi2Length;
private readonly StrategyParam<int> _rsi3Length;
private readonly StrategyParam<DataType> _rsi1CandleType;
private readonly StrategyParam<DataType> _rsi2CandleType;
private readonly StrategyParam<DataType> _rsi3CandleType;
private readonly StrategyParam<decimal> _buyThreshold;
private readonly StrategyParam<decimal> _sellThreshold;
private readonly StrategyParam<int> _cooldownPeriod;
private decimal? _rsi1;
private decimal? _rsi2;
private decimal? _rsi3;
private int _buyCooldown;
private int _sellCooldown;
/// <summary>
/// First RSI enabled.
/// </summary>
public bool Rsi1Enabled { get => _rsi1Enabled.Value; set => _rsi1Enabled.Value = value; }
/// <summary>
/// Second RSI enabled.
/// </summary>
public bool Rsi2Enabled { get => _rsi2Enabled.Value; set => _rsi2Enabled.Value = value; }
/// <summary>
/// Third RSI enabled.
/// </summary>
public bool Rsi3Enabled { get => _rsi3Enabled.Value; set => _rsi3Enabled.Value = value; }
/// <summary>
/// Period for first RSI.
/// </summary>
public int Rsi1Length { get => _rsi1Length.Value; set => _rsi1Length.Value = value; }
/// <summary>
/// Period for second RSI.
/// </summary>
public int Rsi2Length { get => _rsi2Length.Value; set => _rsi2Length.Value = value; }
/// <summary>
/// Period for third RSI.
/// </summary>
public int Rsi3Length { get => _rsi3Length.Value; set => _rsi3Length.Value = value; }
/// <summary>
/// Timeframe for first RSI.
/// </summary>
public DataType Rsi1CandleType { get => _rsi1CandleType.Value; set => _rsi1CandleType.Value = value; }
/// <summary>
/// Timeframe for second RSI.
/// </summary>
public DataType Rsi2CandleType { get => _rsi2CandleType.Value; set => _rsi2CandleType.Value = value; }
/// <summary>
/// Timeframe for third RSI.
/// </summary>
public DataType Rsi3CandleType { get => _rsi3CandleType.Value; set => _rsi3CandleType.Value = value; }
/// <summary>
/// RSI level to trigger buy.
/// </summary>
public decimal BuyThreshold { get => _buyThreshold.Value; set => _buyThreshold.Value = value; }
/// <summary>
/// RSI level to trigger sell.
/// </summary>
public decimal SellThreshold { get => _sellThreshold.Value; set => _sellThreshold.Value = value; }
/// <summary>
/// Cooldown period in bars.
/// </summary>
public int CooldownPeriod { get => _cooldownPeriod.Value; set => _cooldownPeriod.Value = value; }
/// <summary>
/// Initializes a new instance of the <see cref="MultiTimeframeRsiBuySellStrategy"/>.
/// </summary>
public MultiTimeframeRsiBuySellStrategy()
{
_rsi1Enabled = Param(nameof(Rsi1Enabled), true)
.SetDisplay("RSI1 Enabled", "Use first RSI", "RSI1");
_rsi2Enabled = Param(nameof(Rsi2Enabled), true)
.SetDisplay("RSI2 Enabled", "Use second RSI", "RSI2");
_rsi3Enabled = Param(nameof(Rsi3Enabled), true)
.SetDisplay("RSI3 Enabled", "Use third RSI", "RSI3");
_rsi1Length = Param(nameof(Rsi1Length), 14)
.SetGreaterThanZero()
.SetDisplay("RSI1 Length", "Period for first RSI", "RSI1");
_rsi2Length = Param(nameof(Rsi2Length), 14)
.SetGreaterThanZero()
.SetDisplay("RSI2 Length", "Period for second RSI", "RSI2");
_rsi3Length = Param(nameof(Rsi3Length), 14)
.SetGreaterThanZero()
.SetDisplay("RSI3 Length", "Period for third RSI", "RSI3");
_rsi1CandleType = Param(nameof(Rsi1CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("RSI1 Timeframe", "Timeframe for first RSI", "RSI1");
_rsi2CandleType = Param(nameof(Rsi2CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("RSI2 Timeframe", "Timeframe for second RSI", "RSI2");
_rsi3CandleType = Param(nameof(Rsi3CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("RSI3 Timeframe", "Timeframe for third RSI", "RSI3");
_buyThreshold = Param(nameof(BuyThreshold), 30m)
.SetRange(0m, 100m)
.SetDisplay("Buy Threshold", "RSI level to enter long", "Strategy");
_sellThreshold = Param(nameof(SellThreshold), 70m)
.SetRange(0m, 100m)
.SetDisplay("Sell Threshold", "RSI level to enter short", "Strategy");
_cooldownPeriod = Param(nameof(CooldownPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Cooldown", "Bars to wait between signals", "Strategy");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, Rsi1CandleType), (Security, Rsi2CandleType), (Security, Rsi3CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_rsi1 = _rsi2 = _rsi3 = null;
_buyCooldown = _sellCooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_buyCooldown = _sellCooldown = CooldownPeriod;
if (Rsi1Enabled)
{
var rsi1 = new RelativeStrengthIndex { Length = Rsi1Length };
var sub1 = SubscribeCandles(Rsi1CandleType);
sub1.Bind(rsi1, ProcessRsi1).Start();
}
if (Rsi2Enabled)
{
var rsi2 = new RelativeStrengthIndex { Length = Rsi2Length };
var sub2 = SubscribeCandles(Rsi2CandleType);
sub2.Bind(rsi2, ProcessRsi2).Start();
}
if (Rsi3Enabled)
{
var rsi3 = new RelativeStrengthIndex { Length = Rsi3Length };
var sub3 = SubscribeCandles(Rsi3CandleType);
sub3.Bind(rsi3, ProcessRsi3).Start();
}
}
private void ProcessRsi1(ICandleMessage candle, decimal value)
{
if (candle.State != CandleStates.Finished)
return;
_rsi1 = value;
TryTrade(candle);
}
private void ProcessRsi2(ICandleMessage candle, decimal value)
{
if (candle.State != CandleStates.Finished)
return;
_rsi2 = value;
}
private void ProcessRsi3(ICandleMessage candle, decimal value)
{
if (candle.State != CandleStates.Finished)
return;
_rsi3 = value;
}
private void TryTrade(ICandleMessage candle)
{
if (!IsFormedAndOnlineAndAllowTrading())
return;
if ((Rsi1Enabled && _rsi1 == null) || (Rsi2Enabled && _rsi2 == null) || (Rsi3Enabled && _rsi3 == null))
return;
if (_buyCooldown < CooldownPeriod)
_buyCooldown++;
if (_sellCooldown < CooldownPeriod)
_sellCooldown++;
var buyOk = (!Rsi1Enabled || _rsi1 < BuyThreshold) && (!Rsi2Enabled || _rsi2 < BuyThreshold) && (!Rsi3Enabled || _rsi3 < BuyThreshold);
var sellOk = (!Rsi1Enabled || _rsi1 > SellThreshold) && (!Rsi2Enabled || _rsi2 > SellThreshold) && (!Rsi3Enabled || _rsi3 > SellThreshold);
if (buyOk && _buyCooldown >= CooldownPeriod)
{
var volume = Volume + Math.Abs(Position);
BuyMarket(volume);
_sellCooldown = CooldownPeriod;
_buyCooldown = 0;
}
else if (sellOk && _sellCooldown >= CooldownPeriod)
{
var volume = Volume + Math.Abs(Position);
SellMarket(volume);
_sellCooldown = 0;
_buyCooldown = CooldownPeriod;
}
}
}
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
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class multi_timeframe_rsi_buy_sell_strategy(Strategy):
def __init__(self):
super(multi_timeframe_rsi_buy_sell_strategy, self).__init__()
self._rsi1_enabled = self.Param("Rsi1Enabled", True) \
.SetDisplay("RSI1 Enabled", "Use first RSI", "RSI1")
self._rsi2_enabled = self.Param("Rsi2Enabled", True) \
.SetDisplay("RSI2 Enabled", "Use second RSI", "RSI2")
self._rsi3_enabled = self.Param("Rsi3Enabled", True) \
.SetDisplay("RSI3 Enabled", "Use third RSI", "RSI3")
self._rsi1_length = self.Param("Rsi1Length", 14) \
.SetDisplay("RSI1 Length", "Period for first RSI", "RSI1")
self._rsi2_length = self.Param("Rsi2Length", 14) \
.SetDisplay("RSI2 Length", "Period for second RSI", "RSI2")
self._rsi3_length = self.Param("Rsi3Length", 14) \
.SetDisplay("RSI3 Length", "Period for third RSI", "RSI3")
self._rsi1_candle_type = self.Param("Rsi1CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("RSI1 Timeframe", "Timeframe for first RSI", "RSI1")
self._rsi2_candle_type = self.Param("Rsi2CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("RSI2 Timeframe", "Timeframe for second RSI", "RSI2")
self._rsi3_candle_type = self.Param("Rsi3CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("RSI3 Timeframe", "Timeframe for third RSI", "RSI3")
self._buy_threshold = self.Param("BuyThreshold", 30.0) \
.SetDisplay("Buy Threshold", "RSI level to enter long", "Strategy")
self._sell_threshold = self.Param("SellThreshold", 70.0) \
.SetDisplay("Sell Threshold", "RSI level to enter short", "Strategy")
self._cooldown_period = self.Param("CooldownPeriod", 5) \
.SetDisplay("Cooldown", "Bars to wait between signals", "Strategy")
self._rsi1 = None
self._rsi2 = None
self._rsi3 = None
self._buy_cooldown = 0
self._sell_cooldown = 0
@property
def buy_threshold(self):
return self._buy_threshold.Value
@property
def sell_threshold(self):
return self._sell_threshold.Value
@property
def cooldown_period(self):
return self._cooldown_period.Value
def OnReseted(self):
super(multi_timeframe_rsi_buy_sell_strategy, self).OnReseted()
self._rsi1 = None
self._rsi2 = None
self._rsi3 = None
self._buy_cooldown = 0
self._sell_cooldown = 0
def OnStarted2(self, time):
super(multi_timeframe_rsi_buy_sell_strategy, self).OnStarted2(time)
cd = int(self.cooldown_period)
self._buy_cooldown = cd
self._sell_cooldown = cd
if self._rsi1_enabled.Value:
rsi1 = RelativeStrengthIndex()
rsi1.Length = self._rsi1_length.Value
sub1 = self.SubscribeCandles(self._rsi1_candle_type.Value)
sub1.Bind(rsi1, self._process_rsi1).Start()
if self._rsi2_enabled.Value:
rsi2 = RelativeStrengthIndex()
rsi2.Length = self._rsi2_length.Value
sub2 = self.SubscribeCandles(self._rsi2_candle_type.Value)
sub2.Bind(rsi2, self._process_rsi2).Start()
if self._rsi3_enabled.Value:
rsi3 = RelativeStrengthIndex()
rsi3.Length = self._rsi3_length.Value
sub3 = self.SubscribeCandles(self._rsi3_candle_type.Value)
sub3.Bind(rsi3, self._process_rsi3).Start()
def _process_rsi1(self, candle, value):
if candle.State != CandleStates.Finished:
return
self._rsi1 = float(value)
self._try_trade(candle)
def _process_rsi2(self, candle, value):
if candle.State != CandleStates.Finished:
return
self._rsi2 = float(value)
def _process_rsi3(self, candle, value):
if candle.State != CandleStates.Finished:
return
self._rsi3 = float(value)
def _try_trade(self, candle):
if (self._rsi1_enabled.Value and self._rsi1 is None) or \
(self._rsi2_enabled.Value and self._rsi2 is None) or \
(self._rsi3_enabled.Value and self._rsi3 is None):
return
cd = int(self.cooldown_period)
if self._buy_cooldown < cd:
self._buy_cooldown += 1
if self._sell_cooldown < cd:
self._sell_cooldown += 1
bt = float(self.buy_threshold)
st = float(self.sell_threshold)
buy_ok = (not self._rsi1_enabled.Value or self._rsi1 < bt) and \
(not self._rsi2_enabled.Value or self._rsi2 < bt) and \
(not self._rsi3_enabled.Value or self._rsi3 < bt)
sell_ok = (not self._rsi1_enabled.Value or self._rsi1 > st) and \
(not self._rsi2_enabled.Value or self._rsi2 > st) and \
(not self._rsi3_enabled.Value or self._rsi3 > st)
if buy_ok and self._buy_cooldown >= cd:
self.BuyMarket()
self._sell_cooldown = cd
self._buy_cooldown = 0
elif sell_ok and self._sell_cooldown >= cd:
self.SellMarket()
self._sell_cooldown = 0
self._buy_cooldown = cd
def CreateClone(self):
return multi_timeframe_rsi_buy_sell_strategy()