RsiBoosterStrategy es una adaptación a StockSharp del asesor experto de MetaTrader RSI booster. La estrategia compara el valor rápido de RSI calculado sobre la vela actual con un RSI retrasado que usa la vela anterior. Cuando la diferencia supera una relación definida por el usuario, la estrategia abre una posición de mercado y después gestiona la operación con stops fijos, objetivos de take-profit, un trailing stop opcional y una cadena de órdenes inversas para recuperación de pérdidas.
La estrategia está construida sobre la API de alto nivel de StockSharp. Se suscribe a una sola serie de velas, utiliza los indicadores incorporados RelativeStrengthIndex y emplea el sistema de parámetros de estrategia para que todas las entradas estén disponibles para optimización dentro de Designer.
Lógica de trading
Se calculan dos indicadores RSI en cada vela cerrada.
El RSI rápido usa FirstRsiPeriod y FirstRsiPrice, y lee la vela más reciente.
El RSI retrasado usa SecondRsiPeriod y SecondRsiPrice, pero la estrategia conserva el valor anterior para que actúe con un retraso de una barra.
Cuando fast RSI - delayed RSI es mayor que Ratio, la estrategia compra si no hay una posición larga abierta. Cuando la diferencia está por debajo de -Ratio, vende si no hay una posición corta abierta.
OnlyOnePositionPerBar garantiza que como máximo se produzca una entrada por dirección para la misma marca temporal de vela.
Después de cada vela, la estrategia evalúa las reglas de stop-loss, take-profit y trailing. Si se activa alguna condición, la posición se cierra de inmediato.
Cuando una posición se cierra con PnL realizado negativo, la lógica opcional de recuperación puede abrir una posición inversa (dirección opuesta) con el mismo volumen. El número de operaciones de recuperación encadenadas está limitado por ReturnOrdersMax.
Gestión de riesgos
Stop-loss - expresado en puntos del instrumento mediante StopLossPips. La posición se cierra cuando el precio cruza el nivel de stop.
Take-profit - expresado en puntos del instrumento mediante TakeProfitPips.
Trailing stop - si está habilitado mediante TrailingStopPips, el stop empieza a seguir al precio cuando la ganancia supera la distancia configurada. TrailingStepPips define la mejora mínima necesaria antes de mover el nivel trailing.
Orden de retorno - se activa cuando ReturnOrderEnabled es true. Después de una operación perdedora, la estrategia abre al instante una orden de mercado en la dirección opuesta mientras cuenta cuántas órdenes de recuperación se han emitido.
Parámetros
Parámetro
Descripción
Volume
Volumen de negociación usado para cada orden de mercado (lotes o contratos).
Ratio
Diferencia mínima de RSI necesaria para abrir una posición.
StopLossPips
Distancia del stop-loss en puntos del instrumento.
TakeProfitPips
Distancia del take-profit en puntos del instrumento.
TrailingStopPips
Distancia del trailing stop en puntos del instrumento.
TrailingStepPips
Mejora mínima antes de mover el trailing stop.
OnlyOnePositionPerBar
Impide múltiples entradas durante la misma vela.
ReturnOrderEnabled
Habilita la lógica de recuperación con orden inversa.
ReturnOrdersMax
Número máximo de órdenes de recuperación consecutivas.
FirstRsiPeriod
Período del RSI rápido.
FirstRsiPrice
Fuente de precio para el RSI rápido (coincide con los modos de precio aplicado de MetaTrader).
SecondRsiPeriod
Período del RSI retrasado.
SecondRsiPrice
Fuente de precio para el RSI retrasado (coincide con los modos de precio aplicado de MetaTrader).
CandleType
Serie de velas usada para el análisis.
Notas
La conversión del paso de precio respeta el PriceStep del instrumento siempre que esté disponible. Si el instrumento no proporciona un paso de precio, se usa un valor de reserva de 0.0001.
El contador de la cadena de recuperación se reinicia cuando se produce una operación rentable o cuando se alcanza el número máximo configurado de órdenes de recuperación.
La estrategia dibuja ambos indicadores RSI en el área del gráfico para una inspección visual rápida junto con las operaciones ejecutadas.
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;
public class RsiBoosterStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public RsiBoosterStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class rsi_booster_strategy(Strategy):
def __init__(self):
super(rsi_booster_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(rsi_booster_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(rsi_booster_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return rsi_booster_strategy()