Открыть на GitHub

Стратегия M.A Break

Стратегия повторяет логику советников MetaTrader «M.A break mt5 buy» и «M.A break mt5 sell», объединяя длинные и короткие сигналы в одном алгоритме StockSharp. Она анализирует завершённые свечи выбранного таймфрейма, сравнивает несколько экспоненциальных скользящих средних и проверяет структуру импульсной свечи перед открытием позиции. Управление сделкой осуществляется фиксированными стоп-лоссами и тейк-профитами, задаваемыми в пунктах.

Алгоритм работы

  1. Подтверждение тренда. Две пары EMA должны располагаться в направлении сделки: для покупок обе быстрые средние выше медленных, для продаж — ниже. Дополнительно проверяется, что открытие предыдущей свечи находится по правильную сторону от фильтрующей EMA.
  2. Оценка «тихого» диапазона. Перед импульсом учитывается заданное число предыдущих свечей. Максимальный размах их цен (High-Low) используется как базовый диапазон и сравнивается с минимальным порогом в пунктах.
  3. Проверка импульса. Последняя закрытая свеча должна иметь размер не меньше ImpulseStrength * «тихий» диапазон. При необходимости можно ограничить минимальную и максимальную величину свечи в пунктах.
  4. Шаблон свечи. Импульсная свеча должна соответствовать форме:
    • Для покупок: свеча бычья, верхняя тень не превышает BullUpperWickPercent диапазона, нижняя тень не меньше BullLowerWickPercent.
    • Для продаж: свеча медвежья, верхняя тень минимум BearUpperWickPercent, нижняя тень максимум BearLowerWickPercent.
  5. Условие отката. Минимум (для покупок) или максимум (для продаж) импульсной свечи обязан коснуться дополнительной EMA, что подтверждает выход из отката.
  6. Контроль позиции. В системе поддерживается только одна нетто-позиция. При появлении сигнала противоположного направления текущая позиция закрывается перед открытием новой. Стратегия не торгует против фильтров тренда.
  7. Выход из сделки. Стоп и цель рассчитываются от цены входа по заданным расстояниям в пунктах. После закрытия каждой свечи проверяется, достигнута ли защита; при одновременном срабатывании приоритет отдаётся стоп-лоссу.

Параметры

Параметр Описание
Candle Type Основная серия свечей, по которой выполняются расчёты.
Fast MA 1 / Slow MA 1 Периоды первой пары EMA для базового трендового фильтра.
Fast MA 2 / Slow MA 2 Периоды второй пары EMA для дополнительного подтверждения тренда.
Open Filter MA Период EMA, с которой сравнивается открытие предыдущей свечи.
Pullback MA EMA, которую должна протестировать тень импульсной свечи.
Quiet Bars Количество свечей в тихом диапазоне перед импульсом.
Quiet Range (pips) Минимальный размер тихого диапазона в пунктах.
Impulse Multiplier Минимальное отношение размера импульсной свечи к тихому диапазону.
Min / Max Candle Size (pips) Ограничения на диапазон импульсной свечи. Ноль отключает проверку.
Bull Upper Wick % / Bull Lower Wick % Допустимые тени бычьей импульсной свечи в процентах от диапазона.
Bear Upper Wick % / Bear Lower Wick % Допустимые тени медвежьей импульсной свечи.
Volume Объём заявки в лотах.
Stop-Loss (pips) Расстояние до защитного стопа. Ноль — без стопа.
Take-Profit (pips) Расстояние до тейк-профита. Ноль — без цели.
Enable Long / Enable Short Включение торговых сигналов в соответствующем направлении.

Рекомендации по использованию

  • Настройте тип свечей согласно исходным роботам (например, M5 или H1). По умолчанию используется пятиминутный таймфрейм.
  • В памяти хранится только столько свечей, сколько нужно для расчёта тихого диапазона, чтобы избежать лишнего расхода ресурсов.
  • Цена входа приближается к закрытию импульсной свечи, что соответствует постановке рыночного ордера на открытии следующей свечи в MetaTrader.
  • Проверка стопов и целей выполняется после закрытия каждой свечи. Если на одной свече достигаются оба уровня, срабатывает стоп-лосс для консервативного поведения.
  • Отключение одного из направлений позволяет воспроизвести отдельный советник «buy» или «sell».

Особенности конверсии

  • Оба MQ5-файла имели кодировку UTF-16 и были построены из блоков FXD. Каждый блок был преобразован в явные условия на C#.
  • Все проверки используют данные закрытых свечей (Shift = 1), как и в исходных советниках.
  • Виртуальные стопы и графические подписи, присутствующие в MQ5, не влияют на торговлю и потому опущены.

Тестирование

Скомпилируйте решение AlgoTrading.sln или запустите стратегию в тестере StockSharp. Если у инструмента отсутствует шаг цены, задайте его вручную; в противном случае используется значение по умолчанию 0.0001, подходящее для большинства валютных пар.

namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// MA Break strategy: EMA breakout with impulse candle confirmation.
/// Buys when close crosses above EMA with strong bullish candle body.
/// Sells when close crosses below EMA with strong bearish candle body.
/// </summary>
public class MaBreakStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<decimal> _bodyRatio;

	private decimal _prevClose;
	private decimal _prevEma;
	private bool _hasPrev;

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

	public MaBreakStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period for breakout", "Indicators");
		_bodyRatio = Param(nameof(BodyRatio), 0.7m)
			.SetDisplay("Body Ratio", "Min body/range ratio for impulse", "Pattern");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = 0;
		_prevEma = 0;
		_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;

		var range = candle.HighPrice - candle.LowPrice;
		var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);

		if (_hasPrev && range > 0)
		{
			var isImpulse = body >= range * BodyRatio;

			if (_prevClose <= _prevEma && candle.ClosePrice > emaValue
				&& candle.ClosePrice > candle.OpenPrice && isImpulse && Position <= 0)
				BuyMarket();
			else if (_prevClose >= _prevEma && candle.ClosePrice < emaValue
				&& candle.ClosePrice < candle.OpenPrice && isImpulse && Position >= 0)
				SellMarket();
		}

		_prevClose = candle.ClosePrice;
		_prevEma = emaValue;
		_hasPrev = true;
	}
}