Ver en GitHub

Estrategia RSI + MACD Solo Largos

La estrategia entra en largo cuando el RSI cruza por encima de la línea media con confirmación alcista del MACD, o cuando el MACD cruza por encima de su línea de señal mientras el RSI se mantiene por encima de la línea media. Las salidas ocurren cuando el RSI cae por debajo de la línea media o el MACD cruza por debajo de la señal con un histograma no positivo. Un filtro de tendencia EMA opcional y el contexto de sobrevendido pueden refinar las entradas.

Detalles

  • Criterios de entrada: RSI cruza por encima de la línea media con MACD alcista o MACD cruza por encima de la señal con RSI sobre la línea media
  • Largo/Corto: Solo largos
  • Criterios de salida: RSI cruza por debajo de la línea media o MACD cruza por debajo de la señal con histograma ≤ 0
  • Stops: Take profit y stop loss en porcentaje opcionales
  • Valores predeterminados:
    • RsiLength = 14
    • RsiOversold = 30
    • RsiMidline = 50
    • FastLength = 12
    • SlowLength = 26
    • SignalLength = 9
    • OversoldWindowBars = 10
    • EmaLength = 200
    • TakeProfitPercent = 11.5
    • StopLossPercent = 2.5
  • Filtros:
    • Categoría: Tendencia
    • Dirección: Solo largos
    • Indicadores: RSI, MACD, EMA
    • Stops: Sí (opcional)
    • Complejidad: Intermedio
    • Marco temporal: Intradía
    • 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;

/// <summary>
/// RSI MACD long only strategy using EMA crossover.
/// </summary>
public class RsiMacdLongOnlyStrategy : Strategy
{
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public RsiMacdLongOnlyStrategy()
	{
		_slowLength = Param(nameof(SlowLength), 40)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "General");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fast = new ExponentialMovingAverage { Length = 14 };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var prevF = 0m; var prevS = 0m; var init = false;
		var lastSignal = DateTimeOffset.MinValue;
		var cooldown = TimeSpan.FromMinutes(360);
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, (candle, f, s) =>
		{
			if (candle.State != CandleStates.Finished) return;
			if (!fast.IsFormed || !slow.IsFormed) return;
			if (!init) { prevF = f; prevS = s; init = true; return; }
			if (candle.OpenTime - lastSignal >= cooldown)
			{
				if (prevF <= prevS && f > s && Position <= 0) { BuyMarket(); lastSignal = candle.OpenTime; }
				else if (prevF >= prevS && f < s && Position >= 0) { SellMarket(); lastSignal = candle.OpenTime; }
			}
			prevF = f; prevS = s;
		}).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}
}