Открыть на GitHub

Стратегия TemplateEAbyMarket

Обзор

TemplateEAbyMarket — это прямая портированная версия советника MetaTrader 4 TemplateEAbyMarket.mq4 на платформу StockSharp. Стратегия использует индикатор MACD для отслеживания сдвигов импульса. Когда основная линия MACD пересекает сигнальную линию при условии, что обе находятся в одной положительной или отрицательной зоне, открывается рыночная позиция в направлении пересечения. Выход из сделки осуществляется исключительно через защитные уровни (тейк-профит и стоп-лосс), которые настраиваются с помощью StartProtection.

Поведение полностью повторяет оригинальный MQL-алгоритм: стратегия только открывает позиции и не пытается автоматически закрывать противоположную сторону. После открытия сделка ведётся защитными уровнями или вручную.

Торговая логика

  1. Выполняется подписка на выбранный пользователем тип свечей (по умолчанию — 15-минутный таймфрейм).
  2. На каждой завершённой свече рассчитывается MACD с параметрами 12/26/9 (по умолчанию).
  3. Отслеживается относительное положение основной и сигнальной линий MACD для фиксации события пересечения:
    • Бычий сценарий: на предыдущей свече основная линия была ниже сигнальной, текущая свеча закрылась выше, и обе линии находятся выше нулевого уровня. Отправляется рыночная заявка на покупку объёмом OrderVolume, если текущая экспозиция меньше MaxOrders * OrderVolume.
    • Медвежий сценарий: на предыдущей свече основная линия была выше сигнальной, текущая свеча закрылась ниже, и обе линии находятся ниже нулевого уровня. Отправляется рыночная заявка на продажу с тем же ограничением по экспозиции.
  4. Защитные уровни takeProfit и stopLoss активируются один раз при запуске. Автоматического переворота позиции нет — риск контролируется модулем защиты или пользователем.

Параметры

Имя Описание
MacdFastPeriod Период быстрой EMA в расчёте MACD.
MacdSlowPeriod Период медленной EMA в расчёте MACD.
MacdSignalPeriod Период сигнальной EMA MACD.
CandleType Тип свечей (таймфрейм), используемый в расчётах.
OrderVolume Объём каждой рыночной заявки.
MaxOrders Максимальное количество одновременных заявок в кратных OrderVolume. Перед новой заявкой проверяется условие abs(Position) < MaxOrders * OrderVolume.
TakeProfitPoints Дистанция тейк-профита в ценовых пунктах. Значение 0 отключает тейк-профит.
StopLossPoints Дистанция стоп-лосса в ценовых пунктах. Значение 0 отключает стоп-лосс.

Примечания

  • Параметры проскальзывания и magic number из MQL-версии опущены, поскольку в StockSharp они реализуются иначе.
  • Убедитесь, что коннектор возвращает корректные параметры шага цены; StartProtection интерпретирует дистанции в ценовых пунктах инструмента.
  • Стратегия намеренно оставлена минималистичной и не обрабатывает частичные исполнения либо наращивание позиции сверх лимита MaxOrders.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Template EA by Market strategy: MACD histogram crossover with signal line.
/// </summary>
public class TemplateEAbyMarketStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalPeriod;

	private decimal _prevMacd;
	private decimal _prevSignal;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int SignalPeriod { get => _signalPeriod.Value; set => _signalPeriod.Value = value; }

	public TemplateEAbyMarketStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "MACD fast EMA", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "MACD slow EMA", "Indicators");
		_signalPeriod = Param(nameof(SignalPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Signal Period", "MACD signal period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevMacd = 0m;
		_prevSignal = 0m;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;
		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd = { ShortMa = { Length = FastPeriod }, LongMa = { Length = SlowPeriod } },
			SignalMa = { Length = SignalPeriod }
		};
		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(macd, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!macdValue.IsFinal) return;

		var v = (MovingAverageConvergenceDivergenceSignalValue)macdValue;
		if (v.Macd is not decimal macdLine || v.Signal is not decimal signal) return;

		if (_hasPrev)
		{
			var prevHist = _prevMacd - _prevSignal;
			var currHist = macdLine - signal;

			if (prevHist <= 0 && currHist > 0 && Position <= 0)
				BuyMarket();
			else if (prevHist >= 0 && currHist < 0 && Position >= 0)
				SellMarket();
		}

		_prevMacd = macdLine;
		_prevSignal = signal;
		_hasPrev = true;
	}
}