Открыть на GitHub

Базовая стратегия по скользящей средней

Базовая стратегия по скользящей средней — это перенос на StockSharp эксперта MetaTrader 4 из каталога MQL/27964. Исходный робот анализировал свечи старшего таймфрейма и открывал сделку, когда предыдущая свеча пересекала скользящую среднюю. C# версия полностью сохраняет логику, но предоставляет доступ ко всем настройкам через параметры StockSharp, что позволяет удобно оптимизировать систему в новой среде.

Алгоритм ждёт закрытия свечи, затем сравнивает её цену открытия и закрытия с заранее сдвинутым значением скользящей средней. Если свеча открылась выше средней и закрылась ниже — формируется короткий сигнал; если наоборот — длинный. Открывается только одна позиция за раз, как и в оригинале, где перед входом проверялось отсутствие активных ордеров с указанным MagicNumber.

Стоп-лосс и тейк-профит задаются в пунктах. При запуске стратегия вычисляет размер пункта, исходя из шага цены и количества знаков после запятой (для пяти- и трёхзнаковых котировок шаг умножается на десять), после чего переводит значения в абсолютное расстояние по цене и передаёт их в модуль защиты.

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

  • Источник данных: одна серия свечей, выбираемая параметром CandleType (по умолчанию H4).
  • Индикатор: настраиваемая скользящая средняя (SMA, EMA, SMMA, LWMA) с параметром MovingAverageShift, полностью повторяющим аргумент shift функции iMA из MetaTrader.
  • Правила входа:
    • Лонг: предыдущая свеча открылась ниже и закрылась выше сдвинутой средней, позиция отсутствует.
    • Шорт: предыдущая свеча открылась выше и закрылась ниже средней, позиция отсутствует.
  • Правила выхода: исполняются автоматически через StartProtection, куда передаются пересчитанные уровни стоп-лосса и тейк-профита. Даже при нулевых значениях модуль защиты включается, чтобы можно было подключить трейлинг или вручную закрывать сделки.
  • Фильтр по позиции: новые сигналы игнорируются до полного закрытия текущей позиции.

Параметры

Параметр Описание Значение по умолчанию
CandleType Тип свечей для расчёта сигналов. H4 (4-часовые свечи)
MovingAveragePeriod Длина окна скользящей средней. 49
MovingAverageShift Сдвиг значения скользящей средней вперёд. 0
MovingAverageMethod Тип средней (Simple, Exponential, Smoothed, LinearWeighted). Simple
TakeProfitPips Размер тейк-профита в пунктах, конвертируется в абсолютную цену. 38.5
StopLossPips Размер стоп-лосса в пунктах, конвертируется в абсолютную цену. 48.5

Управление рисками

Абсолютные уровни рассчитываются из пункта и автоматически прикрепляются к рыночным заявкам. Благодаря этому ограничения по минимальной дистанции до стопов соответствуют требованиям брокера, как и в версии MetaTrader.

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

  • Двухэтапная схема выставления ордеров (с последующей модификацией SL/TP) заменена на вызов BuyMarket()/SellMarket() с StartProtection, что упрощает код и достигает той же цели.
  • Проверки объёма и свободной маржи из функций CheckVolumeValue и CheckMoneyForTrade не переносятся. Рекомендуется использовать встроенные модули риск-менеджмента StockSharp.
  • Вместо сообщений в лог добавлено рисование свечей, индикатора и сделок в графике стратегии, что облегчает визуальный анализ.

Стратегия демонстрирует, как можно аккуратно перенести MQL-алгоритм на высокоуровневый API StockSharp и получить готовый шаблон для дальнейшего развития.

namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Basic MA Template strategy: trades when price crosses a moving average.
/// Opens long when previous candle crosses above MA, short when crosses below.
/// </summary>
public class BasicMaTemplateStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _maPeriod;

	private decimal? _prevOpen;
	private decimal? _prevClose;

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

	public BasicMaTemplateStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_maPeriod = Param(nameof(MaPeriod), 49)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "Moving average period", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevOpen = null;
		_prevClose = null;
		var sma = new SimpleMovingAverage { Length = MaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(sma, ProcessCandle).Start();
	}

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

		if (_prevOpen.HasValue && _prevClose.HasValue)
		{
			if (_prevOpen.Value > sma && _prevClose.Value < sma && Position >= 0)
				SellMarket();
			else if (_prevOpen.Value < sma && _prevClose.Value > sma && Position <= 0)
				BuyMarket();
		}

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