Открыть на GitHub

Стратегия LeMan Trend Hist

Данная стратегия представляет собой упрощённую конвертацию оригинального эксперта MQL5 «LeManTrendHist». В качестве источника сигналов используется гистограмма на основе экспоненциального скользящего среднего.

Идея

Исходный алгоритм вычисляет специальную гистограмму на основе экстремумов цены и сглаженных диапазонов. В этом примере гистограмма приблизительно рассчитывается как EMA диапазона свечи.

Логика стратегии

  1. Для каждой завершённой свечи вычисляется значение EMA.
  2. Сравниваются три последних значения EMA.
  3. Если среднее значение меньше самого старого, а новое значение выше среднего, открывается длинная позиция и закрываются короткие.
  4. Если среднее значение больше самого старого, а новое значение ниже среднего, открывается короткая позиция и закрываются длинные.

Параметры

  • Candle Type – таймфрейм обрабатываемых свечей.
  • EMA Period – период EMA, используемого в гистограмме-заглушке.
  • Signal Bar – сдвиг по истории для значений индикатора (оставлен для совместимости, в упрощённой логике не используется).
  • Buy/Sell Open – разрешение открытия длинных или коротких позиций.
  • Buy/Sell Close – разрешение закрытия существующих позиций.

Примечания

Настоящий индикатор LeManTrendHist использует сложные алгоритмы сглаживания, которые пока не реализованы. Текущая реализация служит временной заглушкой и должна быть заменена полноценным индикатором для боевого использования.

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();
		}
	}
}