Открыть на GitHub

Простая стратегия по паттерну «Поглощение»

Обзор

Simple Engulfing Strategy воспроизводит работу советников MetaTrader 4 «simple engulf mt4 buy» и «simple engulf mt4 sell». Оригинальные советники ищут свечной паттерн «поглощение» и открывают сделки только в одном направлении. В версии для StockSharp оба робота объединены в один класс с параметром Direction, позволяющим выбрать работу только в лонг, только в шорт или в обе стороны.

Стратегия реагирует исключительно на завершённые свечи, что полностью соответствует логике MetaTrader. Для подписки на данные и выставления заявок применяются высокоуровневые методы StockSharp (SubscribeCandles, Bind, BuyMarket, SellMarket, StartProtection).

Логика торговли

  1. Формировать свечи согласно параметру CandleType.
  2. Обрабатывать сигналы только после закрытия очередной свечи, параллельно запоминая предыдущую завершённую свечу.
  3. Рассчитывать размер тела текущей свечи в пунктах. Если он меньше MinBodyPips или больше MaxBodyPips (при активном верхнем фильтре), сигнал отбрасывается.
  4. Условия бычьего поглощения:
    • Предыдущая свеча медвежья (закрытие ниже открытия).
    • Текущая свеча бычья (закрытие выше открытия).
    • Открытие текущей свечи не выше закрытия предыдущей.
    • Закрытие текущей свечи не ниже открытия предыдущей.
  5. Условия медвежьего поглощения симметричны.
  6. После появления паттерна проверяется доступность торговли (IsFormedAndOnlineAndAllowTrading()) и разрешено ли направление параметром Direction:
    • BuyOnly — поведение советника «simple engulf mt4 buy».
    • SellOnly — поведение советника «simple engulf mt4 sell».
    • Both — торговля в обе стороны.
  7. Для входа используется объём TradeVolume. Если уже существует позиция противоположного знака, стратегия добавляет её абсолютный объём к заявке, тем самым закрывая старую позицию и разворачиваясь, как это делает оригинальный советник.
  8. При положительных значениях StopLossPips или TakeProfitPips активируется StartProtection, который переводит расстояние в пунктах в реальное ценовое смещение и выставляет защитные заявки.

Параметры

Параметр Значение по умолчанию Описание
CandleType 15 минут Тип и таймфрейм свечей для анализа.
TradeVolume 0.01 Объём каждой сделки, совпадает с настройкой MT4.
StopLossPips 20 Расстояние до стоп-лосса в пунктах. Ноль отключает защиту.
TakeProfitPips 20 Расстояние до тейк-профита в пунктах. Ноль отключает защиту.
MinBodyPips 0 Минимальный размер тела свечи в пунктах.
MaxBodyPips 50 Максимальный размер тела свечи в пунктах. Значение 0 отключает ограничение.
Direction BuyOnly Разрешённое направление торговли: только покупки, только продажи или оба варианта.

Практические рекомендации

  • Размер пункта вычисляется автоматически на основе PriceStep и количества знаков инструмента. Это позволяет корректно применять фильтры как на четырёх-, так и на пятизнаковых котировках.
  • Защитные заявки отправляются только при положительных StopLossPips или TakeProfitPips. В остальных случаях выход из позиции остаётся на усмотрение трейдера или других модулей.
  • Сигналы возникают строго на закрытии свечи, поэтому внутри свечи стратегия не «перерисовывается».
  • Код построен на высокоуровневом API StockSharp, что упрощает сопровождение и соблюдает требования проекта.

Отличия от оригинала

  • Два советника объединены в одну стратегию с параметром Direction вместо отдельных файлов.
  • Добавлены вспомогательные возможности StockSharp: при желании можно отобразить свечи и сделки на графике, а также вести журнал сообщений.
  • Управление защитными приказами реализовано через StartProtection, что обеспечивает поведение, аналогичное жёстким стопам в MetaTrader.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Simple Engulfing strategy: engulfing candlestick pattern with EMA filter.
/// Buys on bullish engulfing above EMA, sells on bearish engulfing below EMA.
/// </summary>
public class SimpleEngulfingStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;

	private decimal _prevOpen;
	private decimal _prevClose;
	private bool _hasPrev;

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

	public SimpleEngulfingStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevOpen = 0;
		_prevClose = 0;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, ProcessCandle).Start();
	}

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

		if (_hasPrev)
		{
			var prevBearish = _prevClose < _prevOpen;
			var currBullish = candle.ClosePrice > candle.OpenPrice;
			var bullishEngulf = prevBearish && currBullish
				&& candle.OpenPrice <= _prevClose && candle.ClosePrice >= _prevOpen;

			var prevBullish = _prevClose > _prevOpen;
			var currBearish = candle.ClosePrice < candle.OpenPrice;
			var bearishEngulf = prevBullish && currBearish
				&& candle.OpenPrice >= _prevClose && candle.ClosePrice <= _prevOpen;

			if (bullishEngulf && candle.ClosePrice > emaValue && Position <= 0)
				BuyMarket();
			else if (bearishEngulf && candle.ClosePrice < emaValue && Position >= 0)
				SellMarket();
		}

		_prevOpen = candle.OpenPrice;
		_prevClose = candle.ClosePrice;
		_hasPrev = true;
	}
}