Ver en GitHub

Estrategia de Retroceso Rentable Mark804

Una estrategia de retroceso de seguimiento de tendencia que utiliza una cinta de medias móviles exponenciales. El sistema busca retrocesos del precio hacia la EMA de señal dentro de una tendencia confirmada. Cuando el precio cierra de nuevo en la dirección de la tendencia tras un retroceso, la estrategia abre una posición y la protege con niveles de take profit y stop loss basados en porcentaje.

Detalles

  • Criterios de entrada:
    • Largo: EMA rápida > EMA señal > EMA media, opcionalmente EMA media > EMA lenta, cierre anterior por debajo de la EMA señal y cierre actual por encima.
    • Corto: EMA rápida < EMA señal < EMA media, opcionalmente EMA media < EMA lenta, cierre anterior por encima de la EMA señal y cierre actual por debajo.
  • Largo/Corto: Ambos lados.
  • Criterios de salida: Se alcanza el take profit o el stop loss.
  • Stops: Sí, porcentajes fijos de take profit y stop loss.
  • Valores predeterminados:
    • Fast EMA Length = 8
    • Signal EMA Length = 21
    • Medium EMA Length = 50
    • Slow EMA Length = 200
    • Take Profit % = 2
    • Stop Loss % = 1
  • Filtros:
    • Categoría: Seguimiento de tendencia
    • Dirección: Ambos
    • Indicadores: EMA
    • Stops: Sí
    • Complejidad: Básico
    • Marco temporal: Medio plazo
    • 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>
/// Profitable pullback strategy using EMA crossover.
/// </summary>
public class ProfitablePullbackMark804Strategy : 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 ProfitablePullbackMark804Strategy()
	{
		_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");
	}

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

	/// <inheritdoc />
	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);
		}
	}
}