Ver en GitHub

Estrategia LeMan Trend Hist

Esta estrategia es una conversión simplificada del experto MQL5 original "LeManTrendHist". Se basa en un histograma basado en EMA para generar señales de trading.

Idea

El algoritmo original calcula un histograma personalizado derivado de extremos de precio y rangos suavizados. Para esta muestra, el histograma se aproxima mediante una media móvil exponencial de los rangos de velas.

Lógica de la estrategia

  1. Calcular el valor EMA para cada vela completada.
  2. Comparar los tres últimos valores EMA.
  3. Cuando el valor del medio es menor que el más antiguo y el nuevo valor sube por encima de él, se abre una posición larga y se cierran las posiciones cortas.
  4. Cuando el valor del medio es mayor que el más antiguo y el nuevo valor cae por debajo de él, se abre una posición corta y se cierran las posiciones largas.

Parámetros

  • Candle Type – marco temporal de las velas procesadas.
  • EMA Period – longitud del EMA usado en el histograma de marcador de posición.
  • Signal Bar – desplazamiento histórico para los valores del indicador (mantenido por compatibilidad, no se usa en la lógica simplificada).
  • Buy/Sell Open – habilitar entradas largas o cortas.
  • Buy/Sell Close – habilitar el cierre de posiciones existentes.

Notas

El indicador real LeManTrendHist utiliza algoritmos de suavizado complejos que aún no están implementados. La implementación actual actúa como un marcador de posición y debe reemplazarse con el indicador completo para uso en producción.

using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// LeManTrendHist strategy using EMA slope changes as trend signals.
/// </summary>
public class LeManTrendHistStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;

	private decimal? _value1;
	private decimal? _value2;
	private decimal? _value3;

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

	public int EmaPeriod
	{
		get => _emaPeriod.Value;
		set => _emaPeriod.Value = value;
	}

	public LeManTrendHistStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");

		_emaPeriod = Param(nameof(EmaPeriod), 3)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA length", "Parameters");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_value1 = null;
		_value2 = null;
		_value3 = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, ProcessCandle).Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, ema);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		_value3 = _value2;
		_value2 = _value1;
		_value1 = emaValue;

		if (_value1 is null || _value2 is null || _value3 is null)
			return;

		// EMA turned up (was falling, now rising)
		if (_value2 < _value3 && _value1 > _value2)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// EMA turned down (was rising, now falling)
		else if (_value2 > _value3 && _value1 < _value2)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}
	}
}