Ver en GitHub

Panel de Rompimiento RSI Híbrido

La estrategia combina la reversión a la media del RSI con entradas de ruptura filtradas por ADX y una EMA de 200.

El sistema compra cuando el mercado está en rango y el RSI cae por debajo de RsiBuy en tendencia alcista de la EMA. Vende en corto cuando el RSI sube por encima de RsiSell en tendencia bajista. En régimen tendencial, entra en rupturas por encima/debajo de cierres recientes y rastrea la posición usando ATR.

Incluye un filtro de fecha de inicio y variables simples de panel para el último tipo de trade y dirección.

Detalles

  • Criterios de entrada: Señales de RSI en régimen de rango con sesgo de EMA, o rupturas por encima/debajo de los BreakoutLength cierres anteriores cuando ADX > AdxThreshold.
  • Largo/Corto: Ambos.
  • Criterios de salida: Los trades de RSI salen en RsiExit. Los trades de ruptura usan trailing stop ATR.
  • Stops: Trailing stop ATR para trades de ruptura.
  • Valores predeterminados:
    • AdxLength = 14
    • AdxThreshold = 20m
    • EmaLength = 200
    • RsiLength = 14
    • RsiBuy = 40m
    • RsiSell = 60m
    • RsiExit = 50m
    • BreakoutLength = 20
    • AtrLength = 14
    • AtrMultiplier = 2m
    • StartDate = 2017-01-01
    • CandleType = TimeSpan.FromMinutes(5)
  • Filtros:
    • Categoría: Tendencia, Reversión a la media
    • Dirección: Ambos
    • Indicadores: ADX, EMA, RSI, ATR, Highest/Lowest
    • Stops: Trailing
    • Complejidad: Moderado
    • Marco temporal: Intradía (5m)
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • 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;

public class HybridRsiBreakoutDashboardStrategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaPeriod;
	private readonly StrategyParam<int> _slowEmaPeriod;
	private readonly StrategyParam<DataType> _candleType;
	private decimal _prevFastEma;
	private decimal _prevSlowEma;

	public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
	public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public HybridRsiBreakoutDashboardStrategy()
	{
		_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFastEma = 0m;
		_prevSlowEma = 0m;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fastEma, slowEma, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fastEma);
			DrawIndicator(area, slowEma);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastEmaValue, decimal slowEmaValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevFastEma == 0m || _prevSlowEma == 0m)
		{
			_prevFastEma = fastEmaValue;
			_prevSlowEma = slowEmaValue;
			return;
		}
		if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
			BuyMarket();
		else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
			SellMarket();
		_prevFastEma = fastEmaValue;
		_prevSlowEma = slowEmaValue;
	}
}