Estrategia de impulso RRS
La RRS Impulse Strategy es una versión StockSharp de alto nivel del MetaTrader asesor experto "RRS Impulse". El robot original
filtros de bandas combinados RSI, Stochastic y Bollinger, rotados entre varios modos de intensidad de señal y paradas protectoras utilizadas y
salidas finales virtuales. Esta versión de C# mantiene el mismo comportamiento pero se basa exclusivamente en el StockSharp nivel alto API: vela
las suscripciones alimentan los indicadores, mientras que BuyMarket, SellMarket y ClosePosition ejecutan las órdenes.
Lógica de trading
- Modos de indicador: elija entre cuatro opciones:
Rsi: opera con el oscilador cuando sale de la zona de sobrecompra/sobreventa.
Stochastic: requiere que %K y %D estén por encima o por debajo de los niveles configurados.
BollingerBands: reacciona ante cierres por encima de la banda superior o por debajo de la banda inferior.
RsiStochasticBollinger: se activa solo cuando los tres filtros confirman la misma dirección.
- Dirección comercial:
Trend sigue el indicador (la sobrecompra conduce a posiciones cortas, la sobreventa a posiciones largas). CounterTrend desvanece el
movimiento (la sobrecompra desencadena posiciones largas, la sobreventa activa posiciones cortas).
- Intensidad de la señal: controla cuántos períodos de tiempo deben acordar antes de ingresar a una operación:
SingleTimeFrame: utilice únicamente el plazo base proporcionado por CandleType.
MultiTimeFrame: requiere alineación entre velas M1, M5, M15, M30, H1 y H4.
Strong: céntrese en el impulso intradiario marcando M1, M5, M15 y M30.
VeryStrong: exige confirmación de la escalera M1...H4 completa. Cuando el modo de indicador combinado está habilitado en cada período de tiempo
debe satisfacer los tres filtros.
- Gestión de riesgos: cada posición rastrea el precio de ejecución promedio y monitorea tres condiciones de salida:
- distancia fija de stop-loss en pips;
- distancia fija de obtención de beneficios en pips;
- trailing stop activado una vez que la ganancia excede
TrailingStartPips y mantenido por TrailingGapPips.
Siempre que la dirección cambia, la estrategia llama a ClosePosition() primero para aplanarse y solo abre la operación opuesta después
el siguiente tick de confirmación.
Parámetros
| grupo |
Nombre |
Descripción |
| Datos |
CandleType |
Serie de velas base procesadas para decisiones comerciales. |
| Órdenes |
TradeVolume |
Volumen utilizado al enviar órdenes de mercado. |
| Riesgo |
StopLossPips, TakeProfitPips, TrailingStartPips, TrailingGapPips |
Salidas protectoras virtuales expresadas en pips. |
| Señales |
IndicatorMode, TradeDirection, SignalStrength |
Cambios de comportamiento copiados del bloque de entrada MQL. |
| RSI |
RsiPeriod, RsiUpperLevel, RsiLowerLevel |
Configuración RSI para detección de sobrecompra/sobreventa. |
| Stochastic |
StochasticKPeriod, StochasticDPeriod, StochasticSlowing, StochasticUpperLevel, StochasticLowerLevel |
Configuraciones lentas del oscilador estocástico. |
| Bollinger |
BollingerPeriod, BollingerDeviation |
Bollinger Multiplicador de desviación y retroceso de bandas. |
Todos los parámetros admiten rangos de optimización idénticos a la versión MetaTrader donde tenía sentido (por ejemplo, detenerse y tomar distancias).
u umbrales del oscilador).
Requisitos de datos
La estrategia necesita velas diminutas para la escalera de confirmación. Cuando SignalStrength solicita plazos adicionales, la estrategia
agrega automáticamente las suscripciones requeridas (GetWorkingSecurities las anuncia en el motor). No se utilizan comillas de nivel 1;
sólo los precios de cierre de las velas terminadas impulsan las entradas y salidas. Por lo tanto, la lógica de protección reproduce la parada/objetivo "virtual".
comportamiento del robot original.
Notas sobre la conversión
- La rotación aleatoria de símbolos de EA se eliminó intencionalmente. Las estrategias StockSharp funcionan con un solo
Security, por lo que el
El puerto se concentra en hacer coincidir la lógica del indicador y la gestión de riesgos, dejando la rotación del instrumento en manos del usuario.
- La gestión de órdenes se basa en el mercado: cuando la dirección cambia o se activa una condición de protección, se llama a
ClosePosition(),
reflejando los bucles MetaTrader que se repitieron a través de los tickets.
- La conversión mantiene todos los comentarios en inglés y utiliza pestañas para sangría para cumplir con las pautas del repositorio.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// RRS Impulse strategy.
/// Combines RSI, Stochastic and Bollinger Bands for counter-trend entries.
/// </summary>
public class RrsImpulseStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiUpperLevel;
private readonly StrategyParam<decimal> _rsiLowerLevel;
private readonly StrategyParam<int> _stochasticKPeriod;
private readonly StrategyParam<int> _stochasticDPeriod;
private readonly StrategyParam<decimal> _stochasticUpperLevel;
private readonly StrategyParam<decimal> _stochasticLowerLevel;
private readonly StrategyParam<int> _bollingerPeriod;
private readonly StrategyParam<decimal> _bollingerDeviation;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal RsiUpperLevel { get => _rsiUpperLevel.Value; set => _rsiUpperLevel.Value = value; }
public decimal RsiLowerLevel { get => _rsiLowerLevel.Value; set => _rsiLowerLevel.Value = value; }
public int StochasticKPeriod { get => _stochasticKPeriod.Value; set => _stochasticKPeriod.Value = value; }
public int StochasticDPeriod { get => _stochasticDPeriod.Value; set => _stochasticDPeriod.Value = value; }
public decimal StochasticUpperLevel { get => _stochasticUpperLevel.Value; set => _stochasticUpperLevel.Value = value; }
public decimal StochasticLowerLevel { get => _stochasticLowerLevel.Value; set => _stochasticLowerLevel.Value = value; }
public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
public decimal BollingerDeviation { get => _bollingerDeviation.Value; set => _bollingerDeviation.Value = value; }
public RrsImpulseStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI length", "RSI");
_rsiUpperLevel = Param(nameof(RsiUpperLevel), 65m)
.SetDisplay("RSI Upper", "Overbought", "RSI");
_rsiLowerLevel = Param(nameof(RsiLowerLevel), 35m)
.SetDisplay("RSI Lower", "Oversold", "RSI");
_stochasticKPeriod = Param(nameof(StochasticKPeriod), 10)
.SetDisplay("Stochastic %K", "%K period", "Stochastic");
_stochasticDPeriod = Param(nameof(StochasticDPeriod), 3)
.SetDisplay("Stochastic %D", "%D period", "Stochastic");
_stochasticUpperLevel = Param(nameof(StochasticUpperLevel), 70m)
.SetDisplay("Stochastic Upper", "Overbought", "Stochastic");
_stochasticLowerLevel = Param(nameof(StochasticLowerLevel), 30m)
.SetDisplay("Stochastic Lower", "Oversold", "Stochastic");
_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
.SetDisplay("Bollinger Period", "BB length", "Bollinger");
_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
.SetDisplay("Bollinger Deviation", "BB deviation", "Bollinger");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var stochastic = new StochasticOscillator();
stochastic.K.Length = StochasticKPeriod;
stochastic.D.Length = StochasticDPeriod;
var bollinger = new BollingerBands { Length = BollingerPeriod, Width = BollingerDeviation };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(rsi, stochastic, bollinger, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, bollinger);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue rsiVal, IIndicatorValue stochVal, IIndicatorValue bbVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!rsiVal.IsFinal || !stochVal.IsFinal || !bbVal.IsFinal)
return;
if (!rsiVal.IsFormed || !stochVal.IsFormed || !bbVal.IsFormed)
return;
var rsi = rsiVal.GetValue<decimal>();
var stoch = (StochasticOscillatorValue)stochVal;
var stochK = stoch.K ?? 50m;
var bb = (BollingerBandsValue)bbVal;
var bbUpper = bb.UpBand ?? candle.ClosePrice;
var bbLower = bb.LowBand ?? candle.ClosePrice;
var close = candle.ClosePrice;
// Count how many indicators signal overbought/oversold
var obSignals = 0;
var osSignals = 0;
if (rsi >= RsiUpperLevel) obSignals++;
if (rsi <= RsiLowerLevel) osSignals++;
if (stochK >= StochasticUpperLevel) obSignals++;
if (stochK <= StochasticLowerLevel) osSignals++;
if (close >= bbUpper) obSignals++;
if (close <= bbLower) osSignals++;
// Counter-trend: need at least 2 of 3 indicators confirming
if (osSignals >= 2 && Position <= 0)
{
BuyMarket();
}
else if (obSignals >= 2 && Position >= 0)
{
SellMarket();
}
// Exit long when RSI and stoch neutralize
else if (Position > 0 && rsi > 50m && stochK > 50m)
{
SellMarket();
}
// Exit short when RSI and stoch neutralize
else if (Position < 0 && rsi < 50m && stochK < 50m)
{
BuyMarket();
}
}
}
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 BollingerBands, RelativeStrengthIndex, StochasticOscillator
from StockSharp.Algo.Strategies import Strategy
class rrs_impulse_strategy(Strategy):
"""RSI + Stochastic + Bollinger Bands counter-trend strategy."""
def __init__(self):
super(rrs_impulse_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("RSI Period", "RSI length", "RSI")
self._rsi_upper_level = self.Param("RsiUpperLevel", 65.0) \
.SetDisplay("RSI Upper", "Overbought", "RSI")
self._rsi_lower_level = self.Param("RsiLowerLevel", 35.0) \
.SetDisplay("RSI Lower", "Oversold", "RSI")
self._stochastic_k_period = self.Param("StochasticKPeriod", 10) \
.SetGreaterThanZero() \
.SetDisplay("Stochastic %K", "%K period", "Stochastic")
self._stochastic_d_period = self.Param("StochasticDPeriod", 3) \
.SetGreaterThanZero() \
.SetDisplay("Stochastic %D", "%D period", "Stochastic")
self._stochastic_upper_level = self.Param("StochasticUpperLevel", 70.0) \
.SetDisplay("Stochastic Upper", "Overbought", "Stochastic")
self._stochastic_lower_level = self.Param("StochasticLowerLevel", 30.0) \
.SetDisplay("Stochastic Lower", "Oversold", "Stochastic")
self._bollinger_period = self.Param("BollingerPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("Bollinger Period", "BB length", "Bollinger")
self._bollinger_deviation = self.Param("BollingerDeviation", 2.0) \
.SetGreaterThanZero() \
.SetDisplay("Bollinger Deviation", "BB deviation", "Bollinger")
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(rrs_impulse_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self._rsi_period.Value
stochastic = StochasticOscillator()
stochastic.K.Length = self._stochastic_k_period.Value
stochastic.D.Length = self._stochastic_d_period.Value
bollinger = BollingerBands()
bollinger.Length = self._bollinger_period.Value
bollinger.Width = self._bollinger_deviation.Value
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(rsi, stochastic, bollinger, self._process_candle).Start()
def _process_candle(self, candle, rsi_val, stoch_val, bb_val):
if candle.State != CandleStates.Finished:
return
if not rsi_val.IsFinal or not stoch_val.IsFinal or not bb_val.IsFinal:
return
if not rsi_val.IsFormed or not stoch_val.IsFormed or not bb_val.IsFormed:
return
rsi = float(rsi_val)
stoch_k = float(stoch_val.K) if stoch_val.K is not None else 50.0
bb_upper = bb_val.UpBand
bb_lower = bb_val.LowBand
upper = float(bb_upper) if bb_upper is not None else float(candle.ClosePrice)
lower = float(bb_lower) if bb_lower is not None else float(candle.ClosePrice)
close = float(candle.ClosePrice)
ob_signals = 0
os_signals = 0
if rsi >= float(self._rsi_upper_level.Value):
ob_signals += 1
if rsi <= float(self._rsi_lower_level.Value):
os_signals += 1
if stoch_k >= float(self._stochastic_upper_level.Value):
ob_signals += 1
if stoch_k <= float(self._stochastic_lower_level.Value):
os_signals += 1
if close >= upper:
ob_signals += 1
if close <= lower:
os_signals += 1
if os_signals >= 2 and self.Position <= 0:
self.BuyMarket()
elif ob_signals >= 2 and self.Position >= 0:
self.SellMarket()
elif self.Position > 0 and rsi > 50.0 and stoch_k > 50.0:
self.SellMarket()
elif self.Position < 0 and rsi < 50.0 and stoch_k < 50.0:
self.BuyMarket()
def CreateClone(self):
return rrs_impulse_strategy()